[BACK]Return to if_ze.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / boot / boot

Annotation of sys/arch/vax/boot/boot/if_ze.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_ze.c,v 1.5 2006/08/24 22:10:36 miod Exp $ */
                      2: /*     $NetBSD: if_ze.c,v 1.12 2002/05/27 16:54:18 ragge Exp $ */
                      3: /*
                      4:  * Copyright (c) 1998 James R. Maynard III.  All rights reserved.
                      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:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *     This product includes software developed by James R. Maynard III.
                     17:  * 4. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  *
                     31:  *     Standalone routine for the SGEC Ethernet controller.
                     32:  */
                     33:
                     34: #include <sys/param.h>
                     35: #include <sys/types.h>
                     36: #include <sys/socket.h>
                     37: #include <sys/queue.h>
                     38:
                     39: #include <net/if.h>
                     40:
                     41: #include <netinet/in.h>
                     42: #include <netinet/in_systm.h>
                     43: #include <netinet/if_ether.h>
                     44:
                     45: #include <lib/libsa/netif.h>
                     46: #include <lib/libsa/stand.h>
                     47: #include <lib/libsa/net.h>
                     48:
                     49: #include <arch/vax/if/sgecreg.h>
                     50:
                     51: #include "arch/vax/include/sid.h"
                     52: #include "arch/vax/include/rpb.h"
                     53:
                     54: #include "vaxstand.h"
                     55:
                     56: static int ze_get(struct iodesc *, void *, size_t, time_t);
                     57: static int ze_put(struct iodesc *, void *, size_t);
                     58:
                     59: #define ETHER_MIN_LEN 64
                     60: #define ETHER_MAX_LEN 1518
                     61:
                     62: struct netif_driver ze_driver = {
                     63:        0, 0, 0, 0, ze_get, ze_put,
                     64: };
                     65:
                     66: #define NRCV 8                         /* allocate 8 receive descriptors */
                     67: #define NXMT 4                         /* and 4 transmit - must be >1 */
                     68: #define SETUP_FRAME_LEN 128            /* length of the setup frame */
                     69:
                     70: /* allocate a buffer on an octaword boundary */
                     71: #define OW_ALLOC(x) ((void *)((int)((int)alloc((x) + 15) + 15) & ~15))
                     72:
                     73: static volatile struct zedevice *addr;
                     74:
                     75: struct ze_tdes *ze_tdes_list;  /* transmit desc list */
                     76: struct ze_rdes *ze_rdes_list;  /* and receive desc list */
                     77: u_char ze_myaddr[ETHER_ADDR_LEN];      /* my Ethernet address */
                     78:
                     79: int
                     80: zeopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
                     81: {
                     82:        u_long nicsr0_work, *nisa_rom;
                     83:        struct ze_tdes *ze_setup_tdes_list;
                     84:        int i;
                     85:
                     86:        /* point to the device in memory */
                     87:        if (askname == 0) /* Override if autoboot */
                     88:                addr = (struct zedevice *)bootrpb.csrphy;
                     89:        else
                     90:                addr = (struct zedevice *)0x20008000;
                     91:
                     92:        /* reset the device and wait for completion */
                     93:        addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_RE;
                     94:        while ((addr->ze_nicsr5 & ZE_NICSR5_ID) == 0)
                     95:                ;
                     96:        if (addr->ze_nicsr5 & ZE_NICSR5_SF) {
                     97:                printf("SGEC self-test failed...\n");
                     98:                return 1;
                     99:        }
                    100:
                    101:        /* Get our Ethernet address */
                    102:        if (vax_boardtype == VAX_BTYP_49) {
                    103:                nisa_rom = (u_long *)0x27800000;
                    104:                for (i=0; i<ETHER_ADDR_LEN; i++)
                    105:                        ze_myaddr[i] = nisa_rom[i] & 0377;
                    106:        } else if (vax_boardtype == VAX_BTYP_VXT) {
                    107:                nisa_rom = (u_long *)0x200c4000;
                    108:                for (i=0; i<ETHER_ADDR_LEN; i++)
                    109:                        ze_myaddr[i] = nisa_rom[i] & 0xff;
                    110:        } else {
                    111:                nisa_rom = (u_long *)0x20084000;
                    112:                for (i=0; i<ETHER_ADDR_LEN; i++)
                    113:                        if (vax_boardtype == VAX_BTYP_660)
                    114:                                ze_myaddr[i] = (nisa_rom[i] & 0xff000000) >> 24;
                    115:                        else
                    116:                                ze_myaddr[i] = (nisa_rom[i] & 0x0000ff00) >> 8;
                    117:        }
                    118:        printf("SGEC: Ethernet address %s", ether_sprintf(ze_myaddr));
                    119:
                    120:        /* initialize SGEC operating mode */
                    121:        /* disable interrupts here */
                    122:        nicsr0_work = ZE_NICSR0_IPL14 | ZE_NICSR0_SA | ZE_NICSR0_MBO |
                    123:                (ZE_NICSR0_IV_MASK & 0x0108);
                    124:        do {
                    125:                addr->ze_nicsr0 = nicsr0_work;
                    126:        } while (addr->ze_nicsr0 != nicsr0_work);
                    127:        if (addr->ze_nicsr5 & ZE_NICSR5_ME)
                    128:                addr->ze_nicsr5 |= ZE_NICSR5_ME;
                    129:        /* reenable interrupts here */
                    130:
                    131:        /* Allocate space for descriptor lists and buffers,
                    132:                then initialize them. Set up both lists as a ring. */
                    133:        ze_rdes_list = OW_ALLOC((NRCV+1) * sizeof(struct ze_rdes));
                    134:        ze_tdes_list = OW_ALLOC((NXMT+1) * sizeof(struct ze_tdes));
                    135:        for (i=0; i < NRCV; i++) {
                    136:                bzero(ze_rdes_list+i,sizeof(struct ze_rdes));
                    137:                ze_rdes_list[i].ze_framelen = ZE_FRAMELEN_OW;
                    138:                ze_rdes_list[i].ze_bufsize = ETHER_MAX_LEN;
                    139:                ze_rdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
                    140:        }
                    141:        bzero(ze_rdes_list+NRCV,sizeof(struct ze_rdes));
                    142:        ze_rdes_list[NRCV].ze_framelen = ZE_FRAMELEN_OW;
                    143:        ze_rdes_list[NRCV].ze_rdes1 = ZE_RDES1_CA;
                    144:        ze_rdes_list[NRCV].ze_bufaddr = (u_char *)ze_rdes_list;
                    145:        for (i=0; i < NXMT; i++) {
                    146:                bzero(ze_tdes_list+i,sizeof(struct ze_tdes));
                    147:                ze_tdes_list[i].ze_tdes1 = ZE_TDES1_FS | ZE_TDES1_LS;
                    148:                ze_tdes_list[i].ze_bufsize = ETHER_MAX_LEN;
                    149:                ze_tdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
                    150:        }
                    151:        bzero(ze_tdes_list+NXMT,sizeof(struct ze_tdes));
                    152:        ze_tdes_list[NXMT].ze_tdes1 = ZE_TDES1_CA;
                    153:        ze_tdes_list[NXMT].ze_tdr = ZE_TDR_OW;
                    154:        ze_tdes_list[NXMT].ze_bufaddr = (u_char *)ze_tdes_list;
                    155:
                    156:        printf(".");    /* XXX VXT */
                    157:
                    158:        /* Build setup frame. We set the SGEC to do a
                    159:                perfect filter on our own address. */
                    160:        ze_setup_tdes_list = OW_ALLOC(2*sizeof(struct ze_tdes));
                    161:        bzero(ze_setup_tdes_list+0,2*sizeof(struct ze_tdes));
                    162:        ze_setup_tdes_list[0].ze_tdr = ZE_TDR_OW;
                    163:        ze_setup_tdes_list[0].ze_tdes1 = ZE_TDES1_DT_SETUP;
                    164:        ze_setup_tdes_list[0].ze_bufsize = SETUP_FRAME_LEN;
                    165:        ze_setup_tdes_list[0].ze_bufaddr = alloc(SETUP_FRAME_LEN);
                    166:        bzero(ze_setup_tdes_list[0].ze_bufaddr,SETUP_FRAME_LEN);
                    167:        for (i=0; i < 16; i++)
                    168:                bcopy(ze_myaddr,ze_setup_tdes_list[0].ze_bufaddr+(8*i),
                    169:                        ETHER_ADDR_LEN);
                    170:        ze_setup_tdes_list[1].ze_tdes1 = ZE_TDES1_CA;
                    171:        ze_setup_tdes_list[1].ze_bufaddr = (u_char *)ze_setup_tdes_list;
                    172:
                    173:        printf(".");    /* XXX VXT */
                    174:
                    175:        /* Start the transmitter and initialize almost everything else. */
                    176:        addr->ze_nicsr4 = ze_setup_tdes_list;
                    177:        addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_SE | ZE_NICSR6_ST |
                    178:                ZE_NICSR6_DC | ZE_NICSR6_BL_4;
                    179:        while ((addr->ze_nicsr5 & ZE_NICSR5_TS) != ZE_NICSR5_TS_SUSP)
                    180:                ;       /* wait for the frame to be processed */
                    181:
                    182:        printf(".");    /* XXX VXT */
                    183:
                    184:        /* Setup frame is done processing, initialize the receiver and
                    185:                point the transmitter to the real tdes list. */
                    186:        addr->ze_nicsr4 = ze_tdes_list;
                    187:        addr->ze_nicsr3 = ze_rdes_list;
                    188:        addr->ze_nicsr6 |= ZE_NICSR6_SR;
                    189:
                    190:        /* And away-y-y we go! */
                    191:
                    192:        printf("\n");
                    193:        net_devinit(f, &ze_driver, ze_myaddr);
                    194:        return 0;
                    195: }
                    196:
                    197: int
                    198: ze_get(desc, pkt, maxlen, timeout)
                    199:        struct iodesc *desc;
                    200:        void *pkt;
                    201:        size_t maxlen;
                    202:        time_t timeout;
                    203: {
                    204:        int timeout_ctr=100000*timeout, len, rdes;
                    205:
                    206:        while (timeout_ctr-- > 0) {
                    207:
                    208:        /* If there's not a packet waiting for us, just decrement the
                    209:                timeout counter. */
                    210:                if (!(addr->ze_nicsr5 & ZE_NICSR5_RI))
                    211:                        continue;
                    212:
                    213:        /* Look through the receive descriptor list for the packet. */
                    214:                for (rdes=0; rdes<NRCV; rdes++) {
                    215:                        if (ze_rdes_list[rdes].ze_framelen & ZE_FRAMELEN_OW)
                    216:                                continue;
                    217:
                    218:        /* If the packet has an error, ignore it. */
                    219:                        if (ze_rdes_list[rdes].ze_rdes0 & ZE_RDES0_ES)
                    220:                                len = 0;
                    221:
                    222:        /* Copy the packet, up to the length supplied by the caller, to
                    223:                the caller's buffer. */
                    224:                        else {
                    225:                                if ((len = (ze_rdes_list[rdes].ze_framelen &
                    226:                                        (~ ZE_FRAMELEN_OW))) > maxlen)
                    227:                                        len = maxlen;
                    228:                                bcopy((void *)ze_rdes_list[rdes].ze_bufaddr,
                    229:                                        pkt,len);
                    230:                        }
                    231:
                    232:        /* Give ownership of this descriptor back to the SGEC. */
                    233:                        ze_rdes_list[rdes].ze_framelen = ZE_FRAMELEN_OW;
                    234:
                    235:        /* If we actually got a good packet, reset the error flags and
                    236:                tell the SGEC to look for more before returning. */
                    237:                        if (len > 0) {
                    238:                                addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI |
                    239:                                        ZE_NICSR5_IS;
                    240:                                addr->ze_nicsr2=ZE_NICSR2_RXPD;
                    241:                                return len;
                    242:                        }
                    243:                }
                    244:        }
                    245:
                    246:        /* If we're going to return an error indication, at least reset the
                    247:                error flags and tell the SGEC to keep receiving first. */
                    248:        addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI | ZE_NICSR5_IS;
                    249:        addr->ze_nicsr2=ZE_NICSR2_RXPD;
                    250:        return 0;
                    251: }
                    252:
                    253: int
                    254: ze_put(desc, pkt, len)
                    255:        struct iodesc *desc;
                    256:        void *pkt;
                    257:        size_t len;
                    258: {
                    259:        int timeout=100000;
                    260:
                    261:        /* The SGEC maintains its position in the transmit descriptor list
                    262:        for the next frame to transmit. Unfortunately, there's no way to tell
                    263:        from software just where that is. We're forced to reset the position
                    264:        whenever we send a frame, which requires waiting for the previous
                    265:        frame to be sent. Argh. */
                    266:        while ((addr->ze_nicsr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN)
                    267:                ;
                    268:
                    269:        /* Copy the packet to the buffer we allocated. */
                    270:        bcopy(pkt, (void *)ze_tdes_list[0].ze_bufaddr, len);
                    271:
                    272:        /* Set the packet length in the descriptor, increasing it to the
                    273:                minimum size if needed. */
                    274:        ze_tdes_list[0].ze_bufsize = len;
                    275:        if (len < ETHER_MIN_LEN)
                    276:                ze_tdes_list[0].ze_bufsize = ETHER_MIN_LEN;
                    277:
                    278:        /* Give ownership of the descriptor to the SGEC and tell it to start
                    279:                transmitting. */
                    280:        ze_tdes_list[0].ze_tdr = ZE_TDR_OW;
                    281:        addr->ze_nicsr4 = ze_tdes_list;
                    282:        addr->ze_nicsr1 = ZE_NICSR1_TXPD;
                    283:
                    284:        /* Wait for the frame to be sent, but not too long. */
                    285:        timeout = 100000;
                    286:        while (((addr->ze_nicsr5 & ZE_NICSR5_TI) == 0) && (--timeout>0))
                    287:                ;
                    288:
                    289:        /* Reset the transmitter interrupt pending flag. */
                    290:        addr->ze_nicsr5 |= ZE_NICSR5_TI;
                    291:
                    292:        /* Return good if we didn't timeout, or error if we did. */
                    293:        if (timeout>0) return len;
                    294:        return -1;
                    295: }
                    296:
                    297: int
                    298: zeclose(struct open_file *f)
                    299: {
                    300:        addr->ze_nicsr6 = ZE_NICSR6_RE;
                    301:
                    302:        return 0;
                    303: }

CVSweb