[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     ! 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