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

1.1     ! root        1: /**************************************************************************
        !             2: *    ns83820.c: Etherboot device driver for the National Semiconductor 83820
        !             3: *    Written 2004 by Timothy Legge <[email protected]>
        !             4: *
        !             5: *    This program is free software; you can redistribute it and/or modify
        !             6: *    it under the terms of the GNU General Public License as published by
        !             7: *    the Free Software Foundation; either version 2 of the License, or
        !             8: *    (at your option) any later version.
        !             9: *
        !            10: *    This program is distributed in the hope that it will be useful,
        !            11: *    but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12: *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            13: *    GNU General Public License for more details.
        !            14: *
        !            15: *    You should have received a copy of the GNU General Public License
        !            16: *    along with this program; if not, write to the Free Software
        !            17: *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            18: *
        !            19: *    Portions of this code based on:
        !            20: *      ns83820.c by Benjamin LaHaise with contributions
        !            21: *              for Linux kernel 2.4.x.
        !            22: *      
        !            23: *    Linux Driver Version 0.20, 20020610
        !            24: * 
        !            25: *    This development of this Etherboot driver was funded by:
        !            26: *
        !            27: *    NXTV: http://www.nxtv.com/
        !            28: *      
        !            29: *    REVISION HISTORY:
        !            30: *    ================
        !            31: *
        !            32: *    v1.0      02-16-2004      timlegge        Initial port of Linux driver
        !            33: *    v1.1      02-19-2004      timlegge        More rohbust transmit and poll
        !            34: *    
        !            35: *    Indent Options: indent -kr -i8
        !            36: ***************************************************************************/
        !            37: 
        !            38: FILE_LICENCE ( GPL2_OR_LATER );
        !            39: 
        !            40: /* to get some global routines like printf */
        !            41: #include "etherboot.h"
        !            42: /* to get the interface to the body of the program */
        !            43: #include "nic.h"
        !            44: /* to get the PCI support functions, if this is a PCI NIC */
        !            45: #include <ipxe/pci.h>
        !            46: 
        !            47: #if ARCH == ia64               /* Support 64-bit addressing */
        !            48: #define USE_64BIT_ADDR
        !            49: #endif
        !            50: 
        !            51: #define HZ 100
        !            52: 
        !            53: /* Condensed operations for readability. */
        !            54: #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
        !            55: #define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
        !            56: 
        !            57: /* NIC specific static variables go here */
        !            58: 
        !            59: /* Global parameters.  See MODULE_PARM near the bottom. */
        !            60: // static int ihr = 2;
        !            61: static int reset_phy = 0;
        !            62: static int lnksts = 0;         /* CFG_LNKSTS bit polarity */
        !            63: 
        !            64: #if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)
        !            65: #define USE_64BIT_ADDR "+"
        !            66: #endif
        !            67: 
        !            68: #if defined(USE_64BIT_ADDR)
        !            69: #define TRY_DAC        1
        !            70: #else
        !            71: #define TRY_DAC        0
        !            72: #endif
        !            73: 
        !            74: /* tunables */
        !            75: #define RX_BUF_SIZE    1500    /* 8192 */
        !            76: 
        !            77: /* Must not exceed ~65000. */
        !            78: #define NR_RX_DESC     64
        !            79: #define NR_TX_DESC     1
        !            80: 
        !            81:                   /* not tunable *//* Extra 6 bytes for 64 bit alignment (divisable by 8) */
        !            82: #define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14 + 6)        /* rx/tx mac addr + type */
        !            83: 
        !            84: #define MIN_TX_DESC_FREE       8
        !            85: 
        !            86: /* register defines */
        !            87: #define CFGCS          0x04
        !            88: 
        !            89: #define CR_TXE         0x00000001
        !            90: #define CR_TXD         0x00000002
        !            91: /* Ramit : Here's a tip, don't do a RXD immediately followed by an RXE
        !            92:  * The Receive engine skips one descriptor and moves
        !            93:  * onto the next one!! */
        !            94: #define CR_RXE         0x00000004
        !            95: #define CR_RXD         0x00000008
        !            96: #define CR_TXR         0x00000010
        !            97: #define CR_RXR         0x00000020
        !            98: #define CR_SWI         0x00000080
        !            99: #define CR_RST         0x00000100
        !           100: 
        !           101: #define PTSCR_EEBIST_FAIL       0x00000001
        !           102: #define PTSCR_EEBIST_EN         0x00000002
        !           103: #define PTSCR_EELOAD_EN         0x00000004
        !           104: #define PTSCR_RBIST_FAIL        0x000001b8
        !           105: #define PTSCR_RBIST_DONE        0x00000200
        !           106: #define PTSCR_RBIST_EN          0x00000400
        !           107: #define PTSCR_RBIST_RST         0x00002000
        !           108: 
        !           109: #define MEAR_EEDI              0x00000001
        !           110: #define MEAR_EEDO              0x00000002
        !           111: #define MEAR_EECLK             0x00000004
        !           112: #define MEAR_EESEL             0x00000008
        !           113: #define MEAR_MDIO              0x00000010
        !           114: #define MEAR_MDDIR             0x00000020
        !           115: #define MEAR_MDC               0x00000040
        !           116: 
        !           117: #define ISR_TXDESC3    0x40000000
        !           118: #define ISR_TXDESC2    0x20000000
        !           119: #define ISR_TXDESC1    0x10000000
        !           120: #define ISR_TXDESC0    0x08000000
        !           121: #define ISR_RXDESC3    0x04000000
        !           122: #define ISR_RXDESC2    0x02000000
        !           123: #define ISR_RXDESC1    0x01000000
        !           124: #define ISR_RXDESC0    0x00800000
        !           125: #define ISR_TXRCMP     0x00400000
        !           126: #define ISR_RXRCMP     0x00200000
        !           127: #define ISR_DPERR      0x00100000
        !           128: #define ISR_SSERR      0x00080000
        !           129: #define ISR_RMABT      0x00040000
        !           130: #define ISR_RTABT      0x00020000
        !           131: #define ISR_RXSOVR     0x00010000
        !           132: #define ISR_HIBINT     0x00008000
        !           133: #define ISR_PHY                0x00004000
        !           134: #define ISR_PME                0x00002000
        !           135: #define ISR_SWI                0x00001000
        !           136: #define ISR_MIB                0x00000800
        !           137: #define ISR_TXURN      0x00000400
        !           138: #define ISR_TXIDLE     0x00000200
        !           139: #define ISR_TXERR      0x00000100
        !           140: #define ISR_TXDESC     0x00000080
        !           141: #define ISR_TXOK       0x00000040
        !           142: #define ISR_RXORN      0x00000020
        !           143: #define ISR_RXIDLE     0x00000010
        !           144: #define ISR_RXEARLY    0x00000008
        !           145: #define ISR_RXERR      0x00000004
        !           146: #define ISR_RXDESC     0x00000002
        !           147: #define ISR_RXOK       0x00000001
        !           148: 
        !           149: #define TXCFG_CSI      0x80000000
        !           150: #define TXCFG_HBI      0x40000000
        !           151: #define TXCFG_MLB      0x20000000
        !           152: #define TXCFG_ATP      0x10000000
        !           153: #define TXCFG_ECRETRY  0x00800000
        !           154: #define TXCFG_BRST_DIS 0x00080000
        !           155: #define TXCFG_MXDMA1024        0x00000000
        !           156: #define TXCFG_MXDMA512 0x00700000
        !           157: #define TXCFG_MXDMA256 0x00600000
        !           158: #define TXCFG_MXDMA128 0x00500000
        !           159: #define TXCFG_MXDMA64  0x00400000
        !           160: #define TXCFG_MXDMA32  0x00300000
        !           161: #define TXCFG_MXDMA16  0x00200000
        !           162: #define TXCFG_MXDMA8   0x00100000
        !           163: 
        !           164: #define CFG_LNKSTS     0x80000000
        !           165: #define CFG_SPDSTS     0x60000000
        !           166: #define CFG_SPDSTS1    0x40000000
        !           167: #define CFG_SPDSTS0    0x20000000
        !           168: #define CFG_DUPSTS     0x10000000
        !           169: #define CFG_TBI_EN     0x01000000
        !           170: #define CFG_MODE_1000  0x00400000
        !           171: /* Ramit : Dont' ever use AUTO_1000, it never works and is buggy.
        !           172:  * Read the Phy response and then configure the MAC accordingly */
        !           173: #define CFG_AUTO_1000  0x00200000
        !           174: #define CFG_PINT_CTL   0x001c0000
        !           175: #define CFG_PINT_DUPSTS        0x00100000
        !           176: #define CFG_PINT_LNKSTS        0x00080000
        !           177: #define CFG_PINT_SPDSTS        0x00040000
        !           178: #define CFG_TMRTEST    0x00020000
        !           179: #define CFG_MRM_DIS    0x00010000
        !           180: #define CFG_MWI_DIS    0x00008000
        !           181: #define CFG_T64ADDR    0x00004000
        !           182: #define CFG_PCI64_DET  0x00002000
        !           183: #define CFG_DATA64_EN  0x00001000
        !           184: #define CFG_M64ADDR    0x00000800
        !           185: #define CFG_PHY_RST    0x00000400
        !           186: #define CFG_PHY_DIS    0x00000200
        !           187: #define CFG_EXTSTS_EN  0x00000100
        !           188: #define CFG_REQALG     0x00000080
        !           189: #define CFG_SB         0x00000040
        !           190: #define CFG_POW                0x00000020
        !           191: #define CFG_EXD                0x00000010
        !           192: #define CFG_PESEL      0x00000008
        !           193: #define CFG_BROM_DIS   0x00000004
        !           194: #define CFG_EXT_125    0x00000002
        !           195: #define CFG_BEM                0x00000001
        !           196: 
        !           197: #define EXTSTS_UDPPKT  0x00200000
        !           198: #define EXTSTS_TCPPKT  0x00080000
        !           199: #define EXTSTS_IPPKT   0x00020000
        !           200: 
        !           201: #define SPDSTS_POLARITY        (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0))
        !           202: 
        !           203: #define MIBC_MIBS      0x00000008
        !           204: #define MIBC_ACLR      0x00000004
        !           205: #define MIBC_FRZ       0x00000002
        !           206: #define MIBC_WRN       0x00000001
        !           207: 
        !           208: #define PCR_PSEN       (1 << 31)
        !           209: #define PCR_PS_MCAST   (1 << 30)
        !           210: #define PCR_PS_DA      (1 << 29)
        !           211: #define PCR_STHI_8     (3 << 23)
        !           212: #define PCR_STLO_4     (1 << 23)
        !           213: #define PCR_FFHI_8K    (3 << 21)
        !           214: #define PCR_FFLO_4K    (1 << 21)
        !           215: #define PCR_PAUSE_CNT  0xFFFE
        !           216: 
        !           217: #define RXCFG_AEP      0x80000000
        !           218: #define RXCFG_ARP      0x40000000
        !           219: #define RXCFG_STRIPCRC 0x20000000
        !           220: #define RXCFG_RX_FD    0x10000000
        !           221: #define RXCFG_ALP      0x08000000
        !           222: #define RXCFG_AIRL     0x04000000
        !           223: #define RXCFG_MXDMA512 0x00700000
        !           224: #define RXCFG_DRTH     0x0000003e
        !           225: #define RXCFG_DRTH0    0x00000002
        !           226: 
        !           227: #define RFCR_RFEN      0x80000000
        !           228: #define RFCR_AAB       0x40000000
        !           229: #define RFCR_AAM       0x20000000
        !           230: #define RFCR_AAU       0x10000000
        !           231: #define RFCR_APM       0x08000000
        !           232: #define RFCR_APAT      0x07800000
        !           233: #define RFCR_APAT3     0x04000000
        !           234: #define RFCR_APAT2     0x02000000
        !           235: #define RFCR_APAT1     0x01000000
        !           236: #define RFCR_APAT0     0x00800000
        !           237: #define RFCR_AARP      0x00400000
        !           238: #define RFCR_MHEN      0x00200000
        !           239: #define RFCR_UHEN      0x00100000
        !           240: #define RFCR_ULM       0x00080000
        !           241: 
        !           242: #define VRCR_RUDPE     0x00000080
        !           243: #define VRCR_RTCPE     0x00000040
        !           244: #define VRCR_RIPE      0x00000020
        !           245: #define VRCR_IPEN      0x00000010
        !           246: #define VRCR_DUTF      0x00000008
        !           247: #define VRCR_DVTF      0x00000004
        !           248: #define VRCR_VTREN     0x00000002
        !           249: #define VRCR_VTDEN     0x00000001
        !           250: 
        !           251: #define VTCR_PPCHK     0x00000008
        !           252: #define VTCR_GCHK      0x00000004
        !           253: #define VTCR_VPPTI     0x00000002
        !           254: #define VTCR_VGTI      0x00000001
        !           255: 
        !           256: #define CR             0x00
        !           257: #define CFG            0x04
        !           258: #define MEAR           0x08
        !           259: #define PTSCR          0x0c
        !           260: #define        ISR             0x10
        !           261: #define        IMR             0x14
        !           262: #define        IER             0x18
        !           263: #define        IHR             0x1c
        !           264: #define TXDP           0x20
        !           265: #define TXDP_HI                0x24
        !           266: #define TXCFG          0x28
        !           267: #define GPIOR          0x2c
        !           268: #define RXDP           0x30
        !           269: #define RXDP_HI                0x34
        !           270: #define RXCFG          0x38
        !           271: #define PQCR           0x3c
        !           272: #define WCSR           0x40
        !           273: #define PCR            0x44
        !           274: #define RFCR           0x48
        !           275: #define RFDR           0x4c
        !           276: 
        !           277: #define SRR            0x58
        !           278: 
        !           279: #define VRCR           0xbc
        !           280: #define VTCR           0xc0
        !           281: #define VDR            0xc4
        !           282: #define CCSR           0xcc
        !           283: 
        !           284: #define TBICR          0xe0
        !           285: #define TBISR          0xe4
        !           286: #define TANAR          0xe8
        !           287: #define TANLPAR                0xec
        !           288: #define TANER          0xf0
        !           289: #define TESR           0xf4
        !           290: 
        !           291: #define TBICR_MR_AN_ENABLE     0x00001000
        !           292: #define TBICR_MR_RESTART_AN    0x00000200
        !           293: 
        !           294: #define TBISR_MR_LINK_STATUS   0x00000020
        !           295: #define TBISR_MR_AN_COMPLETE   0x00000004
        !           296: 
        !           297: #define TANAR_PS2              0x00000100
        !           298: #define TANAR_PS1              0x00000080
        !           299: #define TANAR_HALF_DUP                 0x00000040
        !           300: #define TANAR_FULL_DUP                 0x00000020
        !           301: 
        !           302: #define GPIOR_GP5_OE           0x00000200
        !           303: #define GPIOR_GP4_OE           0x00000100
        !           304: #define GPIOR_GP3_OE           0x00000080
        !           305: #define GPIOR_GP2_OE           0x00000040
        !           306: #define GPIOR_GP1_OE           0x00000020
        !           307: #define GPIOR_GP3_OUT          0x00000004
        !           308: #define GPIOR_GP1_OUT          0x00000001
        !           309: 
        !           310: #define LINK_AUTONEGOTIATE     0x01
        !           311: #define LINK_DOWN              0x02
        !           312: #define LINK_UP                        0x04
        !           313: 
        !           314: 
        !           315: #define __kick_rx()    writel(CR_RXE, ns->base + CR)
        !           316: 
        !           317: #define kick_rx() do { \
        !           318:        DBG("kick_rx: maybe kicking\n"); \
        !           319:                writel(virt_to_le32desc(&rx_ring[ns->cur_rx]), ns->base + RXDP); \
        !           320:                if (ns->next_rx == ns->next_empty) \
        !           321:                        printf("uh-oh: next_rx == next_empty???\n"); \
        !           322:                __kick_rx(); \
        !           323: } while(0)
        !           324: 
        !           325: 
        !           326: #ifdef USE_64BIT_ADDR
        !           327: #define HW_ADDR_LEN    8
        !           328: #else
        !           329: #define HW_ADDR_LEN    4
        !           330: #endif
        !           331: 
        !           332: #define CMDSTS_OWN     0x80000000
        !           333: #define CMDSTS_MORE    0x40000000
        !           334: #define CMDSTS_INTR    0x20000000
        !           335: #define CMDSTS_ERR     0x10000000
        !           336: #define CMDSTS_OK      0x08000000
        !           337: #define CMDSTS_LEN_MASK        0x0000ffff
        !           338: 
        !           339: #define CMDSTS_DEST_MASK       0x01800000
        !           340: #define CMDSTS_DEST_SELF       0x00800000
        !           341: #define CMDSTS_DEST_MULTI      0x01000000
        !           342: 
        !           343: #define DESC_SIZE      8       /* Should be cache line sized */
        !           344: 
        !           345: #ifdef USE_64BIT_ADDR
        !           346: struct ring_desc {
        !           347:        uint64_t link;
        !           348:        uint64_t bufptr;
        !           349:        u32 cmdsts;
        !           350:        u32 extsts;             /* Extended status field */
        !           351: };
        !           352: #else
        !           353: struct ring_desc {
        !           354:        u32 link;
        !           355:        u32 bufptr;
        !           356:        u32 cmdsts;
        !           357:        u32 extsts;             /* Extended status field */
        !           358: };
        !           359: #endif
        !           360: 
        !           361: /* Private Storage for the NIC */
        !           362: static struct ns83820_private {
        !           363:        u8 *base;
        !           364:        int up;
        !           365:        long idle;
        !           366:        u32 *next_rx_desc;
        !           367:        u16 next_rx, next_empty;
        !           368:        u32 cur_rx;
        !           369:        u32 *descs;
        !           370:        unsigned ihr;
        !           371:        u32 CFG_cache;
        !           372:        u32 MEAR_cache;
        !           373:        u32 IMR_cache;
        !           374:        int linkstate;
        !           375:        u16 tx_done_idx;
        !           376:        u16 tx_idx;
        !           377:        u16 tx_intr_idx;
        !           378:        u32 phy_descs;
        !           379:        u32 *tx_descs;
        !           380: 
        !           381: } nsx;
        !           382: static struct ns83820_private *ns;
        !           383: 
        !           384: /* Define the TX and RX Descriptor and Buffers */
        !           385: struct {
        !           386:        struct ring_desc tx_ring[NR_TX_DESC] __attribute__ ((aligned(8)));
        !           387:        unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE];
        !           388:        struct ring_desc rx_ring[NR_RX_DESC] __attribute__ ((aligned(8)));
        !           389:        unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE]
        !           390:        __attribute__ ((aligned(8)));
        !           391: } ns83820_bufs __shared;
        !           392: #define tx_ring ns83820_bufs.tx_ring
        !           393: #define rx_ring ns83820_bufs.rx_ring
        !           394: #define txb ns83820_bufs.txb
        !           395: #define rxb ns83820_bufs.rxb
        !           396: 
        !           397: static void phy_intr(struct nic *nic __unused)
        !           398: {
        !           399:        static char *speeds[] =
        !           400:            { "10", "100", "1000", "1000(?)", "1000F" };
        !           401:        u32 cfg, new_cfg;
        !           402:        u32 tbisr, tanar, tanlpar;
        !           403:        int speed, fullduplex, newlinkstate;
        !           404: 
        !           405:        cfg = readl(ns->base + CFG) ^ SPDSTS_POLARITY;
        !           406:        if (ns->CFG_cache & CFG_TBI_EN) {
        !           407:                /* we have an optical transceiver */
        !           408:                tbisr = readl(ns->base + TBISR);
        !           409:                tanar = readl(ns->base + TANAR);
        !           410:                tanlpar = readl(ns->base + TANLPAR);
        !           411:                DBG("phy_intr: tbisr=%hX, tanar=%hX, tanlpar=%hX\n",
        !           412:                    tbisr, tanar, tanlpar);
        !           413: 
        !           414:                if ((fullduplex = (tanlpar & TANAR_FULL_DUP)
        !           415:                     && (tanar & TANAR_FULL_DUP))) {
        !           416: 
        !           417:                        /* both of us are full duplex */
        !           418:                        writel(readl(ns->base + TXCFG)
        !           419:                               | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,
        !           420:                               ns->base + TXCFG);
        !           421:                        writel(readl(ns->base + RXCFG) | RXCFG_RX_FD,
        !           422:                               ns->base + RXCFG);
        !           423:                        /* Light up full duplex LED */
        !           424:                        writel(readl(ns->base + GPIOR) | GPIOR_GP1_OUT,
        !           425:                               ns->base + GPIOR);
        !           426: 
        !           427:                } else if (((tanlpar & TANAR_HALF_DUP)
        !           428:                            && (tanar & TANAR_HALF_DUP))
        !           429:                           || ((tanlpar & TANAR_FULL_DUP)
        !           430:                               && (tanar & TANAR_HALF_DUP))
        !           431:                           || ((tanlpar & TANAR_HALF_DUP)
        !           432:                               && (tanar & TANAR_FULL_DUP))) {
        !           433: 
        !           434:                        /* one or both of us are half duplex */
        !           435:                        writel((readl(ns->base + TXCFG)
        !           436:                                & ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP,
        !           437:                               ns->base + TXCFG);
        !           438:                        writel(readl(ns->base + RXCFG) & ~RXCFG_RX_FD,
        !           439:                               ns->base + RXCFG);
        !           440:                        /* Turn off full duplex LED */
        !           441:                        writel(readl(ns->base + GPIOR) & ~GPIOR_GP1_OUT,
        !           442:                               ns->base + GPIOR);
        !           443:                }
        !           444: 
        !           445:                speed = 4;      /* 1000F */
        !           446: 
        !           447:        } else {
        !           448:                /* we have a copper transceiver */
        !           449:                new_cfg =
        !           450:                    ns->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
        !           451: 
        !           452:                if (cfg & CFG_SPDSTS1)
        !           453:                        new_cfg |= CFG_MODE_1000;
        !           454:                else
        !           455:                        new_cfg &= ~CFG_MODE_1000;
        !           456: 
        !           457:                speed = ((cfg / CFG_SPDSTS0) & 3);
        !           458:                fullduplex = (cfg & CFG_DUPSTS);
        !           459: 
        !           460:                if (fullduplex)
        !           461:                        new_cfg |= CFG_SB;
        !           462: 
        !           463:                if ((cfg & CFG_LNKSTS) &&
        !           464:                    ((new_cfg ^ ns->CFG_cache) & CFG_MODE_1000)) {
        !           465:                        writel(new_cfg, ns->base + CFG);
        !           466:                        ns->CFG_cache = new_cfg;
        !           467:                }
        !           468: 
        !           469:                ns->CFG_cache &= ~CFG_SPDSTS;
        !           470:                ns->CFG_cache |= cfg & CFG_SPDSTS;
        !           471:        }
        !           472: 
        !           473:        newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN;
        !           474: 
        !           475:        if (newlinkstate & LINK_UP && ns->linkstate != newlinkstate) {
        !           476:                printf("link now %s mbps, %s duplex and up.\n",
        !           477:                       speeds[speed], fullduplex ? "full" : "half");
        !           478:        } else if (newlinkstate & LINK_DOWN
        !           479:                   && ns->linkstate != newlinkstate) {
        !           480:                printf("link now down.\n");
        !           481:        }
        !           482:        ns->linkstate = newlinkstate;
        !           483: }
        !           484: static void ns83820_set_multicast(struct nic *nic __unused);
        !           485: static void ns83820_setup_rx(struct nic *nic)
        !           486: {
        !           487:        unsigned i;
        !           488:        ns->idle = 1;
        !           489:        ns->next_rx = 0;
        !           490:        ns->next_rx_desc = ns->descs;
        !           491:        ns->next_empty = 0;
        !           492:        ns->cur_rx = 0;
        !           493: 
        !           494: 
        !           495:        for (i = 0; i < NR_RX_DESC; i++) {
        !           496:                rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);
        !           497:                rx_ring[i].bufptr =
        !           498:                    virt_to_le32desc(&rxb[i * REAL_RX_BUF_SIZE]);
        !           499:                rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);
        !           500:                rx_ring[i].extsts = cpu_to_le32(0);
        !           501:        }
        !           502: //      No need to wrap the ring 
        !           503: //      rx_ring[i].link = virt_to_le32desc(&rx_ring[0]);
        !           504:        writel(0, ns->base + RXDP_HI);
        !           505:        writel(virt_to_le32desc(&rx_ring[0]), ns->base + RXDP);
        !           506: 
        !           507:        DBG("starting receiver\n");
        !           508: 
        !           509:        writel(0x0001, ns->base + CCSR);
        !           510:        writel(0, ns->base + RFCR);
        !           511:        writel(0x7fc00000, ns->base + RFCR);
        !           512:        writel(0xffc00000, ns->base + RFCR);
        !           513: 
        !           514:        ns->up = 1;
        !           515: 
        !           516:        phy_intr(nic);
        !           517: 
        !           518:        /* Okay, let it rip */
        !           519:        ns->IMR_cache |= ISR_PHY;
        !           520:        ns->IMR_cache |= ISR_RXRCMP;
        !           521:        //dev->IMR_cache |= ISR_RXERR;
        !           522:        //dev->IMR_cache |= ISR_RXOK;
        !           523:        ns->IMR_cache |= ISR_RXORN;
        !           524:        ns->IMR_cache |= ISR_RXSOVR;
        !           525:        ns->IMR_cache |= ISR_RXDESC;
        !           526:        ns->IMR_cache |= ISR_RXIDLE;
        !           527:        ns->IMR_cache |= ISR_TXDESC;
        !           528:        ns->IMR_cache |= ISR_TXIDLE;
        !           529: 
        !           530:        // No reason to enable interupts...
        !           531:        // writel(ns->IMR_cache, ns->base + IMR);
        !           532:        // writel(1, ns->base + IER);
        !           533:        ns83820_set_multicast(nic);
        !           534:        kick_rx();
        !           535: }
        !           536: 
        !           537: 
        !           538: static void ns83820_do_reset(struct nic *nic __unused, u32 which)
        !           539: {
        !           540:        DBG("resetting chip...\n");
        !           541:        writel(which, ns->base + CR);
        !           542:        do {
        !           543: 
        !           544:        } while (readl(ns->base + CR) & which);
        !           545:        DBG("okay!\n");
        !           546: }
        !           547: 
        !           548: static void ns83820_reset(struct nic *nic)
        !           549: {
        !           550:        unsigned i;
        !           551:        DBG("ns83820_reset\n");
        !           552: 
        !           553:        writel(0, ns->base + PQCR);
        !           554: 
        !           555:        ns83820_setup_rx(nic);
        !           556: 
        !           557:        for (i = 0; i < NR_TX_DESC; i++) {
        !           558:                tx_ring[i].link = 0;
        !           559:                tx_ring[i].bufptr = 0;
        !           560:                tx_ring[i].cmdsts = cpu_to_le32(0);
        !           561:                tx_ring[i].extsts = cpu_to_le32(0);
        !           562:        }
        !           563: 
        !           564:        ns->tx_idx = 0;
        !           565:        ns->tx_done_idx = 0;
        !           566:        writel(0, ns->base + TXDP_HI);
        !           567:        return;
        !           568: }
        !           569: static void ns83820_getmac(struct nic *nic __unused, u8 * mac)
        !           570: {
        !           571:        unsigned i;
        !           572:        for (i = 0; i < 3; i++) {
        !           573:                u32 data;
        !           574:                /* Read from the perfect match memory: this is loaded by
        !           575:                 * the chip from the EEPROM via the EELOAD self test.
        !           576:                 */
        !           577:                writel(i * 2, ns->base + RFCR);
        !           578:                data = readl(ns->base + RFDR);
        !           579:                *mac++ = data;
        !           580:                *mac++ = data >> 8;
        !           581:        }
        !           582: }
        !           583: 
        !           584: static void ns83820_set_multicast(struct nic *nic __unused)
        !           585: {
        !           586:        u8 *rfcr = ns->base + RFCR;
        !           587:        u32 and_mask = 0xffffffff;
        !           588:        u32 or_mask = 0;
        !           589:        u32 val;
        !           590: 
        !           591:        /* Support Multicast */
        !           592:        and_mask &= ~(RFCR_AAU | RFCR_AAM);
        !           593:        or_mask |= RFCR_AAM;
        !           594:        val = (readl(rfcr) & and_mask) | or_mask;
        !           595:        /* Ramit : RFCR Write Fix doc says RFEN must be 0 modify other bits */
        !           596:        writel(val & ~RFCR_RFEN, rfcr);
        !           597:        writel(val, rfcr);
        !           598: 
        !           599: }
        !           600: static void ns83820_run_bist(struct nic *nic __unused, const char *name,
        !           601:                             u32 enable, u32 done, u32 fail)
        !           602: {
        !           603:        int timed_out = 0;
        !           604:        long start;
        !           605:        u32 status;
        !           606:        int loops = 0;
        !           607: 
        !           608:        DBG("start %s\n", name);
        !           609: 
        !           610:            start = currticks();
        !           611: 
        !           612:        writel(enable, ns->base + PTSCR);
        !           613:        for (;;) {
        !           614:                loops++;
        !           615:                status = readl(ns->base + PTSCR);
        !           616:                if (!(status & enable))
        !           617:                        break;
        !           618:                if (status & done)
        !           619:                        break;
        !           620:                if (status & fail)
        !           621:                        break;
        !           622:                if ((currticks() - start) >= HZ) {
        !           623:                        timed_out = 1;
        !           624:                        break;
        !           625:                }
        !           626:        }
        !           627: 
        !           628:        if (status & fail)
        !           629:          printf("%s failed! (0x%hX & 0x%hX)\n", name, (unsigned int) status, 
        !           630:                 (unsigned int) fail);
        !           631:        else if (timed_out)
        !           632:                printf("run_bist %s timed out! (%hX)\n", name, (unsigned int) status);
        !           633:        DBG("done %s in %d loops\n", name, loops);
        !           634: }
        !           635: 
        !           636: /*************************************
        !           637: Check Link
        !           638: *************************************/
        !           639: static void ns83820_check_intr(struct nic *nic) {
        !           640:        int i;
        !           641:        u32 isr = readl(ns->base + ISR);
        !           642:        if(ISR_PHY & isr)
        !           643:                phy_intr(nic);
        !           644:        if(( ISR_RXIDLE | ISR_RXDESC | ISR_RXERR) & isr)
        !           645:                kick_rx();
        !           646:        for (i = 0; i < NR_RX_DESC; i++) {
        !           647:                if (rx_ring[i].cmdsts == CMDSTS_OWN) {
        !           648: //                     rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);
        !           649:                        rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);
        !           650:                }
        !           651:        }
        !           652: }
        !           653: /**************************************************************************
        !           654: POLL - Wait for a frame
        !           655: ***************************************************************************/
        !           656: static int ns83820_poll(struct nic *nic, int retrieve)
        !           657: {
        !           658:        /* return true if there's an ethernet packet ready to read */
        !           659:        /* nic->packet should contain data on return */
        !           660:        /* nic->packetlen should contain length of data */
        !           661:        u32 cmdsts;
        !           662:        int entry = ns->cur_rx;
        !           663: 
        !           664:        ns83820_check_intr(nic);
        !           665: 
        !           666:        cmdsts = le32_to_cpu(rx_ring[entry].cmdsts);
        !           667: 
        !           668:        if ( ! ( (CMDSTS_OWN & (cmdsts)) && (cmdsts != (CMDSTS_OWN)) ) )
        !           669:          return 0;
        !           670: 
        !           671:        if ( ! retrieve ) return 1;
        !           672: 
        !           673:        if (! (CMDSTS_OK & cmdsts) )
        !           674:          return 0;
        !           675: 
        !           676:        nic->packetlen = cmdsts & 0xffff;
        !           677:        memcpy(nic->packet,
        !           678:               rxb + (entry * REAL_RX_BUF_SIZE),
        !           679:               nic->packetlen);
        !           680:        //                      rx_ring[entry].link = 0;
        !           681:        rx_ring[entry].cmdsts = cpu_to_le32(CMDSTS_OWN);
        !           682: 
        !           683:        ns->cur_rx = (ns->cur_rx + 1) % NR_RX_DESC;
        !           684: 
        !           685:        if (ns->cur_rx == 0)    /* We have wrapped the ring */
        !           686:          kick_rx();
        !           687: 
        !           688:        return 1;
        !           689: }
        !           690: 
        !           691: static inline void kick_tx(struct nic *nic __unused)
        !           692: {
        !           693:        DBG("kick_tx\n");
        !           694:        writel(CR_TXE, ns->base + CR);
        !           695: }
        !           696: 
        !           697: /**************************************************************************
        !           698: TRANSMIT - Transmit a frame
        !           699: ***************************************************************************/
        !           700: static void ns83820_transmit(struct nic *nic, const char *d,   /* Destination */
        !           701:                             unsigned int t,    /* Type */
        !           702:                             unsigned int s,    /* size */
        !           703:                             const char *p)
        !           704: {                              /* Packet */
        !           705:        /* send the packet to destination */
        !           706: 
        !           707:        u16 nstype;
        !           708:        u32 cmdsts, extsts;
        !           709:        int cur_tx = 0;
        !           710:        u32 isr = readl(ns->base + ISR);
        !           711:        if (ISR_TXIDLE & isr)
        !           712:                kick_tx(nic);
        !           713:        /* point to the current txb incase multiple tx_rings are used */
        !           714:        memcpy(txb, d, ETH_ALEN);
        !           715:        memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
        !           716:        nstype = htons((u16) t);
        !           717:        memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
        !           718:        memcpy(txb + ETH_HLEN, p, s);
        !           719:        s += ETH_HLEN;
        !           720:        s &= 0x0FFF;
        !           721:        while (s < ETH_ZLEN)
        !           722:                txb[s++] = '\0';
        !           723: 
        !           724:        /* Setup the transmit descriptor */
        !           725:        extsts = 0;
        !           726:        extsts |= EXTSTS_UDPPKT;
        !           727: 
        !           728:        tx_ring[cur_tx].bufptr = virt_to_le32desc(&txb);
        !           729:        tx_ring[cur_tx].extsts = cpu_to_le32(extsts);
        !           730: 
        !           731:        cmdsts = cpu_to_le32(0);
        !           732:        cmdsts |= cpu_to_le32(CMDSTS_OWN | s);
        !           733:        tx_ring[cur_tx].cmdsts = cpu_to_le32(cmdsts);
        !           734: 
        !           735:        writel(virt_to_le32desc(&tx_ring[0]), ns->base + TXDP);
        !           736:        kick_tx(nic);
        !           737: }
        !           738: 
        !           739: /**************************************************************************
        !           740: DISABLE - Turn off ethernet interface
        !           741: ***************************************************************************/
        !           742: static void ns83820_disable ( struct nic *nic ) {
        !           743: 
        !           744:        /* put the card in its initial state */
        !           745:        /* This function serves 3 purposes.
        !           746:         * This disables DMA and interrupts so we don't receive
        !           747:         *  unexpected packets or interrupts from the card after
        !           748:         *  etherboot has finished. 
        !           749:         * This frees resources so etherboot may use
        !           750:         *  this driver on another interface
        !           751:         * This allows etherboot to reinitialize the interface
        !           752:         *  if something is something goes wrong.
        !           753:         */
        !           754:        /* disable interrupts */
        !           755:        writel(0, ns->base + IMR);
        !           756:        writel(0, ns->base + IER);
        !           757:        readl(ns->base + IER);
        !           758: 
        !           759:        ns->up = 0;
        !           760: 
        !           761:        ns83820_do_reset(nic, CR_RST);
        !           762: 
        !           763:        ns->IMR_cache &=
        !           764:            ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY |
        !           765:              ISR_RXIDLE);
        !           766:        writel(ns->IMR_cache, ns->base + IMR);
        !           767: 
        !           768:        /* touch the pci bus... */
        !           769:        readl(ns->base + IMR);
        !           770: 
        !           771:        /* assumes the transmitter is already disabled and reset */
        !           772:        writel(0, ns->base + RXDP_HI);
        !           773:        writel(0, ns->base + RXDP);
        !           774: }
        !           775: 
        !           776: /**************************************************************************
        !           777: IRQ - Enable, Disable, or Force interrupts
        !           778: ***************************************************************************/
        !           779: static void ns83820_irq(struct nic *nic __unused, irq_action_t action __unused)
        !           780: {
        !           781:   switch ( action ) {
        !           782:   case DISABLE :
        !           783:     break;
        !           784:   case ENABLE :
        !           785:     break;
        !           786:   case FORCE :
        !           787:     break;
        !           788:   }
        !           789: }
        !           790: 
        !           791: static struct nic_operations ns83820_operations = {
        !           792:        .connect        = dummy_connect,
        !           793:        .poll           = ns83820_poll,
        !           794:        .transmit       = ns83820_transmit,
        !           795:        .irq            = ns83820_irq,
        !           796: 
        !           797: };
        !           798: 
        !           799: static struct pci_device_id ns83820_nics[] = {
        !           800:        PCI_ROM(0x100b, 0x0022, "ns83820", "National Semiconductor 83820", 0),
        !           801: };
        !           802: 
        !           803: PCI_DRIVER ( ns83820_driver, ns83820_nics, PCI_NO_CLASS );
        !           804: 
        !           805: /**************************************************************************
        !           806: PROBE - Look for an adapter, this routine's visible to the outside
        !           807: ***************************************************************************/
        !           808: 
        !           809: #define board_found 1
        !           810: #define valid_link 0
        !           811: static int ns83820_probe ( struct nic *nic, struct pci_device *pci ) {
        !           812: 
        !           813:        long addr;
        !           814:        int using_dac = 0;
        !           815: 
        !           816:        if (pci->ioaddr == 0)
        !           817:                return 0;
        !           818: 
        !           819:        printf("ns83820.c: Found %s, vendor=0x%hX, device=0x%hX\n",
        !           820:               pci->id->name, pci->vendor, pci->device);
        !           821: 
        !           822:        /* point to private storage */
        !           823:        ns = &nsx;
        !           824: 
        !           825:        adjust_pci_device(pci);
        !           826: 
        !           827:        addr = pci_bar_start(pci, PCI_BASE_ADDRESS_1);
        !           828: 
        !           829:        ns->base = ioremap(addr, (1UL << 12));
        !           830: 
        !           831:        if (!ns->base)
        !           832:                return 0;
        !           833: 
        !           834:        nic->irqno  = 0;
        !           835:        nic->ioaddr = pci->ioaddr & ~3;
        !           836: 
        !           837:        /* disable interrupts */
        !           838:        writel(0, ns->base + IMR);
        !           839:        writel(0, ns->base + IER);
        !           840:        readl(ns->base + IER);
        !           841: 
        !           842:        ns->IMR_cache = 0;
        !           843: 
        !           844:        ns83820_do_reset(nic, CR_RST);
        !           845: 
        !           846:        /* Must reset the ram bist before running it */
        !           847:        writel(PTSCR_RBIST_RST, ns->base + PTSCR);
        !           848:        ns83820_run_bist(nic, "sram bist", PTSCR_RBIST_EN,
        !           849:                         PTSCR_RBIST_DONE, PTSCR_RBIST_FAIL);
        !           850:        ns83820_run_bist(nic, "eeprom bist", PTSCR_EEBIST_EN, 0,
        !           851:                         PTSCR_EEBIST_FAIL);
        !           852:        ns83820_run_bist(nic, "eeprom load", PTSCR_EELOAD_EN, 0, 0);
        !           853: 
        !           854:        /* I love config registers */
        !           855:        ns->CFG_cache = readl(ns->base + CFG);
        !           856: 
        !           857:        if ((ns->CFG_cache & CFG_PCI64_DET)) {
        !           858:                printf("%s: detected 64 bit PCI data bus.\n", pci->id->name);
        !           859:                /*dev->CFG_cache |= CFG_DATA64_EN; */
        !           860:                if (!(ns->CFG_cache & CFG_DATA64_EN))
        !           861:                        printf
        !           862:                            ("%s: EEPROM did not enable 64 bit bus.  Disabled.\n",
        !           863:                             pci->id->name);
        !           864:        } else
        !           865:                ns->CFG_cache &= ~(CFG_DATA64_EN);
        !           866: 
        !           867:        ns->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS |
        !           868:                          CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 |
        !           869:                          CFG_M64ADDR);
        !           870:        ns->CFG_cache |=
        !           871:            CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS |
        !           872:            CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL;
        !           873:        ns->CFG_cache |= CFG_REQALG;
        !           874:        ns->CFG_cache |= CFG_POW;
        !           875:        ns->CFG_cache |= CFG_TMRTEST;
        !           876: 
        !           877:        /* When compiled with 64 bit addressing, we must always enable
        !           878:         * the 64 bit descriptor format.
        !           879:         */
        !           880: #ifdef USE_64BIT_ADDR
        !           881:        ns->CFG_cache |= CFG_M64ADDR;
        !           882: #endif
        !           883: 
        !           884: //FIXME: Enable section on dac or remove this
        !           885:        if (using_dac)
        !           886:                ns->CFG_cache |= CFG_T64ADDR;
        !           887: 
        !           888:        /* Big endian mode does not seem to do what the docs suggest */
        !           889:        ns->CFG_cache &= ~CFG_BEM;
        !           890: 
        !           891:        /* setup optical transceiver if we have one */
        !           892:        if (ns->CFG_cache & CFG_TBI_EN) {
        !           893:                DBG("%s: enabling optical transceiver\n", pci->id->name);
        !           894:                writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR);
        !           895: 
        !           896:                /* setup auto negotiation feature advertisement */
        !           897:                writel(readl(ns->base + TANAR)
        !           898:                       | TANAR_HALF_DUP | TANAR_FULL_DUP,
        !           899:                       ns->base + TANAR);
        !           900: 
        !           901:                /* start auto negotiation */
        !           902:                writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,
        !           903:                       ns->base + TBICR);
        !           904:                writel(TBICR_MR_AN_ENABLE, ns->base + TBICR);
        !           905:                ns->linkstate = LINK_AUTONEGOTIATE;
        !           906: 
        !           907:                ns->CFG_cache |= CFG_MODE_1000;
        !           908:        }
        !           909:        writel(ns->CFG_cache, ns->base + CFG);
        !           910:        DBG("CFG: %hX\n", ns->CFG_cache);
        !           911: 
        !           912:        /* FIXME: reset_phy is defaulted to 0, should we reset anyway? */
        !           913:        if (reset_phy) {
        !           914:                DBG("%s: resetting phy\n", pci->id->name);
        !           915:                writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG);
        !           916:                writel(ns->CFG_cache, ns->base + CFG);
        !           917:        }
        !           918: #if 0                          /* Huh?  This sets the PCI latency register.  Should be done via 
        !           919:                                 * the PCI layer.  FIXME.
        !           920:                                 */
        !           921:        if (readl(dev->base + SRR))
        !           922:                writel(readl(dev->base + 0x20c) | 0xfe00,
        !           923:                       dev->base + 0x20c);
        !           924: #endif
        !           925: 
        !           926:        /* Note!  The DMA burst size interacts with packet
        !           927:         * transmission, such that the largest packet that
        !           928:         * can be transmitted is 8192 - FLTH - burst size.
        !           929:         * If only the transmit fifo was larger...
        !           930:         */
        !           931:        /* Ramit : 1024 DMA is not a good idea, it ends up banging 
        !           932:         * some DELL and COMPAQ SMP systems */
        !           933:        writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA512
        !           934:               | ((1600 / 32) * 0x100), ns->base + TXCFG);
        !           935: 
        !           936:        /* Set Rx to full duplex, don't accept runt, errored, long or length
        !           937:         * range errored packets.  Use 512 byte DMA.
        !           938:         */
        !           939:        /* Ramit : 1024 DMA is not a good idea, it ends up banging 
        !           940:         * some DELL and COMPAQ SMP systems 
        !           941:         * Turn on ALP, only we are accpeting Jumbo Packets */
        !           942:        writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD
        !           943:               | RXCFG_STRIPCRC
        !           944:               //| RXCFG_ALP
        !           945:               | (RXCFG_MXDMA512) | 0, ns->base + RXCFG);
        !           946: 
        !           947:        /* Disable priority queueing */
        !           948:        writel(0, ns->base + PQCR);
        !           949: 
        !           950:        /* Enable IP checksum validation and detetion of VLAN headers.
        !           951:         * Note: do not set the reject options as at least the 0x102
        !           952:         * revision of the chip does not properly accept IP fragments
        !           953:         * at least for UDP.
        !           954:         */
        !           955:        /* Ramit : Be sure to turn on RXCFG_ARP if VLAN's are enabled, since
        !           956:         * the MAC it calculates the packetsize AFTER stripping the VLAN
        !           957:         * header, and if a VLAN Tagged packet of 64 bytes is received (like
        !           958:         * a ping with a VLAN header) then the card, strips the 4 byte VLAN
        !           959:         * tag and then checks the packet size, so if RXCFG_ARP is not enabled,
        !           960:         * it discrards it!.  These guys......
        !           961:         */
        !           962:        writel(VRCR_IPEN | VRCR_VTDEN, ns->base + VRCR);
        !           963: 
        !           964:        /* Enable per-packet TCP/UDP/IP checksumming */
        !           965:        writel(VTCR_PPCHK, ns->base + VTCR);
        !           966: 
        !           967:        /* Ramit : Enable async and sync pause frames */
        !           968: //      writel(0, ns->base + PCR); 
        !           969:        writel((PCR_PS_MCAST | PCR_PS_DA | PCR_PSEN | PCR_FFLO_4K |
        !           970:                PCR_FFHI_8K | PCR_STLO_4 | PCR_STHI_8 | PCR_PAUSE_CNT),
        !           971:               ns->base + PCR);
        !           972: 
        !           973:        /* Disable Wake On Lan */
        !           974:        writel(0, ns->base + WCSR);
        !           975: 
        !           976:        ns83820_getmac(nic, nic->node_addr);
        !           977: 
        !           978:        if (using_dac) {
        !           979:                DBG("%s: using 64 bit addressing.\n", pci->id->name);
        !           980:        }
        !           981: 
        !           982:        DBG("%s: DP83820 %d.%d: io=%#04lx\n",
        !           983:            pci->id->name,
        !           984:            (unsigned) readl(ns->base + SRR) >> 8,
        !           985:            (unsigned) readl(ns->base + SRR) & 0xff,
        !           986:            pci->ioaddr);
        !           987: 
        !           988: #ifdef PHY_CODE_IS_FINISHED
        !           989:        ns83820_probe_phy(dev);
        !           990: #endif
        !           991: 
        !           992:        ns83820_reset(nic);
        !           993:        /* point to NIC specific routines */
        !           994:        nic->nic_op     = &ns83820_operations;
        !           995:        return 1;
        !           996: }
        !           997: 
        !           998: DRIVER ( "NS83820/PCI", nic_driver, pci_driver, ns83820_driver,
        !           999:         ns83820_probe, ns83820_disable );
        !          1000: 
        !          1001: /*
        !          1002:  * Local variables:
        !          1003:  *  c-basic-offset: 8
        !          1004:  *  c-indent-level: 8
        !          1005:  *  tab-width: 8
        !          1006:  * End:
        !          1007:  */

unix.superglobalmegacorp.com

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