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

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

1.1       nbrk        1: /*     $OpenBSD: if_ie.c,v 1.12 2003/08/20 00:26:00 deraadt 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:
                     49: #include "i82586.h"
                     50: #include "if_iereg.h"
                     51:
                     52: int     ie_debug = 0;
                     53:
                     54: void ie_stop(struct netif *);
                     55: void ie_end(struct netif *);
                     56: void ie_error(struct netif *, char *, volatile struct iereg *);
                     57: int ie_get(struct iodesc *, void *, size_t, time_t);
                     58: void ie_init(struct iodesc *, void *);
                     59: int ie_match(struct netif *, void *);
                     60: int ie_poll(struct iodesc *, void *, int);
                     61: int ie_probe(struct netif *, void *);
                     62: int ie_put(struct iodesc *, void *, size_t);
                     63: void ie_reset(struct netif *, u_char *);
                     64:
                     65: struct netif_stats ie_stats;
                     66:
                     67: struct netif_dif ie0_dif = {
                     68:        0,                      /* unit */
                     69:        1,                      /* nsel */
                     70:        &ie_stats,
                     71:        0,
                     72:        0,
                     73: };
                     74:
                     75: struct netif_driver ie_driver = {
                     76:        "ie",                   /* netif_bname */
                     77:        ie_match,               /* match */
                     78:        ie_probe,               /* probe */
                     79:        ie_init,                /* init */
                     80:        ie_get,                 /* get */
                     81:        ie_put,                 /* put */
                     82:        ie_end,                 /* end */
                     83:        &ie0_dif,               /* netif_ifs */
                     84:        1,                      /* netif_nifs */
                     85: };
                     86:
                     87: struct ie_configuration {
                     88:        u_int   phys_addr;
                     89:        int     used;
                     90: } ie_config[] = {
                     91:        { INTEL_REG_ADDR, 0 }
                     92: };
                     93:
                     94: int     nie_config = sizeof(ie_config) / (sizeof(ie_config[0]));
                     95:
                     96: struct {
                     97:        struct iereg *sc_reg;   /* IE registers */
                     98:        struct iemem *sc_mem;   /* RAM */
                     99: }       ie_softc;
                    100:
                    101: int
                    102: ie_match(struct netif *nif, void *machdep_hint)
                    103: {
                    104:        char   *name;
                    105:        int     i, val = 0;
                    106:
                    107:        if (bugargs.cputyp == CPU_147)
                    108:                return (0);
                    109:        name = machdep_hint;
                    110:        if (name && !bcmp(ie_driver.netif_bname, name, 2))
                    111:                val += 10;
                    112:        for (i = 0; i < nie_config; i++) {
                    113:                if (ie_config[i].used)
                    114:                        continue;
                    115:                if (ie_debug)
                    116:                        printf("ie%d: ie_match --> %d\n", i, val + 1);
                    117:                ie_config[i].used++;
                    118:                return (val + 1);
                    119:        }
                    120:        if (ie_debug)
                    121:                printf("ie%d: ie_match --> 0\n", i);
                    122:        return (0);
                    123: }
                    124:
                    125: int
                    126: ie_probe(struct netif *nif, void *machdep_hint)
                    127: {
                    128:
                    129:        /* the set unit is the current unit */
                    130:        if (ie_debug)
                    131:                printf("ie%d: ie_probe called\n", nif->nif_unit);
                    132:
                    133:        if (bugargs.cputyp != CPU_147)
                    134:                return (0);
                    135:        return (1);
                    136: }
                    137:
                    138: void
                    139: ie_error(struct netif *nif, char *str, volatile struct iereg *ier)
                    140: {
                    141:        panic("ie%d: unknown error", nif->nif_unit);
                    142: }
                    143:
                    144: static void
                    145: ieack(volatile struct iereg *ier, struct iemem *iem)
                    146: {
                    147:        /* ack the `interrupt' */
                    148:        iem->im_scb.ie_command = iem->im_scb.ie_status & IE_ST_WHENCE;
                    149:        ier->ie_attention = 1;  /* chan attention! */
                    150:        while (iem->im_scb.ie_command)
                    151:                ;
                    152: }
                    153:
                    154: void
                    155: ie_reset(struct netif *nif, u_char *myea)
                    156: {
                    157:        volatile struct iereg *ier = ie_softc.sc_reg;
                    158:        struct iemem *iem = ie_softc.sc_mem;
                    159:        int     timo = 10000, stat, i;
                    160:        volatile int t;
                    161:        u_int   a;
                    162:
                    163:        if (ie_debug)
                    164:                printf("ie%d: ie_reset called\n", nif->nif_unit);
                    165:
                    166:        /*printf("ier %x iem %x\n", ier, iem);*/
                    167:
                    168:        *(u_char *)0xfff4202a = 0x40;
                    169:
                    170:        bzero(iem, sizeof(*iem));
                    171:        iem->im_scp.scp_sysbus = 0;
                    172:        iem->im_scp.scp_iscp_low = (int) &iem->im_iscp & 0xffff;
                    173:        iem->im_scp.scp_iscp_high = (int) &iem->im_iscp >> 16;
                    174:
                    175:        iem->im_iscp.iscp_scboffset = (int) &iem->im_scb - (int) iem;
                    176:        iem->im_iscp.iscp_busy = 1;
                    177:        iem->im_iscp.iscp_base_low = (int) iem & 0xffff;
                    178:        iem->im_iscp.iscp_base_high = (int) iem >> 16;
                    179:
                    180:        /*
                    181:         * completely and utterly unlike what i expected, the
                    182:         * "write" order is:
                    183:         * 1st: d15-d0 -> high address
                    184:         * 2nd: d31-d16 -> low address
                    185:         */
                    186:
                    187:        /* reset chip */
                    188:        a = IE_PORT_RESET;
                    189:        ier->ie_porthigh = a & 0xffff;
                    190:        t = 0;
                    191:        t = 1;
                    192:        ier->ie_portlow = a >> 16;
                    193:        for (t = timo; t--;)
                    194:                ;
                    195:
                    196:        /* set new SCP pointer */
                    197:        a = (int) &iem->im_scp | IE_PORT_NEWSCP;
                    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:        ier->ie_attention = 1;  /* chan attention! */
                    206:        for (t = timo * 10; t--;)
                    207:                ;
                    208:
                    209:        /* send CONFIGURE command */
                    210:        iem->im_scb.ie_command = IE_CU_START;
                    211:        iem->im_scb.ie_command_list = (int) &iem->im_cc - (int) iem;
                    212:        iem->im_cc.com.ie_cmd_status = 0;
                    213:        iem->im_cc.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
                    214:        iem->im_cc.com.ie_cmd_link = 0xffff;
                    215:        iem->im_cc.ie_config_count = 0x0c;
                    216:        iem->im_cc.ie_fifo = 8;
                    217:        iem->im_cc.ie_save_bad = 0x40;
                    218:        iem->im_cc.ie_addr_len = 0x2e;
                    219:        iem->im_cc.ie_priority = 0;
                    220:        iem->im_cc.ie_ifs = 0x60;
                    221:        iem->im_cc.ie_slot_low = 0;
                    222:        iem->im_cc.ie_slot_high = 0xf2;
                    223:        iem->im_cc.ie_promisc = 0;
                    224:        iem->im_cc.ie_crs_cdt = 0;
                    225:        iem->im_cc.ie_min_len = 64;
                    226:        iem->im_cc.ie_junk = 0xff;
                    227:
                    228:        ier->ie_attention = 1;  /* chan attention! */
                    229:        for (t = timo * 10; t--;)
                    230:                ;
                    231:
                    232:        ieack(ier, iem);
                    233:
                    234:        /*printf("ic %x\n", &iem->im_ic);*/
                    235:        /* send IASETUP command */
                    236:        iem->im_scb.ie_command = IE_CU_START;
                    237:        iem->im_scb.ie_command_list = (int) &iem->im_ic - (int) iem;
                    238:        iem->im_ic.com.ie_cmd_status = 0;
                    239:        iem->im_ic.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
                    240:        iem->im_ic.com.ie_cmd_link = 0xffff;
                    241:        bcopy(myea, (void *)&iem->im_ic.ie_address, sizeof iem->im_ic.ie_address);
                    242:
                    243:        ier->ie_attention = 1;  /* chan attention! */
                    244:        for (t = timo * 10; t--;)
                    245:                ;
                    246:
                    247:        ieack(ier, iem);
                    248:
                    249:        /* setup buffers */
                    250:
                    251:        for (i = 0; i < NRXBUF; i++) {
                    252:                iem->im_rfd[i].ie_fd_next = (int) &iem->im_rfd[(i+1) % NRXBUF] -
                    253:                    (int) iem;
                    254:                iem->im_rbd[i].ie_rbd_next = (int) &iem->im_rbd[(i+1) % NRXBUF] -
                    255:                    (int) iem;
                    256:                a = (int) &iem->im_rxbuf[i * IE_RBUF_SIZE];
                    257:                iem->im_rbd[i].ie_rbd_buffer_low = a & 0xffff;
                    258:                iem->im_rbd[i].ie_rbd_buffer_high = a >> 16;
                    259:                iem->im_rbd[i].ie_rbd_length = IE_RBUF_SIZE;
                    260:        }
                    261:        iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
                    262:        iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
                    263:        iem->im_rfd[0].ie_fd_buf_desc = (int) &iem->im_rbd[0] - (int) iem;
                    264:
                    265:        /*printf("rfd[0] %x rbd[0] %x buf[0] %x\n", &iem->im_rfd, &iem->im_rbd,
                    266:            &iem->im_rxbuf);*/
                    267:
                    268:        /* send receiver start command */
                    269:        iem->im_scb.ie_command = IE_RU_START;
                    270:        iem->im_scb.ie_command_list = 0;
                    271:        iem->im_scb.ie_recv_list = (int) &iem->im_rfd[0] - (int) iem;
                    272:        ier->ie_attention = 1;  /* chan attention! */
                    273:        while (iem->im_scb.ie_command)
                    274:                ;
                    275:
                    276:        ieack(ier, iem);
                    277: }
                    278:
                    279: int
                    280: ie_poll(struct iodesc *desc, void *pkt, int len)
                    281: {
                    282:        volatile struct iereg *ier = ie_softc.sc_reg;
                    283:        struct iemem *iem = ie_softc.sc_mem;
                    284:        u_char *p = pkt;
                    285:        static int slot;
                    286:        int     length = 0;
                    287:        u_int   a;
                    288:        u_short status;
                    289:
                    290:        asm(".word      0xf518\n");
                    291:        status = iem->im_rfd[slot].ie_fd_status;
                    292:        if (status & IE_FD_BUSY)
                    293:                return (0);
                    294:
                    295:        /* printf("slot %d: %x\n", slot, status); */
                    296:        if ((status & (IE_FD_COMPLETE | IE_FD_OK)) == (IE_FD_COMPLETE | IE_FD_OK)) {
                    297:                if (status & IE_FD_OK) {
                    298:                        length = iem->im_rbd[slot].ie_rbd_actual & 0x3fff;
                    299:                        if (length > len)
                    300:                                length = len;
                    301:                        bcopy((void *)&iem->im_rxbuf[slot * IE_RBUF_SIZE],
                    302:                            pkt, length);
                    303:
                    304:                        iem->im_rfd[slot].ie_fd_status = 0;
                    305:                        iem->im_rfd[slot].ie_fd_last |= IE_FD_LAST;
                    306:                        iem->im_rfd[(slot+NRXBUF-1)%NRXBUF].ie_fd_last &=
                    307:                            ~IE_FD_LAST;
                    308:                        iem->im_rbd[slot].ie_rbd_actual = 0;
                    309:                        iem->im_rbd[slot].ie_rbd_length |= IE_RBD_LAST;
                    310:                        iem->im_rbd[(slot+NRXBUF-1)%NRXBUF].ie_rbd_length &=
                    311:                            ~IE_RBD_LAST;
                    312:                        /*printf("S%d\n", slot);*/
                    313:
                    314:                } else {
                    315:                        printf("shit\n");
                    316:                }
                    317:                slot++;
                    318:                /* should move descriptor onto end of queue... */
                    319:        }
                    320:        if ((iem->im_scb.ie_status & IE_RU_READY) == 0) {
                    321:                printf("RR\n");
                    322:
                    323:                for (slot = 0; slot < NRXBUF; slot++) {
                    324:                        iem->im_rbd[slot].ie_rbd_length &= ~IE_RBD_LAST;
                    325:                        iem->im_rfd[slot].ie_fd_last &= ~IE_FD_LAST;
                    326:                }
                    327:                iem->im_rbd[NRXBUF-1].ie_rbd_length |= IE_RBD_LAST;
                    328:                iem->im_rfd[NRXBUF-1].ie_fd_last |= IE_FD_LAST;
                    329:
                    330:                iem->im_rfd[0].ie_fd_buf_desc = (int)&iem->im_rbd[0] - (int)iem;
                    331:
                    332:                iem->im_scb.ie_command = IE_RU_START;
                    333:                iem->im_scb.ie_command_list = 0;
                    334:                iem->im_scb.ie_recv_list = (int)&iem->im_rfd[0] - (int)iem;
                    335:                ier->ie_attention = 1;  /* chan attention! */
                    336:                while (iem->im_scb.ie_command)
                    337:                        ;
                    338:                slot = 0;
                    339:        }
                    340:        slot = slot % NRXBUF;
                    341:        return (length);
                    342: }
                    343:
                    344: int
                    345: ie_put(struct iodesc *desc, void *pkt, size_t len)
                    346: {
                    347:        volatile struct iereg *ier = ie_softc.sc_reg;
                    348:        struct iemem *iem = ie_softc.sc_mem;
                    349:        u_char *p = pkt;
                    350:        int     timo = 10000, stat, i;
                    351:        volatile int t;
                    352:        u_int   a;
                    353:        int     xx = 0;
                    354:
                    355:        /* send transmit command */
                    356:
                    357:        while (iem->im_scb.ie_command)
                    358:                ;
                    359:
                    360:        /* copy data */
                    361:        bcopy(p, (void *)&iem->im_txbuf[xx], len);
                    362:
                    363:        if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
                    364:                bzero((char *)&iem->im_txbuf[xx] + len,
                    365:                    ETHER_MIN_LEN - ETHER_CRC_LEN - len);
                    366:                len = ETHER_MIN_LEN - ETHER_CRC_LEN;
                    367:        }
                    368:
                    369:        /* build transmit descriptor */
                    370:        iem->im_xd[xx].ie_xmit_flags = len | IE_XMIT_LAST;
                    371:        iem->im_xd[xx].ie_xmit_next = 0xffff;
                    372:        a = (int) &iem->im_txbuf[xx];
                    373:        iem->im_xd[xx].ie_xmit_buf_low = a & 0xffff;
                    374:        iem->im_xd[xx].ie_xmit_buf_high = a >> 16;
                    375:
                    376:        /* transmit command */
                    377:        iem->im_xc[xx].com.ie_cmd_status = 0;
                    378:        iem->im_xc[xx].com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_LAST;
                    379:        iem->im_xc[xx].com.ie_cmd_link = 0xffff;
                    380:        iem->im_xc[xx].ie_xmit_desc = (int) &iem->im_xd[xx] - (int) iem;
                    381:        iem->im_xc[xx].ie_xmit_length = len;
                    382:        bcopy(p, (void *)&iem->im_xc[xx].ie_xmit_addr,
                    383:            sizeof iem->im_xc[xx].ie_xmit_addr);
                    384:
                    385:        iem->im_scb.ie_command = IE_CU_START;
                    386:        iem->im_scb.ie_command_list = (int) &iem->im_xc[xx] - (int) iem;
                    387:
                    388:        ier->ie_attention = 1;  /* chan attention! */
                    389:
                    390:        if (ie_debug) {
                    391:                printf("ie%d: send %d to %x:%x:%x:%x:%x:%x\n",
                    392:                    desc->io_netif->nif_unit, len,
                    393:                    p[0], p[1], p[2], p[3], p[4], p[5]);
                    394:        }
                    395:        return (len);
                    396: }
                    397:
                    398: int
                    399: ie_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
                    400: {
                    401:        time_t  t;
                    402:        int     cc;
                    403:
                    404:        t = getsecs();
                    405:        cc = 0;
                    406:        while (((getsecs() - t) < timeout) && !cc) {
                    407:                cc = ie_poll(desc, pkt, len);
                    408:        }
                    409:        return (cc);
                    410: }
                    411: /*
                    412:  * init ie device.   return 0 on failure, 1 if ok.
                    413:  */
                    414: void
                    415: ie_init(struct iodesc *desc, void *machdep_hint)
                    416: {
                    417:        struct netif *nif = desc->io_netif;
                    418:
                    419:        if (ie_debug)
                    420:                printf("ie%d: ie_init called\n", desc->io_netif->nif_unit);
                    421:        machdep_common_ether(desc->myea);
                    422:        bzero(&ie_softc, sizeof(ie_softc));
                    423:        ie_softc.sc_reg =
                    424:            (struct iereg *) ie_config[desc->io_netif->nif_unit].phys_addr;
                    425:        /* printf("buffer @0x%x\n", RELOC - 0x20000);*/
                    426:        ie_softc.sc_mem = (struct iemem *) 0x3e0000;
                    427:        ie_reset(desc->io_netif, desc->myea);
                    428:        printf("device: %s%d attached to %s\n", nif->nif_driver->netif_bname,
                    429:            nif->nif_unit, ether_sprintf(desc->myea));
                    430: }
                    431:
                    432: void
                    433: ie_stop(struct netif *nif)
                    434: {
                    435:        volatile struct iereg *ier = ie_softc.sc_reg;
                    436:        struct iemem *iem = ie_softc.sc_mem;
                    437:        int     timo = 10000;
                    438:        volatile int t;
                    439:        u_int   a;
                    440:
                    441:        iem->im_iscp.iscp_busy = 1;
                    442:        /* reset chip */
                    443:        a = IE_PORT_RESET;
                    444:        ier->ie_porthigh = a & 0xffff;
                    445:        t = 0;
                    446:        t = 1;
                    447:        ier->ie_portlow = a >> 16;
                    448:        for (t = timo; t--;)
                    449:                ;
                    450:
                    451:        /* reset chip again */
                    452:        a = IE_PORT_RESET;
                    453:        ier->ie_porthigh = a & 0xffff;
                    454:        t = 0;
                    455:        t = 1;
                    456:        ier->ie_portlow = a >> 16;
                    457:        for (t = timo; t--;)
                    458:                ;
                    459:
                    460:        /*printf("status %x busy %x\n", iem->im_scb.ie_status,
                    461:            iem->im_iscp.iscp_busy);*/
                    462: }
                    463:
                    464: void
                    465: ie_end(struct netif *nif)
                    466: {
                    467:        if (ie_debug)
                    468:                printf("ie%d: ie_end called\n", nif->nif_unit);
                    469:
                    470:        ie_stop(nif);
                    471:
                    472:        /* *(u_char *) 0xfff42002 = 0; */
                    473: }

CVSweb