Annotation of qemu/roms/ipxe/src/drivers/net/epic100.c, revision 1.1

1.1     ! root        1: 
        !             2: /* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Etherboot */
        !             3: 
        !             4: FILE_LICENCE ( GPL2_OR_LATER );
        !             5: 
        !             6: /* 05/06/2003  timlegge        Fixed relocation and implemented Multicast */
        !             7: #define LINUX_OUT_MACROS
        !             8: 
        !             9: #include "etherboot.h"
        !            10: #include <ipxe/pci.h>
        !            11: #include <ipxe/ethernet.h>
        !            12: #include "nic.h"
        !            13: #include <ipxe/console.h>
        !            14: #include "epic100.h"
        !            15: 
        !            16: /* Condensed operations for readability */
        !            17: #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
        !            18: #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
        !            19: 
        !            20: #define TX_RING_SIZE   2       /* use at least 2 buffers for TX */
        !            21: #define RX_RING_SIZE   2
        !            22: 
        !            23: #define PKT_BUF_SZ     1536    /* Size of each temporary Tx/Rx buffer.*/
        !            24: 
        !            25: /*
        !            26: #define DEBUG_RX
        !            27: #define DEBUG_TX
        !            28: #define DEBUG_EEPROM
        !            29: */
        !            30: 
        !            31: #define EPIC_DEBUG 0   /* debug level */
        !            32: 
        !            33: /* The EPIC100 Rx and Tx buffer descriptors. */
        !            34: struct epic_rx_desc {
        !            35:     unsigned long status;
        !            36:     unsigned long bufaddr;
        !            37:     unsigned long buflength;
        !            38:     unsigned long next;
        !            39: };
        !            40: /* description of the tx descriptors control bits commonly used */
        !            41: #define TD_STDFLAGS    TD_LASTDESC
        !            42: 
        !            43: struct epic_tx_desc {
        !            44:     unsigned long status;
        !            45:     unsigned long bufaddr;
        !            46:     unsigned long buflength;
        !            47:     unsigned long  next;
        !            48: };
        !            49: 
        !            50: #define delay(nanosec)   do { int _i = 3; while (--_i > 0) \
        !            51:                                      { __SLOW_DOWN_IO; }} while (0)
        !            52: 
        !            53: static void    epic100_open(void);
        !            54: static void    epic100_init_ring(void);
        !            55: static void    epic100_disable(struct nic *nic);
        !            56: static int     epic100_poll(struct nic *nic, int retrieve);
        !            57: static void    epic100_transmit(struct nic *nic, const char *destaddr,
        !            58:                                 unsigned int type, unsigned int len, const char *data);
        !            59: #ifdef DEBUG_EEPROM
        !            60: static int     read_eeprom(int location);
        !            61: #endif
        !            62: static int     mii_read(int phy_id, int location);
        !            63: static void     epic100_irq(struct nic *nic, irq_action_t action);
        !            64: 
        !            65: static struct nic_operations epic100_operations;
        !            66: 
        !            67: static int     ioaddr;
        !            68: 
        !            69: static int     command;
        !            70: static int     intstat;
        !            71: static int     intmask;
        !            72: static int     genctl ;
        !            73: static int     eectl  ;
        !            74: static int     test   ;
        !            75: static int     mmctl  ;
        !            76: static int     mmdata ;
        !            77: static int     lan0   ;
        !            78: static int     mc0    ;
        !            79: static int     rxcon  ;
        !            80: static int     txcon  ;
        !            81: static int     prcdar ;
        !            82: static int     ptcdar ;
        !            83: static int     eththr ;
        !            84: 
        !            85: static unsigned int    cur_rx, cur_tx;         /* The next free ring entry */
        !            86: #ifdef DEBUG_EEPROM
        !            87: static unsigned short  eeprom[64];
        !            88: #endif
        !            89: static signed char     phys[4];                /* MII device addresses. */
        !            90: struct {
        !            91:        struct epic_rx_desc     rx_ring[RX_RING_SIZE]
        !            92:        __attribute__ ((aligned(4)));
        !            93:        struct epic_tx_desc     tx_ring[TX_RING_SIZE]
        !            94:        __attribute__ ((aligned(4)));
        !            95:        unsigned char           rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
        !            96:        unsigned char           tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
        !            97: } epic100_bufs __shared;
        !            98: #define rx_ring epic100_bufs.rx_ring
        !            99: #define tx_ring epic100_bufs.tx_ring
        !           100: #define rx_packet epic100_bufs.rx_packet
        !           101: #define tx_packet epic100_bufs.tx_packet
        !           102: 
        !           103: /***********************************************************************/
        !           104: /*                    Externally visible functions                     */
        !           105: /***********************************************************************/
        !           106: 
        !           107: 
        !           108: static int
        !           109: epic100_probe ( struct nic *nic, struct pci_device *pci ) {
        !           110: 
        !           111:     int i;
        !           112:     unsigned short* ap;
        !           113:     unsigned int phy, phy_idx;
        !           114: 
        !           115:     if (pci->ioaddr == 0)
        !           116:        return 0;
        !           117: 
        !           118:     /* Ideally we would detect all network cards in slot order.  That would
        !           119:        be best done a central PCI probe dispatch, which wouldn't work
        !           120:        well with the current structure.  So instead we detect just the
        !           121:        Epic cards in slot order. */
        !           122: 
        !           123:     ioaddr = pci->ioaddr;
        !           124: 
        !           125:     nic->irqno  = 0;
        !           126:     nic->ioaddr = pci->ioaddr & ~3;
        !           127: 
        !           128:     /* compute all used static epic100 registers address */
        !           129:     command = ioaddr + COMMAND;                /* Control Register */
        !           130:     intstat = ioaddr + INTSTAT;                /* Interrupt Status */
        !           131:     intmask = ioaddr + INTMASK;                /* Interrupt Mask */
        !           132:     genctl  = ioaddr + GENCTL;         /* General Control */
        !           133:     eectl   = ioaddr + EECTL;          /* EEPROM Control  */
        !           134:     test    = ioaddr + TEST;           /* Test register (clocks) */
        !           135:     mmctl   = ioaddr + MMCTL;          /* MII Management Interface Control */
        !           136:     mmdata  = ioaddr + MMDATA;         /* MII Management Interface Data */
        !           137:     lan0    = ioaddr + LAN0;           /* MAC address. (0x40-0x48) */
        !           138:     mc0     = ioaddr + MC0;            /* Multicast Control */
        !           139:     rxcon   = ioaddr + RXCON;          /* Receive Control */
        !           140:     txcon   = ioaddr + TXCON;          /* Transmit Control */
        !           141:     prcdar  = ioaddr + PRCDAR;         /* PCI Receive Current Descr Address */
        !           142:     ptcdar  = ioaddr + PTCDAR;         /* PCI Transmit Current Descr Address */
        !           143:     eththr  = ioaddr + ETHTHR;         /* Early Transmit Threshold */
        !           144: 
        !           145:     /* Reset the chip & bring it out of low-power mode. */
        !           146:     outl(GC_SOFT_RESET, genctl);
        !           147: 
        !           148:     /* Disable ALL interrupts by setting the interrupt mask. */
        !           149:     outl(INTR_DISABLE, intmask);
        !           150: 
        !           151:     /*
        !           152:      * set the internal clocks:
        !           153:      * Application Note 7.15 says:
        !           154:      *    In order to set the CLOCK TEST bit in the TEST register,
        !           155:      *   perform the following:
        !           156:      *
        !           157:      *        Write 0x0008 to the test register at least sixteen
        !           158:      *        consecutive times.
        !           159:      *
        !           160:      * The CLOCK TEST bit is Write-Only. Writing it several times
        !           161:      * consecutively insures a successful write to the bit...
        !           162:      */
        !           163: 
        !           164:     for (i = 0; i < 16; i++) {
        !           165:        outl(0x00000008, test);
        !           166:     }
        !           167: 
        !           168: #ifdef DEBUG_EEPROM
        !           169: {
        !           170:     unsigned short sum = 0;
        !           171:     unsigned short value;
        !           172:     for (i = 0; i < 64; i++) {
        !           173:        value = read_eeprom(i);
        !           174:        eeprom[i] = value;
        !           175:        sum += value;
        !           176:     }
        !           177: }
        !           178: 
        !           179: #if    (EPIC_DEBUG > 1)
        !           180:     printf("EEPROM contents\n");
        !           181:     for (i = 0; i < 64; i++) {
        !           182:        printf(" %hhX%s", eeprom[i], i % 16 == 15 ? "\n" : "");
        !           183:     }
        !           184: #endif
        !           185: #endif
        !           186: 
        !           187:     /* This could also be read from the EEPROM. */
        !           188:     ap = (unsigned short*)nic->node_addr;
        !           189:     for (i = 0; i < 3; i++)
        !           190:        *ap++ = inw(lan0 + i*4);
        !           191: 
        !           192:     DBG ( " I/O %4.4x %s ", ioaddr, eth_ntoa ( nic->node_addr ) );
        !           193: 
        !           194:     /* Find the connected MII xcvrs. */
        !           195:     for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) {
        !           196:        int mii_status = mii_read(phy, 0);
        !           197: 
        !           198:        if (mii_status != 0xffff  && mii_status != 0x0000) {
        !           199:            phys[phy_idx++] = phy;
        !           200: #if    (EPIC_DEBUG > 1)
        !           201:            printf("MII transceiver found at address %d.\n", phy);
        !           202: #endif
        !           203:        }
        !           204:     }
        !           205:     if (phy_idx == 0) {
        !           206: #if    (EPIC_DEBUG > 1)
        !           207:        printf("***WARNING***: No MII transceiver found!\n");
        !           208: #endif
        !           209:        /* Use the known PHY address of the EPII. */
        !           210:        phys[0] = 3;
        !           211:     }
        !           212: 
        !           213:     epic100_open();
        !           214:     nic->nic_op        = &epic100_operations;
        !           215: 
        !           216:     return 1;
        !           217: }
        !           218: 
        !           219: static void set_rx_mode(void)
        !           220: {
        !           221:        unsigned char mc_filter[8];
        !           222:        int i;
        !           223:        memset(mc_filter, 0xff, sizeof(mc_filter));
        !           224:        outl(0x0C, rxcon);
        !           225:        for(i = 0; i < 4; i++)
        !           226:                outw(((unsigned short *)mc_filter)[i], mc0 + i*4);
        !           227:        return;
        !           228: }
        !           229:        
        !           230:    static void
        !           231: epic100_open(void)
        !           232: {
        !           233:     int mii_reg5;
        !           234:     unsigned long tmp;
        !           235: 
        !           236:     epic100_init_ring();
        !           237: 
        !           238:     /* Pull the chip out of low-power mode, and set for PCI read multiple. */
        !           239:     outl(GC_RX_FIFO_THR_64 | GC_MRC_READ_MULT | GC_ONE_COPY, genctl);
        !           240: 
        !           241:     outl(TX_FIFO_THRESH, eththr);
        !           242: 
        !           243:     tmp = TC_EARLY_TX_ENABLE | TX_SLOT_TIME;
        !           244: 
        !           245:     mii_reg5 = mii_read(phys[0], 5);
        !           246:     if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
        !           247:        printf(" full-duplex mode");
        !           248:        tmp |= TC_LM_FULL_DPX;
        !           249:     } else
        !           250:        tmp |= TC_LM_NORMAL;
        !           251: 
        !           252:     outl(tmp, txcon);
        !           253: 
        !           254:     /* Give adress of RX and TX ring to the chip */
        !           255:     outl(virt_to_le32desc(&rx_ring), prcdar);
        !           256:     outl(virt_to_le32desc(&tx_ring), ptcdar);
        !           257: 
        !           258:     /* Start the chip's Rx process: receive unicast and broadcast */
        !           259:     set_rx_mode();
        !           260:     outl(CR_START_RX | CR_QUEUE_RX, command);
        !           261: 
        !           262:     putchar('\n');
        !           263: }
        !           264: 
        !           265: /* Initialize the Rx and Tx rings. */
        !           266:     static void
        !           267: epic100_init_ring(void)
        !           268: {
        !           269:     int i;
        !           270: 
        !           271:     cur_rx = cur_tx = 0;
        !           272: 
        !           273:     for (i = 0; i < RX_RING_SIZE; i++) {
        !           274:        rx_ring[i].status    = cpu_to_le32(RRING_OWN);  /* Owned by Epic chip */
        !           275:        rx_ring[i].buflength = cpu_to_le32(PKT_BUF_SZ);
        !           276:        rx_ring[i].bufaddr   = virt_to_bus(&rx_packet[i * PKT_BUF_SZ]);
        !           277:        rx_ring[i].next      = virt_to_le32desc(&rx_ring[i + 1]) ;
        !           278:     }
        !           279:     /* Mark the last entry as wrapping the ring. */
        !           280:     rx_ring[i-1].next = virt_to_le32desc(&rx_ring[0]);
        !           281: 
        !           282:     /*
        !           283:      *The Tx buffer descriptor is filled in as needed,
        !           284:      * but we do need to clear the ownership bit.
        !           285:      */
        !           286: 
        !           287:     for (i = 0; i < TX_RING_SIZE; i++) {
        !           288:        tx_ring[i].status  = 0x0000;                    /* Owned by CPU */
        !           289:        tx_ring[i].buflength = 0x0000 | cpu_to_le32(TD_STDFLAGS << 16);
        !           290:        tx_ring[i].bufaddr = virt_to_bus(&tx_packet[i * PKT_BUF_SZ]);
        !           291:        tx_ring[i].next    = virt_to_le32desc(&tx_ring[i + 1]);
        !           292:     }
        !           293:        tx_ring[i-1].next    = virt_to_le32desc(&tx_ring[0]);
        !           294: }
        !           295: 
        !           296: /* function: epic100_transmit
        !           297:  * This transmits a packet.
        !           298:  *
        !           299:  * Arguments: char d[6]:          destination ethernet address.
        !           300:  *            unsigned short t:   ethernet protocol type.
        !           301:  *            unsigned short s:   size of the data-part of the packet.
        !           302:  *            char *p:            the data for the packet.
        !           303:  * returns:   void.
        !           304:  */
        !           305:     static void
        !           306: epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
        !           307:                 unsigned int len, const char *data)
        !           308: {
        !           309:     unsigned short nstype;
        !           310:     unsigned char *txp;
        !           311:     int entry;
        !           312:     unsigned long ct;
        !           313: 
        !           314:     /* Calculate the next Tx descriptor entry. */
        !           315:     entry = cur_tx % TX_RING_SIZE;
        !           316: 
        !           317:     if ((tx_ring[entry].status & TRING_OWN) == TRING_OWN) {
        !           318:        printf("eth_transmit: Unable to transmit. status=%4.4lx. Resetting...\n",
        !           319:               tx_ring[entry].status);
        !           320: 
        !           321:        epic100_open();
        !           322:        return;
        !           323:     }
        !           324: 
        !           325:     txp = tx_packet + (entry * PKT_BUF_SZ);
        !           326: 
        !           327:     memcpy(txp, destaddr, ETH_ALEN);
        !           328:     memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
        !           329:     nstype = htons(type);
        !           330:     memcpy(txp + 12, (char*)&nstype, 2);
        !           331:     memcpy(txp + ETH_HLEN, data, len);
        !           332: 
        !           333:     len += ETH_HLEN;
        !           334:        len &= 0x0FFF;
        !           335:        while(len < ETH_ZLEN)
        !           336:                txp[len++] = '\0';
        !           337:     /*
        !           338:      * Caution: the write order is important here,
        !           339:      * set the base address with the "ownership"
        !           340:      * bits last.
        !           341:      */
        !           342:    
        !           343:     tx_ring[entry].buflength |= cpu_to_le32(len);
        !           344:     tx_ring[entry].status = cpu_to_le32(len << 16) |
        !           345:            cpu_to_le32(TRING_OWN);     /* Pass ownership to the chip. */
        !           346: 
        !           347:     cur_tx++;
        !           348: 
        !           349:     /* Trigger an immediate transmit demand. */
        !           350:     outl(CR_QUEUE_TX, command);
        !           351: 
        !           352:     ct = currticks();
        !           353:     /* timeout 10 ms for transmit */
        !           354:     while ((le32_to_cpu(tx_ring[entry].status) & (TRING_OWN)) &&
        !           355:                ct + 10*1000 < currticks())
        !           356:        /* Wait */;
        !           357: 
        !           358:     if ((le32_to_cpu(tx_ring[entry].status) & TRING_OWN) != 0)
        !           359:        printf("Oops, transmitter timeout, status=%4.4lX\n",
        !           360:            tx_ring[entry].status);
        !           361: }
        !           362: 
        !           363: /* function: epic100_poll / eth_poll
        !           364:  * This receives a packet from the network.
        !           365:  *
        !           366:  * Arguments: none
        !           367:  *
        !           368:  * returns:   1 if a packet was received.
        !           369:  *            0 if no pacet was received.
        !           370:  * side effects:
        !           371:  *            returns the packet in the array nic->packet.
        !           372:  *            returns the length of the packet in nic->packetlen.
        !           373:  */
        !           374: 
        !           375:     static int
        !           376: epic100_poll(struct nic *nic, int retrieve)
        !           377: {
        !           378:     int entry;
        !           379:     int retcode;
        !           380:     int status;
        !           381:     entry = cur_rx % RX_RING_SIZE;
        !           382: 
        !           383:     if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN)
        !           384:        return (0);
        !           385: 
        !           386:     if ( ! retrieve ) return 1;
        !           387: 
        !           388:     status = le32_to_cpu(rx_ring[entry].status);
        !           389:     /* We own the next entry, it's a new packet. Send it up. */
        !           390: 
        !           391: #if    (EPIC_DEBUG > 4)
        !           392:     printf("epic_poll: entry %d status %hX\n", entry, status);
        !           393: #endif
        !           394: 
        !           395:     cur_rx++;
        !           396:     if (status & 0x2000) {
        !           397:        printf("epic_poll: Giant packet\n");
        !           398:        retcode = 0;
        !           399:     } else if (status & 0x0006) {
        !           400:        /* Rx Frame errors are counted in hardware. */
        !           401:        printf("epic_poll: Frame received with errors\n");
        !           402:        retcode = 0;
        !           403:     } else {
        !           404:        /* Omit the four octet CRC from the length. */
        !           405:        nic->packetlen = le32_to_cpu((rx_ring[entry].buflength))- 4;
        !           406:        memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen);
        !           407:        retcode = 1;
        !           408:     }
        !           409: 
        !           410:     /* Clear all error sources. */
        !           411:     outl(status & INTR_CLEARERRS, intstat);
        !           412: 
        !           413:     /* Give the descriptor back to the chip */
        !           414:     rx_ring[entry].status = RRING_OWN;
        !           415: 
        !           416:     /* Restart Receiver */
        !           417:     outl(CR_START_RX | CR_QUEUE_RX, command); 
        !           418: 
        !           419:     return retcode;
        !           420: }
        !           421: 
        !           422: 
        !           423: static void epic100_disable ( struct nic *nic __unused ) {
        !           424:        /* Soft reset the chip. */
        !           425:        outl(GC_SOFT_RESET, genctl);
        !           426: }
        !           427: 
        !           428: static void epic100_irq(struct nic *nic __unused, irq_action_t action __unused)
        !           429: {
        !           430:   switch ( action ) {
        !           431:   case DISABLE :
        !           432:     break;
        !           433:   case ENABLE :
        !           434:     break;
        !           435:   case FORCE :
        !           436:     break;
        !           437:   }
        !           438: }
        !           439: 
        !           440: #ifdef DEBUG_EEPROM
        !           441: /* Serial EEPROM section. */
        !           442: 
        !           443: /*  EEPROM_Ctrl bits. */
        !           444: #define EE_SHIFT_CLK   0x04    /* EEPROM shift clock. */
        !           445: #define EE_CS          0x02    /* EEPROM chip select. */
        !           446: #define EE_DATA_WRITE  0x08    /* EEPROM chip data in. */
        !           447: #define EE_WRITE_0     0x01
        !           448: #define EE_WRITE_1     0x09
        !           449: #define EE_DATA_READ   0x10    /* EEPROM chip data out. */
        !           450: #define EE_ENB         (0x0001 | EE_CS)
        !           451: 
        !           452: /* The EEPROM commands include the alway-set leading bit. */
        !           453: #define EE_WRITE_CMD   (5 << 6)
        !           454: #define EE_READ_CMD    (6 << 6)
        !           455: #define EE_ERASE_CMD   (7 << 6)
        !           456: 
        !           457: #define eeprom_delay(n)        delay(n)
        !           458: 
        !           459:     static int
        !           460: read_eeprom(int location)
        !           461: {
        !           462:     int i;
        !           463:     int retval = 0;
        !           464:     int read_cmd = location | EE_READ_CMD;
        !           465: 
        !           466:     outl(EE_ENB & ~EE_CS, eectl);
        !           467:     outl(EE_ENB, eectl);
        !           468: 
        !           469:     /* Shift the read command bits out. */
        !           470:     for (i = 10; i >= 0; i--) {
        !           471:        short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
        !           472:        outl(EE_ENB | dataval, eectl);
        !           473:        eeprom_delay(100);
        !           474:        outl(EE_ENB | dataval | EE_SHIFT_CLK, eectl);
        !           475:        eeprom_delay(150);
        !           476:        outl(EE_ENB | dataval, eectl);  /* Finish EEPROM a clock tick. */
        !           477:        eeprom_delay(250);
        !           478:     }
        !           479:     outl(EE_ENB, eectl);
        !           480: 
        !           481:     for (i = 16; i > 0; i--) {
        !           482:        outl(EE_ENB | EE_SHIFT_CLK, eectl);
        !           483:        eeprom_delay(100);
        !           484:        retval = (retval << 1) | ((inl(eectl) & EE_DATA_READ) ? 1 : 0);
        !           485:        outl(EE_ENB, eectl);
        !           486:        eeprom_delay(100);
        !           487:     }
        !           488: 
        !           489:     /* Terminate the EEPROM access. */
        !           490:     outl(EE_ENB & ~EE_CS, eectl);
        !           491:     return retval;
        !           492: }
        !           493: #endif
        !           494: 
        !           495: 
        !           496: #define MII_READOP     1
        !           497: #define MII_WRITEOP    2
        !           498: 
        !           499:     static int
        !           500: mii_read(int phy_id, int location)
        !           501: {
        !           502:     int i;
        !           503: 
        !           504:     outl((phy_id << 9) | (location << 4) | MII_READOP, mmctl);
        !           505:     /* Typical operation takes < 50 ticks. */
        !           506: 
        !           507:     for (i = 4000; i > 0; i--)
        !           508:        if ((inl(mmctl) & MII_READOP) == 0)
        !           509:            break;
        !           510:     return inw(mmdata);
        !           511: }
        !           512: 
        !           513: static struct nic_operations epic100_operations = {
        !           514:        .connect        = dummy_connect,
        !           515:        .poll           = epic100_poll,
        !           516:        .transmit       = epic100_transmit,
        !           517:        .irq            = epic100_irq,
        !           518: 
        !           519: };
        !           520: 
        !           521: static struct pci_device_id epic100_nics[] = {
        !           522: PCI_ROM(0x10b8, 0x0005, "epic100",    "SMC EtherPowerII", 0),          /* SMC 83c170 EPIC/100 */
        !           523: PCI_ROM(0x10b8, 0x0006, "smc-83c175", "SMC EPIC/C 83c175", 0),
        !           524: };
        !           525: 
        !           526: PCI_DRIVER ( epic100_driver, epic100_nics, PCI_NO_CLASS );
        !           527: 
        !           528: DRIVER ( "EPIC100", nic_driver, pci_driver, epic100_driver,
        !           529:         epic100_probe, epic100_disable );
        !           530: 
        !           531: /*
        !           532:  * Local variables:
        !           533:  *  c-basic-offset: 8
        !           534:  *  c-indent-level: 8
        !           535:  *  tab-width: 8
        !           536:  * End:
        !           537:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.