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