Annotation of Gnu-Mach/i386/i386at/gpl/if_ul.c, revision 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.