Annotation of Gnu-Mach/i386/i386at/gpl/if_ul.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Copyright (c) 1994 Shantanu Goel
                      3:  * All Rights Reserved.
                      4:  * 
                      5:  * Permission to use, copy, modify and distribute this software and its
                      6:  * documentation is hereby granted, provided that both the copyright
                      7:  * notice and this permission notice appear in all copies of the
                      8:  * software, derivative works or modified versions, and any portions
                      9:  * thereof, and that both notices appear in supporting documentation.
                     10:  * 
                     11:  * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     12:  * CONDITION.  THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     13:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     14:  */
                     15: 
                     16: /*
                     17:  * Written 1993 by Donald Becker.
                     18:  * 
                     19:  * Copyright 1993 United States Government as represented by the
                     20:  * Director, National Security Agency.  This software may be used and
                     21:  * distributed according to the terms of the GNU Public License,
                     22:  * incorporated herein by reference.
                     23:  *
                     24:  * The Author may be reached as [email protected] or
                     25:  * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
                     26:  */
                     27: 
                     28: #include <wd.h>
                     29: #include <ul.h>
                     30: #if NUL > 0
                     31: /*
                     32:  * Driver for SMC Ultra ethernet adaptor.
                     33:  * Derived from the Linux driver by Donald Becker.
                     34:  *
                     35:  * Shantanu Goel ([email protected])
                     36:  */
                     37: #include <mach/sa/sys/types.h>
                     38: #include "vm_param.h"
                     39: #include <kern/time_out.h>
                     40: #include <device/device_types.h>
                     41: #include <device/errno.h>
                     42: #include <device/io_req.h>
                     43: #include <device/if_hdr.h>
                     44: #include <device/if_ether.h>
                     45: #include <device/net_status.h>
                     46: #include <device/net_io.h>
                     47: #include <chips/busses.h>
                     48: #include <i386/machspl.h>
                     49: #include <i386/pio.h>
                     50: #include <i386at/gpl/if_nsreg.h>
                     51: 
                     52: #define START_PG       0x00    /* first page of TX buffer */
                     53: #define ULTRA_CMDREG   0       /* offset of ASIC command register */
                     54: #define  ULTRA_RESET   0x80    /* board reset in ULTRA_CMDREG */
                     55: #define  ULTRA_MEMEN   0x40    /* enable shared memory */
                     56: #define ULTRA_NIC_OFF  16      /* NIC register offset */
                     57: 
                     58: #define ulunit(dev)    minor(dev)
                     59: 
                     60: /*
                     61:  * Autoconfiguration stuff.
                     62:  */
                     63: int    ulprobe();
                     64: void   ulattach();
                     65: int    ulstd[] = { 0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0 };
                     66: struct bus_device *ulinfo[NUL];
                     67: struct bus_driver uldriver = {
                     68:        ulprobe, 0, ulattach, 0, ulstd, "ul", ulinfo, 0, 0, 0
                     69: };
                     70: 
                     71: /*
                     72:  * NS8390 state.
                     73:  */
                     74: struct nssoftc ulnssoftc[NUL];
                     75: 
                     76: /*
                     77:  * Ultra state.
                     78:  */
                     79: struct ulsoftc {
                     80:        int     sc_mstart;      /* start of board's RAM */
                     81:        int     sc_mend;        /* end of board's RAM */
                     82:        int     sc_rmstart;     /* start of receive RAM */
                     83:        int     sc_rmend;       /* end of receive RAM */
                     84: } ulsoftc[NUL];
                     85: 
                     86: void   ulstart(int);
                     87: void   ul_reset(struct nssoftc *sc);
                     88: void   ul_input(struct nssoftc *sc, int, char *, int);
                     89: int    ul_output(struct nssoftc *sc, int, char *, int);
                     90: 
                     91: /*
                     92:  * Watchdog.
                     93:  */
                     94: int    ulwstart = 0;
                     95: void   ulwatch(void);
                     96: 
                     97: #define ULDEBUG
                     98: #ifdef ULDEBUG
                     99: int    uldebug = 0;
                    100: #define DEBUGF(stmt)   { if (uldebug) stmt; }
                    101: #else
                    102: #define DEBUGF(stmt)
                    103: #endif
                    104: 
                    105: /*
                    106:  * Probe for the Ultra.
                    107:  * This looks like an 8013 with the station address PROM
                    108:  * at I/O ports <base>+8 to <base>+13, with a checksum following.
                    109:  */
                    110: int
                    111: ulprobe(xxx, ui)
                    112:        int xxx;
                    113:        struct bus_device *ui;
                    114: {
                    115:        int *port;
                    116: 
                    117:        if (ui->unit >= NUL) {
                    118:                printf("ul%d: not configured\n", ui->unit);
                    119:                return (0);
                    120:        }
                    121:        for (port = ulstd; *port; port++) {
                    122:                if (*port < 0)
                    123:                        continue;
                    124:                /*
                    125:                 * Check chip ID nibble.
                    126:                 */
                    127:                if ((inb(*port + 7) & 0xf0) != 0x20)
                    128:                        continue;
                    129:                if (ulprobe1(*port, ui)) {
                    130:                        ui->address = *port;
                    131:                        *port = -1;
                    132: #if NWD > 0
                    133:                        /*
                    134:                         * XXX: The Western Digital/SMC driver can sometimes
                    135:                         * probe the Ultra incorrectly.  Remove the Ultra's
                    136:                         * port from it's list to avoid the problem.
                    137:                         */
                    138:                        {
                    139:                                int i;
                    140:                                extern int wdstd[];
                    141: 
                    142:                                for (i = 0; wdstd[i]; i++) {
                    143:                                        if (wdstd[i] == ui->address) {
                    144:                                                wdstd[i] = -1;
                    145:                                                break;
                    146:                                        }
                    147:                                }
                    148:                        }
                    149: #endif
                    150:                        return (1);
                    151:                }
                    152:        }
                    153:        return (0);
                    154: }
                    155: 
                    156: int
                    157: ulprobe1(port, ui)
                    158:        int port;
                    159:        struct bus_device *ui;
                    160: {
                    161:        u_char num_pages, irqreg, addr, reg4;
                    162:        u_char irqmap[] = { 0, 9, 3, 5, 7, 10, 11, 15 };
                    163:        short num_pages_tbl[4] = { 0x20, 0x40, 0x80, 0xff };
                    164:        int i, irq, checksum = 0;
                    165:        int addr_tbl[4] = { 0x0c0000, 0x0e0000, 0xfc0000, 0xfe0000 };
                    166:        struct ulsoftc *ul = &ulsoftc[ui->unit];
                    167:        struct nssoftc *ns = &ulnssoftc[ui->unit];
                    168:        struct ifnet *ifp = &ns->sc_if;
                    169: 
                    170:        /*
                    171:         * Select the station address register set.
                    172:         */
                    173:        reg4 = inb(port + 4) & 0x7f;
                    174:        outb(port + 4, reg4);
                    175: 
                    176:        for (i = 0; i < 8; i++)
                    177:                checksum += inb(port + 8 + i);
                    178:        if ((checksum & 0xff) != 0xff)
                    179:                return (0);
                    180: 
                    181:        /*
                    182:         * Use 2 transmit buffers.
                    183:         */
                    184:        ns->sc_pingpong = 1;
                    185: 
                    186:        printf("ul%d: SMC Ultra at 0x%03x, ", ui->unit, port);
                    187:        for (i = 0; i < ETHER_ADDR_LEN; i++) {
                    188:                if (i == 0)
                    189:                        printf("%02x", ns->sc_addr[i] = inb(port + 8 + i));
                    190:                else
                    191:                        printf(":%02x", ns->sc_addr[i] = inb(port + 8 + i));
                    192:        }
                    193:        /*
                    194:         * Switch from station address to alternate register set
                    195:         * and read useful registers there.
                    196:         */
                    197:        outb(port + 4, 0x80 | reg4);
                    198: 
                    199:        /*
                    200:         * Enable FINE16 mode to avoid BIOS ROM width mismatches
                    201:         * during reboot.
                    202:         */
                    203:        outb(port + 0x0c, 0x80 | inb(port + 0x0c));
                    204:        irqreg = inb(port + 0x0d);
                    205:        addr = inb(port + 0x0b);
                    206: 
                    207:        /*
                    208:         * Switch back to station address register set so the MSDOG
                    209:         * driver can find the card after a warm boot.
                    210:         */
                    211:        outb(port + 4, reg4);
                    212: 
                    213:        /*
                    214:         * Determine IRQ.  The IRQ bits are split.
                    215:         */
                    216:        irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
                    217:        if (irq == 0) {
                    218:                printf(", failed to detect IRQ line.\n");
                    219:                return (0);
                    220:        }
                    221:        ui->sysdep1 = irq;
                    222:        take_dev_irq(ui);
                    223:        printf(", irq %d", irq);
                    224: 
                    225:        /*
                    226:         * Determine board's RAM location.
                    227:         */
                    228:        ul->sc_mstart = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3];
                    229:        num_pages = num_pages_tbl[(addr >> 4) & 3];
                    230:        ul->sc_rmstart = ul->sc_mstart + TX_PAGES(ns) * 256;
                    231:        ul->sc_mend = ul->sc_rmend
                    232:                = ul->sc_mstart + (num_pages - START_PG) * 256;
                    233:        printf(", memory 0x%05x-0x%05x\n", ul->sc_mstart, ul->sc_mend);
                    234: 
                    235:        /*
                    236:         * Initialize 8390 state.
                    237:         */
                    238:        ns->sc_name = ui->name;
                    239:        ns->sc_unit = ui->unit;
                    240:        ns->sc_port = port + ULTRA_NIC_OFF;
                    241:        ns->sc_word16 = 1;
                    242:        ns->sc_txstrtpg = START_PG;
                    243:        ns->sc_rxstrtpg = START_PG + TX_PAGES(ns);
                    244:        ns->sc_stoppg = num_pages;
                    245:        ns->sc_reset = ul_reset;
                    246:        ns->sc_input = ul_input;
                    247:        ns->sc_output = ul_output;
                    248: 
                    249:        DEBUGF(printf("ul%d: txstrtpg %d rxstrtpg %d num_pages %d\n",
                    250:                      ui->unit, ns->sc_txstrtpg, ns->sc_rxstrtpg, num_pages));
                    251: 
                    252:        /*
                    253:         * Initialize interface header.
                    254:         */
                    255:        ifp->if_unit = ui->unit;
                    256:        ifp->if_mtu = ETHERMTU;
                    257:        ifp->if_flags = IFF_BROADCAST;
                    258:        ifp->if_header_size = sizeof(struct ether_header);
                    259:        ifp->if_header_format = HDR_ETHERNET;
                    260:        ifp->if_address_size = ETHER_ADDR_LEN;
                    261:        ifp->if_address = ns->sc_addr;
                    262:        if_init_queues(ifp);
                    263: 
                    264:        return (1);
                    265: }
                    266: 
                    267: void
                    268: ulattach(ui)
                    269:        struct bus_device *ui;
                    270: {
                    271:        /*
                    272:         * void
                    273:         */
                    274: }
                    275: 
                    276: int
                    277: ulopen(dev, flag)
                    278:        dev_t dev;
                    279:        int flag;
                    280: {
                    281:        int unit = ulunit(dev), s;
                    282:        struct bus_device *ui;
                    283: 
                    284:        if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0)
                    285:                return (ENXIO);
                    286: 
                    287:        /*
                    288:         * Start watchdog.
                    289:         */
                    290:        if (!ulwstart) {
                    291:                ulwstart++;
                    292:                timeout(ulwatch, 0, hz);
                    293:        }
                    294:        ulnssoftc[unit].sc_if.if_flags |= IFF_UP;
                    295:        s = splimp();
                    296:        outb(ui->address, ULTRA_MEMEN); /* enable memory, 16 bit mode */
                    297:        outb(ui->address + 5, 0x80);
                    298:        outb(ui->address + 6, 0x01);    /* enable interrupts and memory */
                    299:        nsinit(&ulnssoftc[unit]);
                    300:        splx(s);
                    301:        return (0);
                    302: }
                    303: 
                    304: int
                    305: uloutput(dev, ior)
                    306:        dev_t dev;
                    307:        io_req_t ior;
                    308: {
                    309:        int unit = ulunit(dev);
                    310:        struct bus_device *ui;
                    311: 
                    312:        if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0)
                    313:                return (ENXIO);
                    314: 
                    315:        return (net_write(&ulnssoftc[unit].sc_if, ulstart, ior));
                    316: }
                    317: 
                    318: int
                    319: ulsetinput(dev, receive_port, priority, filter, filter_count)
                    320:        dev_t dev;
                    321:        mach_port_t receive_port;
                    322:        int priority;
                    323:        filter_t *filter;
                    324:        unsigned filter_count;
                    325: {
                    326:        int unit = ulunit(dev);
                    327:        struct bus_device *ui;
                    328: 
                    329:        if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0)
                    330:                return (ENXIO);
                    331: 
                    332:        return (net_set_filter(&ulnssoftc[unit].sc_if, receive_port,
                    333:                               priority, filter, filter_count));
                    334: }
                    335: 
                    336: int
                    337: ulgetstat(dev, flavor, status, count)
                    338:        dev_t dev;
                    339:        int flavor;
                    340:        dev_status_t status;
                    341:        unsigned *count;
                    342: {
                    343:        int unit = ulunit(dev);
                    344:        struct bus_device *ui;
                    345: 
                    346:        if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0)
                    347:                return (ENXIO);
                    348: 
                    349:        return (net_getstat(&ulnssoftc[unit].sc_if, flavor, status, count));
                    350: }
                    351: 
                    352: int
                    353: ulsetstat(dev, flavor, status, count)
                    354:        dev_t dev;
                    355:        int flavor;
                    356:        dev_status_t status;
                    357:        unsigned count;
                    358: {
                    359:        int unit = ulunit(dev), oflags, s;
                    360:        struct bus_device *ui;
                    361:        struct ifnet *ifp;
                    362:        struct net_status *ns;
                    363: 
                    364:        if (unit >= NUL || (ui = ulinfo[unit]) == 0 || ui->alive == 0)
                    365:                return (ENXIO);
                    366: 
                    367:        ifp = &ulnssoftc[unit].sc_if;
                    368: 
                    369:        switch (flavor) {
                    370: 
                    371:        case NET_STATUS:
                    372:                if (count < NET_STATUS_COUNT)
                    373:                        return (D_INVALID_SIZE);
                    374:                ns = (struct net_status *)status;
                    375:                oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC);
                    376:                ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC);
                    377:                ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC);
                    378:                if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) {
                    379:                        s = splimp();
                    380:                        nsinit(&ulnssoftc[unit]);
                    381:                        splx(s);
                    382:                }
                    383:                break;
                    384: 
                    385:        default:
                    386:                return (D_INVALID_OPERATION);
                    387:        }
                    388:        return (D_SUCCESS);
                    389: }
                    390: 
                    391: void
                    392: ulintr(unit)
                    393:        int unit;
                    394: {
                    395:        nsintr(&ulnssoftc[unit]);
                    396: }
                    397: 
                    398: void
                    399: ulstart(unit)
                    400:        int unit;
                    401: {
                    402:        nsstart(&ulnssoftc[unit]);
                    403: }
                    404: 
                    405: void
                    406: ul_reset(ns)
                    407:        struct nssoftc *ns;
                    408: {
                    409:        int port = ns->sc_port - ULTRA_NIC_OFF; /* ASIC base address */
                    410: 
                    411:        outb(port, ULTRA_RESET);
                    412:        outb(0x80, 0);                  /* I/O delay */
                    413:        outb(port, ULTRA_MEMEN);
                    414: }
                    415: 
                    416: void
                    417: ul_input(ns, count, buf, ring_offset)
                    418:        struct nssoftc *ns;
                    419:        int count;
                    420:        char *buf;
                    421:        int ring_offset;
                    422: {
                    423:        int xfer_start;
                    424:        struct ulsoftc *ul = &ulsoftc[ns->sc_unit];
                    425: 
                    426:        DEBUGF(printf("ul%d: ring_offset = %d\n", ns->sc_unit, ring_offset));
                    427: 
                    428:        xfer_start = ul->sc_mstart + ring_offset - (START_PG << 8);
                    429:        if (xfer_start + count > ul->sc_rmend) {
                    430:                int semi_count = ul->sc_rmend - xfer_start;
                    431: 
                    432:                /*
                    433:                 * Input move must be wrapped.
                    434:                 */
                    435:                bcopy((char *)phystokv(xfer_start), buf, semi_count);
                    436:                count -= semi_count;
                    437:                bcopy((char *)phystokv(ul->sc_rmstart), buf+semi_count, count);
                    438:        } else
                    439:                bcopy((char *)phystokv(xfer_start), buf, count);
                    440: }
                    441: 
                    442: int
                    443: ul_output(ns, count, buf, start_page)
                    444:        struct nssoftc *ns;
                    445:        int count;
                    446:        char *buf;
                    447:        int start_page;
                    448: {
                    449:        char *shmem;
                    450:        int i;
                    451:        struct ulsoftc *ul = &ulsoftc[ns->sc_unit];
                    452: 
                    453:        DEBUGF(printf("ul%d: start_page = %d\n", ns->sc_unit, start_page));
                    454: 
                    455:        shmem = (char *)phystokv(ul->sc_mstart + ((start_page-START_PG) << 8));
                    456:        bcopy(buf, shmem, count);
                    457:        while (count <  ETHERMIN + sizeof(struct ether_header)) {
                    458:                *(shmem + count) = 0;
                    459:                count++;
                    460:        }
                    461:        return (count);
                    462: }
                    463: 
                    464: /*
                    465:  * Watchdog.
                    466:  * Check for hung transmissions.
                    467:  */
                    468: void
                    469: ulwatch()
                    470: {
                    471:        int unit, s;
                    472:        struct nssoftc *ns;
                    473: 
                    474:        timeout(ulwatch, 0, hz);
                    475: 
                    476:        s = splimp();
                    477:        for (unit = 0; unit < NUL; unit++) {
                    478:                if (ulinfo[unit] == 0 || ulinfo[unit]->alive == 0)
                    479:                        continue;
                    480:                ns = &ulnssoftc[unit];
                    481:                if (ns->sc_timer && --ns->sc_timer == 0) {
                    482:                        printf("ul%d: transmission timeout\n", unit);
                    483:                        nsinit(ns);
                    484:                }
                    485:        }
                    486:        splx(s);
                    487: }
                    488: 
                    489: #endif /* NUL > 0 */

unix.superglobalmegacorp.com

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