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