[BACK]Return to if_ie.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme88k / stand / netboot

Annotation of sys/arch/mvme88k/stand/netboot/if_ie.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_ie.c,v 1.8 2006/05/16 22:52:09 miod Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 1995 Theo de Raadt
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     19:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include <sys/param.h>
                     29: #include <sys/types.h>
                     30:
                     31: #include <netinet/in.h>
                     32: #include <netinet/in_systm.h>
                     33:
                     34: #define ETHER_MIN_LEN   64
                     35: #define ETHER_MAX_LEN   1518
                     36: #define ETHER_CRC_LEN  4
                     37:
                     38: #define NTXBUF 1
                     39: #define NRXBUF 16
                     40: #define IE_RBUF_SIZE   ETHER_MAX_LEN
                     41:
                     42: #include <machine/prom.h>
                     43:
                     44: #include "stand.h"
                     45: #include "libsa.h"
                     46: #include "netif.h"
                     47: #include "config.h"
                     48: #include "net.h"
                     49:
                     50: #include "i82586.h"
                     51: #include "if_iereg.h"
                     52:
                     53: int     ie_debug = 0;
                     54:
                     55: void ie_stop(struct netif *);
                     56: void ie_end(struct netif *);
                     57: void ie_error(struct netif *, char *, volatile struct iereg *);
                     58: int ie_get(struct iodesc *, void *, size_t, time_t);
                     59: void ie_init(struct iodesc *, void *);
                     60: int ie_match(struct netif *, void *);
                     61: int ie_poll(struct iodesc *, void *, int);
                     62: int ie_probe(struct netif *, void *);
                     63: int ie_put(struct iodesc *, void *, size_t);
                     64: void ie_reset(struct netif *, u_char *);
                     65: extern void machdep_common_ether(u_char *);
                     66:
                     67: struct netif_stats ie_stats;
                     68:
                     69: struct netif_dif ie0_dif = {
                     70:        0,                      /* unit */
                     71:        1,                      /* nsel */
                     72:        &ie_stats,
                     73:        0,
                     74:        0,
                     75: };
                     76:
                     77: struct netif_driver ie_driver = {
                     78:        "ie",                   /* netif_bname */
                     79:        ie_match,               /* match */
                     80:        ie_probe,               /* probe */
                     81:        ie_init,                /* init */
                     82:        ie_get,                 /* get */
                     83:        ie_put,                 /* put */
                     84:        ie_end,                 /* end */
                     85:        &ie0_dif,               /* netif_ifs */
                     86:        1,                      /* netif_nifs */
                     87: };
                     88:
                     89: struct ie_configuration {
                     90:        u_int   phys_addr;
                     91:        int     used;
                     92: } ie_config[] = {
                     93:        { INTEL_REG_ADDR, 0 }
                     94: };
                     95:
                     96: int     nie_config = sizeof(ie_config) / (sizeof(ie_config[0]));
                     97:
                     98: struct {
                     99:        struct iereg *sc_reg;   /* IE registers */
                    100:        struct iemem *sc_mem;   /* RAM */
                    101: }       ie_softc;
                    102:
                    103: int
                    104: ie_match(nif, machdep_hint)
                    105:        struct netif *nif;
                    106:        void   *machdep_hint;
                    107: {
                    108:        char   *name;
                    109:        int     i, val = 0;
                    110:
                    111:        name = machdep_hint;
                    112:        if (name && !bcmp(ie_driver.netif_bname, name, 2))
                    113:                val += 10;
                    114:        for (i = 0; i < nie_config; i++) {
                    115:                if (ie_config[i].used)
                    116:                        continue;
                    117:                if (ie_debug)
                    118:                        printf("ie%d: ie_match --> %d\n", i, val + 1);
                    119:                ie_config[i].used++;
                    120:                return (val + 1);
                    121:        }
                    122:        if (ie_debug)
                    123:                printf("ie%d: ie_match --> 0\n", i);
                    124:        return (0);
                    125: }
                    126:
                    127: int
                    128: ie_probe(nif, machdep_hint)
                    129:        struct netif *nif;
                    130:        void   *machdep_hint;
                    131: {
                    132:
                    133:        /* the set unit is the current unit */
                    134:        if (ie_debug)
                    135:                printf("ie%d: ie_probe called\n", nif->nif_unit);
                    136:        return (0);
                    137: /*     return (1);*/
                    138: }
                    139:
                    140: void
                    141: ie_error(nif, str, ier)
                    142:        struct netif *nif;
                    143:        char   *str;
                    144:        volatile struct iereg *ier;
                    145: {
                    146:        panic("ie%d: unknown error", nif->nif_unit);
                    147: }
                    148:
                    149: void
                    150: ieack(ier, iem)
                    151:        volatile struct iereg *ier;
                    152:        struct iemem *iem;
                    153: {
                    154:        /* ack the `interrupt' */
                    155:        iem->im_scb.ie_command = iem->im_scb.ie_status & IE_ST_WHENCE;
                    156:        ier->ie_attention = 1;  /* chan attention! */
                    157:        while (iem->im_scb.ie_command)
                    158:                ;
                    159: }
                    160:
                    161: void
                    162: ie_reset(nif, myea)
                    163:        struct netif *nif;
                    164:        u_char *myea;
                    165: {
                    166:        volatile struct iereg *ier = ie_softc.sc_reg;
                    167:        struct iemem *iem = ie_softc.sc_mem;
                    168:        int     timo = 10000, i;
                    169:        volatile int t;
                    170:        u_int   a;
                    171:
                    172:        if (ie_debug)
                    173:                printf("ie%d: ie_reset called\n", nif->nif_unit);
                    174:
                    175:        /*printf("ier %x iem %x\n", ier, iem);*/
                    176:
                    177:        *(u_char *)0xfff4202a = 0x40;
                    178:
                    179:        bzero(iem, sizeof(*iem));
                    180:        iem->im_scp.scp_sysbus = 0;
                    181:        iem->im_scp.scp_iscp_low = (int) &iem->im_iscp & 0xffff;
                    182:        iem->im_scp.scp_iscp_high = (int) &iem->im_iscp >> 16;
                    183:
                    184:        iem->im_iscp.iscp_scboffset = (int) &iem->im_scb - (int) iem;
                    185:        iem->im_iscp.iscp_busy = 1;
                    186:        iem->im_iscp.iscp_base_low = (int) iem & 0xffff;
                    187:        iem->im_iscp.iscp_base_high = (int) iem >> 16;
                    188:
                    189:        /*
                    190:         * completely and utterly unlike what i expected, the
                    191:         * "write" order is:
                    192:         * 1st: d15-d0 -> high address
                    193:         * 2nd: d31-d16 -> low address
                    194:         */
                    195:
                    196:        /* reset chip */
                    197:        a = IE_PORT_RESET;
                    198:        ier->ie_porthigh = a & 0xffff;
                    199:        t = 0;
                    200:        t = 1;
                    201:        ier->ie_portlow = a >> 16;
                    202:        for (t = timo; t--;)
                    203:                ;
                    204:
                    205:        /* set new SCP pointer */
                    206:        a = (int) &iem->im_scp | IE_PORT_NEWSCP;
                    207:        ier->ie_porthigh = a & 0xffff;
                    208:        t = 0;
                    209:        t = 1;
                    210:        ier->ie_portlow = a >> 16;
                    211:        for (t = timo; t--;)
                    212:                ;
                    213:
                    214:        ier->ie_attention = 1;  /* chan attention! */
                    215:        for (t = timo * 10; t--;)
                    216:                ;
                    217:
                    218:        /* send CONFIGURE command */
                    219:        iem->im_scb.ie_command = IE_CU_START;
                    220:        iem->im_scb.ie_command_list = (int) &iem->im_cc - (int) iem;
                    221:        iem->im_cc.com.ie_cmd_status = 0;
                    222:        iem->im_cc.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
                    223:        iem->im_cc.com.ie_cmd_link = 0xffff;
                    224:        iem->im_cc.ie_config_count = 0x0c;
                    225:        iem->im_cc.ie_fifo = 8;
                    226:        iem->im_cc.ie_save_bad = 0x40;
                    227:        iem->im_cc.ie_addr_len = 0x2e;
                    228:        iem->im_cc.ie_priority = 0;
                    229:        iem->im_cc.ie_ifs = 0x60;
                    230:        iem->im_cc.ie_slot_low = 0;
                    231:        iem->im_cc.ie_slot_high = 0xf2;
                    232:        iem->im_cc.ie_promisc = 0;
                    233:        iem->im_cc.ie_crs_cdt = 0;
                    234:        iem->im_cc.ie_min_len = 64;
                    235:        iem->im_cc.ie_junk = 0xff;
                    236:
                    237:        ier->ie_attention = 1;  /* chan attention! */
                    238:        for (t = timo * 10; t--;)
                    239:                ;
                    240:
                    241:        ieack(ier, iem);
                    242:
                    243:        /*printf("ic %x\n", &iem->im_ic);*/
                    244:        /* send IASETUP command */
                    245:        iem->im_scb.ie_command = IE_CU_START;
                    246:        iem->im_scb.ie_command_list = (int) &iem->im_ic - (int) iem;
                    247:        iem->im_ic.com.ie_cmd_status = 0;
                    248:        iem->im_ic.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
                    249:        iem->im_ic.com.ie_cmd_link = 0xffff;
                    250:        bcopy(myea, (void *)&iem->im_ic.ie_address, sizeof iem->im_ic.ie_address);
                    251:
                    252:        ier->ie_attention = 1;  /* chan attention! */
                    253:        for (t = timo * 10; t--;)
                    254:                ;
                    255:
                    256:        ieack(ier, iem);
                    257:
                    258:        /* setup buffers */
                    259:
                    260:        for (i = 0; i < NRXBUF; i++) {
                    261:                iem->im_rfd[i].ie_fd_next = (int) &iem->im_rfd[(i+1) % NRXBUF] -
                    262:                    (int) iem;
                    263:                iem->im_rbd[i].ie_rbd_next = (int) &iem->im_rbd[(i+1) % NRXBUF] -
                    264:                    (int) iem;
                    265:                a = (int) &iem->im_rxbuf[i * IE_RBUF_SIZE];
                    266:                iem->im_rbd[i].ie_rbd_buffer_low = a & 0xffff;
                    267:                iem->im_rbd[i].ie_rbd_buffer_high = a >> 16;
                    268:                iem->im_rbd[i].ie_rbd_length = IE_RBUF_SIZE;
                    269:        }
                    270:        iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
                    271:        iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
                    272:        iem->im_rfd[0].ie_fd_buf_desc = (int) &iem->im_rbd[0] - (int) iem;
                    273:
                    274:        /*printf("rfd[0] %x rbd[0] %x buf[0] %x\n", &iem->im_rfd, &iem->im_rbd,
                    275:            &iem->im_rxbuf);*/
                    276:
                    277:        /* send receiver start command */
                    278:        iem->im_scb.ie_command = IE_RU_START;
                    279:        iem->im_scb.ie_command_list = 0;
                    280:        iem->im_scb.ie_recv_list = (int) &iem->im_rfd[0] - (int) iem;
                    281:        ier->ie_attention = 1;  /* chan attention! */
                    282:        while (iem->im_scb.ie_command)
                    283:                ;
                    284:
                    285:        ieack(ier, iem);
                    286: }
                    287:
                    288: int
                    289: ie_poll(desc, pkt, len)
                    290:        struct iodesc *desc;
                    291:        void   *pkt;
                    292:        int     len;
                    293: {
                    294:        volatile struct iereg *ier = ie_softc.sc_reg;
                    295:        struct iemem *iem = ie_softc.sc_mem;
                    296:        static int slot;
                    297:        int     length = 0;
                    298:        u_short status;
                    299:
                    300:        asm(".word      0xf518\n");
                    301:        status = iem->im_rfd[slot].ie_fd_status;
                    302:        if (status & IE_FD_BUSY)
                    303:                return (0);
                    304:
                    305:        /* printf("slot %d: %x\n", slot, status); */
                    306:        if ((status & (IE_FD_COMPLETE | IE_FD_OK)) == (IE_FD_COMPLETE | IE_FD_OK)) {
                    307:                if (status & IE_FD_OK) {
                    308:                        length = iem->im_rbd[slot].ie_rbd_actual & 0x3fff;
                    309:                        if (length > len)
                    310:                                length = len;
                    311:                        bcopy((void *)&iem->im_rxbuf[slot * IE_RBUF_SIZE],
                    312:                            pkt, length);
                    313:
                    314:                        iem->im_rfd[slot].ie_fd_status = 0;
                    315:                        iem->im_rfd[slot].ie_fd_last |= IE_FD_LAST;
                    316:                        iem->im_rfd[(slot+NRXBUF-1)%NRXBUF].ie_fd_last &=
                    317:                            ~IE_FD_LAST;
                    318:                        iem->im_rbd[slot].ie_rbd_actual = 0;
                    319:                        iem->im_rbd[slot].ie_rbd_length |= IE_RBD_LAST;
                    320:                        iem->im_rbd[(slot+NRXBUF-1)%NRXBUF].ie_rbd_length &=
                    321:                            ~IE_RBD_LAST;
                    322:                        /*printf("S%d\n", slot);*/
                    323:
                    324:                } else {
                    325:                        printf("shit\n");
                    326:                }
                    327:                slot++;
                    328:                /* should move descriptor onto end of queue... */
                    329:        }
                    330:        if ((iem->im_scb.ie_status & IE_RU_READY) == 0) {
                    331:                printf("RR\n");
                    332:
                    333:                for (slot = 0; slot < NRXBUF; slot++) {
                    334:                        iem->im_rbd[slot].ie_rbd_length &= ~IE_RBD_LAST;
                    335:                        iem->im_rfd[slot].ie_fd_last &= ~IE_FD_LAST;
                    336:                }
                    337:                iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
                    338:                iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
                    339:
                    340:                iem->im_rfd[0].ie_fd_buf_desc = (int)&iem->im_rbd[0] - (int)iem;
                    341:
                    342:                iem->im_scb.ie_command = IE_RU_START;
                    343:                iem->im_scb.ie_command_list = 0;
                    344:                iem->im_scb.ie_recv_list = (int)&iem->im_rfd[0] - (int)iem;
                    345:                ier->ie_attention = 1;  /* chan attention! */
                    346:                while (iem->im_scb.ie_command)
                    347:                        ;
                    348:                slot = 0;
                    349:        }
                    350:        slot = slot % NRXBUF;
                    351:        return (length);
                    352: }
                    353:
                    354: int
                    355: ie_put(desc, pkt, len)
                    356:        struct  iodesc *desc;
                    357:        void    *pkt;
                    358:        size_t  len;
                    359: {
                    360:        volatile struct iereg *ier = ie_softc.sc_reg;
                    361:        struct iemem *iem = ie_softc.sc_mem;
                    362:        u_char *p = pkt;
                    363:        u_int   a;
                    364:        int     xx = 0;
                    365:
                    366:        /* send transmit command */
                    367:
                    368:        while (iem->im_scb.ie_command)
                    369:                ;
                    370:
                    371:        /* copy data */
                    372:        bcopy(p, (void *)&iem->im_txbuf[xx], len);
                    373:
                    374:        if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
                    375:                bzero((char *)&iem->im_txbuf[xx] + len,
                    376:                    ETHER_MIN_LEN - ETHER_CRC_LEN - len);
                    377:                len = ETHER_MIN_LEN - ETHER_CRC_LEN;
                    378:        }
                    379:
                    380:        /* build transmit descriptor */
                    381:        iem->im_xd[xx].ie_xmit_flags = len | IE_XMIT_LAST;
                    382:        iem->im_xd[xx].ie_xmit_next = 0xffff;
                    383:        a = (int) &iem->im_txbuf[xx];
                    384:        iem->im_xd[xx].ie_xmit_buf_low = a & 0xffff;
                    385:        iem->im_xd[xx].ie_xmit_buf_high = a >> 16;
                    386:
                    387:        /* transmit command */
                    388:        iem->im_xc[xx].com.ie_cmd_status = 0;
                    389:        iem->im_xc[xx].com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_LAST;
                    390:        iem->im_xc[xx].com.ie_cmd_link = 0xffff;
                    391:        iem->im_xc[xx].ie_xmit_desc = (int) &iem->im_xd[xx] - (int) iem;
                    392:        iem->im_xc[xx].ie_xmit_length = len;
                    393:        bcopy(p, (void *)&iem->im_xc[xx].ie_xmit_addr,
                    394:            sizeof iem->im_xc[xx].ie_xmit_addr);
                    395:
                    396:        iem->im_scb.ie_command = IE_CU_START;
                    397:        iem->im_scb.ie_command_list = (int) &iem->im_xc[xx] - (int) iem;
                    398:
                    399:        ier->ie_attention = 1;  /* chan attention! */
                    400:
                    401:        if (ie_debug) {
                    402:                printf("ie%d: send %ld to %x:%x:%x:%x:%x:%x\n",
                    403:                    desc->io_netif->nif_unit, len,
                    404:                    p[0], p[1], p[2], p[3], p[4], p[5]);
                    405:        }
                    406:        return (len);
                    407: }
                    408:
                    409: int
                    410: ie_get(desc, pkt, len, timeout)
                    411:        struct  iodesc *desc;
                    412:        void    *pkt;
                    413:        size_t  len;
                    414:        time_t  timeout;
                    415: {
                    416:        time_t  t;
                    417:        int     cc;
                    418:
                    419:        t = getsecs();
                    420:        cc = 0;
                    421:        while (((getsecs() - t) < timeout) && !cc) {
                    422:                cc = ie_poll(desc, pkt, len);
                    423:        }
                    424:        return (cc);
                    425: }
                    426: /*
                    427:  * init ie device.   return 0 on failure, 1 if ok.
                    428:  */
                    429: void
                    430: ie_init(desc, machdep_hint)
                    431:        struct iodesc *desc;
                    432:        void   *machdep_hint;
                    433: {
                    434:        struct netif *nif = desc->io_netif;
                    435:
                    436:        if (ie_debug)
                    437:                printf("ie%d: ie_init called\n", desc->io_netif->nif_unit);
                    438:        machdep_common_ether(desc->myea);
                    439:        bzero(&ie_softc, sizeof(ie_softc));
                    440:        ie_softc.sc_reg =
                    441:            (struct iereg *) ie_config[desc->io_netif->nif_unit].phys_addr;
                    442:        ie_softc.sc_mem = (struct iemem *) 0xae0000;
                    443:        ie_reset(desc->io_netif, desc->myea);
                    444:        printf("device: %s%d attached to %s\n", nif->nif_driver->netif_bname,
                    445:            nif->nif_unit, ether_sprintf(desc->myea));
                    446: }
                    447:
                    448: void
                    449: ie_stop(nif)
                    450:        struct netif *nif;
                    451: {
                    452:        volatile struct iereg *ier = ie_softc.sc_reg;
                    453:        struct iemem *iem = ie_softc.sc_mem;
                    454:        int     timo = 10000;
                    455:        volatile int t;
                    456:        u_int   a;
                    457:
                    458:        iem->im_iscp.iscp_busy = 1;
                    459:        /* reset chip */
                    460:        a = IE_PORT_RESET;
                    461:        ier->ie_porthigh = a & 0xffff;
                    462:        t = 0;
                    463:        t = 1;
                    464:        ier->ie_portlow = a >> 16;
                    465:        for (t = timo; t--;)
                    466:                ;
                    467:
                    468:        /* reset chip again */
                    469:        a = IE_PORT_RESET;
                    470:        ier->ie_porthigh = a & 0xffff;
                    471:        t = 0;
                    472:        t = 1;
                    473:        ier->ie_portlow = a >> 16;
                    474:        for (t = timo; t--;)
                    475:                ;
                    476:
                    477:        /*printf("status %x busy %x\n", iem->im_scb.ie_status,
                    478:            iem->im_iscp.iscp_busy);*/
                    479: }
                    480:
                    481: void
                    482: ie_end(nif)
                    483:        struct netif *nif;
                    484: {
                    485:        if (ie_debug)
                    486:                printf("ie%d: ie_end called\n", nif->nif_unit);
                    487:
                    488:        ie_stop(nif);
                    489:
                    490:        /* *(u_char *) 0xfff42002 = 0; */
                    491: }

CVSweb