1 /* $NetBSD: if_le.c,v 1.13 2017/05/22 16:59:32 ragge Exp $ */ 2 /* 3 * Copyright (c) 1997, 1999 Ludd, University of Lule}, Sweden. 4 * 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* 28 * Standalone routine for MicroVAX LANCE chip. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/queue.h> 34 #include <sys/socket.h> 35 36 #include <net/if.h> 37 #include <net/if_ether.h> 38 39 #include <netinet/in.h> 40 #include <netinet/in_systm.h> 41 42 #include <../include/sid.h> 43 #include <../include/rpb.h> 44 45 #include <lib/libsa/netif.h> 46 #include <lib/libsa/stand.h> 47 48 #include <dev/ic/lancereg.h> 49 #include <dev/ic/am7990reg.h> 50 51 #include "vaxstand.h" 52 53 /* 54 * Buffer sizes. 55 */ 56 #define TLEN 1 57 #define NTBUF (1 << TLEN) 58 #define RLEN 3 59 #define NRBUF (1 << RLEN) 60 #define BUFSIZE 1518 61 62 #define QW_ALLOC(x) (((uintptr_t)alloc((x) + 7) + 7) & ~7) 63 64 static int le_get(struct iodesc *, void *, size_t, saseconds_t); 65 static int le_put(struct iodesc *, void *, size_t); 66 static void copyout(void *from, int dest, int len); 67 static void copyin(int src, void *to, int len); 68 69 struct netif_driver le_driver = { 70 0, 0, 0, 0, le_get, le_put, 71 }; 72 73 /* 74 * Init block & buffer descriptors according to DEC system 75 * specification documentation. 76 */ 77 struct initblock { 78 short ib_mode; 79 char ib_padr[6]; /* Ethernet address */ 80 int ib_ladrf1; 81 int ib_ladrf2; 82 int ib_rdr; /* Receive address */ 83 int ib_tdr; /* Transmit address */ 84 } *initblock = NULL; 85 86 struct nireg { 87 volatile u_short ni_rdp; /* data port */ 88 volatile short ni_pad0; 89 volatile short ni_rap; /* register select port */ 90 } *nireg; 91 92 93 volatile struct buffdesc { 94 int bd_adrflg; 95 short bd_bcnt; 96 short bd_mcnt; 97 } *rdesc, *tdesc; 98 99 static int addoff, kopiera = 0; 100 101 /* Flags in the address field */ 102 #define BR_OWN 0x80000000 103 #define BR_ERR 0x40000000 104 #define BR_FRAM 0x20000000 105 #define BR_OFLO 0x10000000 106 #define BR_CRC 0x08000000 107 #define BR_BUFF 0x04000000 108 #define BR_STP 0x02000000 109 #define BR_ENP 0x01000000 110 111 #define BT_OWN 0x80000000 112 #define BT_ERR 0x40000000 113 #define BT_MORE 0x10000000 114 #define BT_ONE 0x08000000 115 #define BT_DEF 0x04000000 116 #define BT_STP 0x02000000 117 #define BT_ENP 0x01000000 118 119 int next_rdesc, next_tdesc; 120 121 #define LEWRCSR(port, val) { \ 122 nireg->ni_rap = (port); \ 123 nireg->ni_rdp = (val); \ 124 } 125 126 #define LERDCSR(port) \ 127 (nireg->ni_rap = port, nireg->ni_rdp) 128 129 int 130 leopen(struct open_file *f, int adapt, int ctlr, int unit, int part) 131 { 132 int i, *ea; 133 volatile int to = 100000; 134 u_char eaddr[6]; 135 136 next_rdesc = next_tdesc = 0; 137 138 if (vax_boardtype == VAX_BTYP_650 && 139 ((vax_siedata >> 8) & 0xff) == VAX_SIE_KA640) { 140 kopiera = 1; 141 ea = (void *)0x20084200; 142 nireg = (void *)0x20084400; 143 } else { 144 *(int *)0x20080014 = 0; /* Be sure we do DMA in low 16MB */ 145 ea = (void *)0x20090000; /* XXX ethernetaddress */ 146 nireg = (void *)0x200e0000; 147 } 148 if (askname == 0) /* Override if autoboot */ 149 nireg = (void *)bootrpb.csrphy; 150 else /* Tell kernel from where we booted */ 151 bootrpb.csrphy = (int)nireg; 152 153 if (vax_boardtype == VAX_BTYP_43) 154 addoff = 0x28000000; 155 else 156 addoff = 0; 157 igen: 158 LEWRCSR(LE_CSR0, LE_C0_STOP); 159 while (to--) 160 ; 161 162 for (i = 0; i < 6; i++) 163 eaddr[i] = ea[i] & 0377; 164 165 if (initblock == NULL) { 166 initblock = (struct initblock *) 167 (QW_ALLOC(sizeof(struct initblock)) + addoff); 168 initblock->ib_mode = LE_MODE_NORMAL; 169 memcpy(initblock->ib_padr, eaddr, 6); 170 initblock->ib_ladrf1 = 0; 171 initblock->ib_ladrf2 = 0; 172 173 rdesc = (struct buffdesc *) 174 (QW_ALLOC(sizeof(struct buffdesc) * NRBUF) + addoff); 175 initblock->ib_rdr = (RLEN << 29) | (int)rdesc; 176 if (kopiera) 177 initblock->ib_rdr -= (int)initblock; 178 tdesc = (struct buffdesc *) 179 (QW_ALLOC(sizeof(struct buffdesc) * NTBUF) + addoff); 180 initblock->ib_tdr = (TLEN << 29) | (int)tdesc; 181 if (kopiera) 182 initblock->ib_tdr -= (int)initblock; 183 if (kopiera) 184 copyout(initblock, 0, sizeof(struct initblock)); 185 186 for (i = 0; i < NRBUF; i++) { 187 rdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE) | BR_OWN; 188 if (kopiera) 189 rdesc[i].bd_adrflg -= (int)initblock; 190 rdesc[i].bd_bcnt = -BUFSIZE; 191 rdesc[i].bd_mcnt = 0; 192 } 193 if (kopiera) 194 copyout((void *)rdesc, (int)rdesc - (int)initblock, 195 sizeof(struct buffdesc) * NRBUF); 196 197 for (i = 0; i < NTBUF; i++) { 198 tdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE); 199 if (kopiera) 200 tdesc[i].bd_adrflg -= (int)initblock; 201 tdesc[i].bd_bcnt = 0xf000; 202 tdesc[i].bd_mcnt = 0; 203 } 204 if (kopiera) 205 copyout((void *)tdesc, (int)tdesc - (int)initblock, 206 sizeof(struct buffdesc) * NTBUF); 207 } 208 209 if (kopiera) { 210 LEWRCSR(LE_CSR1, 0); 211 LEWRCSR(LE_CSR2, 0); 212 } else { 213 LEWRCSR(LE_CSR1, (int)initblock & 0xffff); 214 LEWRCSR(LE_CSR2, ((int)initblock >> 16) & 0xff); 215 } 216 217 LEWRCSR(LE_CSR0, LE_C0_INIT); 218 219 to = 100000; 220 while (to--) { 221 if (LERDCSR(LE_CSR0) & LE_C0_IDON) 222 break; 223 if (LERDCSR(LE_CSR0) & LE_C0_ERR) { 224 printf("lance init error: csr0 %x\n", LERDCSR(LE_CSR0)); 225 goto igen; 226 } 227 } 228 229 LEWRCSR(LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON); 230 231 net_devinit(f, &le_driver, eaddr); 232 return 0; 233 } 234 235 int 236 le_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timeout) 237 { 238 int csr, len; 239 volatile int to = 100000 * timeout; 240 241 retry: 242 if (to-- == 0) 243 return 0; 244 245 csr = LERDCSR(LE_CSR0); 246 LEWRCSR(LE_CSR0, csr & (LE_C0_BABL|LE_C0_MISS|LE_C0_MERR|LE_C0_RINT)); 247 248 if (kopiera) 249 copyin((int)&rdesc[next_rdesc] - (int)initblock, 250 (void *)&rdesc[next_rdesc], sizeof(struct buffdesc)); 251 if (rdesc[next_rdesc].bd_adrflg & BR_OWN) 252 goto retry; 253 254 if (rdesc[next_rdesc].bd_adrflg & BR_ERR) 255 len = 0; 256 else { 257 if ((len = rdesc[next_rdesc].bd_mcnt - 4) > maxlen) 258 len = maxlen; 259 260 if (kopiera) 261 copyin((rdesc[next_rdesc].bd_adrflg&0xffffff), 262 pkt, len); 263 else 264 memcpy(pkt, 265 (char *)(rdesc[next_rdesc].bd_adrflg&0xffffff) + 266 addoff, len); 267 } 268 269 rdesc[next_rdesc].bd_mcnt = 0; 270 rdesc[next_rdesc].bd_adrflg |= BR_OWN; 271 if (kopiera) 272 copyout((void *)&rdesc[next_rdesc], (int)&rdesc[next_rdesc] - 273 (int)initblock, sizeof(struct buffdesc)); 274 if (++next_rdesc >= NRBUF) 275 next_rdesc = 0; 276 277 278 if (len == 0) 279 goto retry; 280 return len; 281 } 282 283 int 284 le_put(struct iodesc *desc, void *pkt, size_t len) 285 { 286 volatile int to = 100000; 287 int csr; 288 289 retry: 290 if (--to == 0) 291 return -1; 292 293 csr = LERDCSR(LE_CSR0); 294 LEWRCSR(LE_CSR0, csr & (LE_C0_MISS|LE_C0_CERR|LE_C0_TINT)); 295 296 if (kopiera) 297 copyin((int)&tdesc[next_tdesc] - (int)initblock, 298 (void *)&tdesc[next_tdesc], sizeof(struct buffdesc)); 299 if (tdesc[next_tdesc].bd_adrflg & BT_OWN) 300 goto retry; 301 302 if (kopiera) 303 copyout(pkt, (tdesc[next_tdesc].bd_adrflg & 0xffffff), len); 304 else 305 memcpy((char *)(tdesc[next_tdesc].bd_adrflg & 0xffffff) + 306 addoff, pkt, len); 307 tdesc[next_tdesc].bd_bcnt = 308 (len < ETHER_MIN_LEN ? -ETHER_MIN_LEN : -len); 309 tdesc[next_tdesc].bd_mcnt = 0; 310 tdesc[next_tdesc].bd_adrflg |= BT_OWN | BT_STP | BT_ENP; 311 if (kopiera) 312 copyout((void *)&tdesc[next_tdesc], (int)&tdesc[next_tdesc] - 313 (int)initblock, sizeof(struct buffdesc)); 314 315 LEWRCSR(LE_CSR0, LE_C0_TDMD); 316 317 to = 100000; 318 while (((LERDCSR(LE_CSR0) & LE_C0_TINT) == 0) && --to) 319 ; 320 321 LEWRCSR(LE_CSR0, LE_C0_TINT); 322 if (++next_tdesc >= NTBUF) 323 next_tdesc = 0; 324 325 if (to) 326 return len; 327 328 return -1; 329 } 330 331 int 332 leclose(struct open_file *f) 333 { 334 LEWRCSR(LE_CSR0, LE_C0_STOP); 335 336 return 0; 337 } 338 339 void 340 copyout(void *f, int dest, int len) 341 { 342 short *from = f; 343 short *toaddr; 344 345 toaddr = (short *)0x20120000 + dest; 346 347 while (len > 0) { 348 *toaddr = *from++; 349 toaddr += 2; 350 len -= 2; 351 } 352 } 353 354 void 355 copyin(int src, void *f, int len) 356 { 357 short *to = f; 358 short *fromaddr; 359 360 fromaddr = (short *)0x20120000 + src; 361 362 while (len > 0) { 363 *to++ = *fromaddr; 364 fromaddr += 2; 365 len -= 2; 366 } 367 } 368