1 /* $OpenBSD: lance.c,v 1.4 2023/01/10 17:10:57 miod Exp $ */ 2 /* $NetBSD: lance.c,v 1.1 2013/01/13 14:10:55 tsutsui Exp $ */ 3 4 /* 5 * Copyright (c) 2013 Izumi Tsutsui. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 /*- 28 * Copyright (c) 2004 The NetBSD Foundation, Inc. 29 * All rights reserved. 30 * 31 * This code is derived from software contributed to The NetBSD Foundation 32 * by UCHIYAMA Yasushi. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions 36 * are met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce the above copyright 40 * notice, this list of conditions and the following disclaimer in the 41 * documentation and/or other materials provided with the distribution. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 44 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 45 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 46 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 47 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 48 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 49 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 51 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 52 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 53 * POSSIBILITY OF SUCH DAMAGE. 54 */ 55 56 /* 57 * LANCE driver for LUNA 58 * based on sys/arch/ews4800mips/stand/common/lance.c 59 */ 60 61 #include <luna88k/stand/boot/samachdep.h> 62 63 #include <dev/ic/am7990reg.h> 64 #include <dev/ic/lancereg.h> 65 66 #include <luna88k/stand/boot/lance.h> 67 68 static void lance_setup(struct le_softc *); 69 static int lance_set_initblock(struct le_softc *); 70 static int lance_do_initialize(struct le_softc *); 71 72 #define NLE 1 /* XXX for now */ 73 static struct le_softc lesc[NLE]; 74 75 void * 76 lance_attach(uint unit, void *reg, void *mem, uint8_t *eaddr) 77 { 78 struct le_softc *sc; 79 80 if (unit >= NLE) { 81 printf("%s: invalid unit number\n", __func__); 82 return NULL; 83 } 84 sc = &lesc[unit]; 85 86 if (sc->sc_reg != NULL) { 87 printf("%s: unit %d is already attached\n", __func__, unit); 88 return NULL; 89 } 90 sc->sc_reg = reg; 91 sc->sc_mem = mem; 92 memcpy(sc->sc_enaddr, eaddr, 6); 93 94 return sc; 95 } 96 97 void * 98 lance_cookie(uint unit) 99 { 100 struct le_softc *sc; 101 102 if (unit >= NLE) 103 return NULL; 104 105 sc = &lesc[unit]; 106 107 if (sc->sc_reg == NULL) 108 return NULL; 109 110 return sc; 111 } 112 113 uint8_t * 114 lance_eaddr(void *cookie) 115 { 116 struct le_softc *sc = cookie; 117 118 if (sc == NULL || sc->sc_reg == NULL) 119 return NULL; 120 121 return sc->sc_enaddr; 122 } 123 124 int 125 lance_init(void *cookie) 126 { 127 struct le_softc *sc = cookie; 128 129 lance_setup(sc); 130 131 if (!lance_set_initblock(sc)) 132 return 0; 133 134 if (!lance_do_initialize(sc)) 135 return 0; 136 137 return 1; 138 } 139 140 int 141 lance_get(void *cookie, void *data, size_t maxlen) 142 { 143 struct le_softc *sc = cookie; 144 struct lereg *lereg = sc->sc_reg; 145 struct lemem *lemem = sc->sc_mem; 146 struct lermd_v *rmd; 147 uint16_t csr; 148 int len = -1; 149 150 lereg->ler_rap = LE_CSR0; 151 if ((lereg->ler_rdp & LE_C0_RINT) != 0) 152 lereg->ler_rdp = LE_C0_RINT; 153 rmd = &lemem->lem_rmd[sc->sc_currmd]; 154 if ((rmd->rmd1_bits & LE_R1_OWN) != 0) 155 return -1; 156 157 csr = lereg->ler_rdp; 158 #if 0 159 if ((csr & LE_C0_ERR) != 0) 160 printf("%s: RX poll error (CSR=0x%x)\n", __func__, csr); 161 #endif 162 if ((rmd->rmd1_bits & LE_R1_ERR) != 0) { 163 printf("%s: RX error (rmd status=0x%x)\n", __func__, 164 rmd->rmd1_bits); 165 goto out; 166 } 167 168 len = rmd->rmd3; 169 if (len < LEMINSIZE + 4 || len > LEMTU) { 170 printf("%s: RX error (bad length %d)\n", __func__, len); 171 goto out; 172 } 173 len -= 4; 174 memcpy(data, (void *)lemem->lem_rbuf[sc->sc_currmd], min(len, maxlen)); 175 176 out: 177 rmd->rmd2 = -LEMTU; 178 rmd->rmd1_bits = LE_R1_OWN; /* return to LANCE */ 179 sc->sc_currmd = LE_NEXTRMD(sc->sc_currmd); 180 181 return len; 182 } 183 184 int 185 lance_put(void *cookie, void *data, size_t len) 186 { 187 struct le_softc *sc = cookie; 188 struct lereg *lereg = sc->sc_reg; 189 struct lemem *lemem = sc->sc_mem; 190 struct letmd_v *tmd; 191 uint16_t stat; 192 int timeout; 193 194 lereg->ler_rap = LE_CSR0; 195 stat = lereg->ler_rdp; 196 lereg->ler_rdp = 197 stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_TINT); 198 #if 0 199 if (stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR)) 200 printf("%s: TX error before xmit csr0=0x%x\n", 201 __func__, stat); 202 #endif 203 204 /* setup TX descriptor */ 205 tmd = &lemem->lem_tmd[sc->sc_curtmd]; 206 while (tmd->tmd1_bits & LE_T1_OWN) 207 continue; 208 tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP; 209 memcpy((void *)lemem->lem_tbuf[sc->sc_curtmd], data, len); 210 tmd->tmd2 = -max(len, LEMINSIZE); 211 tmd->tmd3 = 0; 212 213 /* start TX */ 214 tmd->tmd1_bits |= LE_T1_OWN; 215 lereg->ler_rap = LE_CSR0; 216 lereg->ler_rdp = LE_C0_TDMD; 217 218 /* check TX complete */ 219 timeout = 0; 220 do { 221 lereg->ler_rap = LE_CSR0; 222 stat = lereg->ler_rdp; 223 #if 0 224 if (stat & LE_C0_ERR) { 225 printf("%s: TX error (CSR0=%x)\n", __func__, stat); 226 if (stat & LE_C0_CERR) { 227 lereg->ler_rdp = LE_C0_CERR; 228 } 229 } 230 #endif 231 if (timeout++ > 1000) { 232 printf("%s: TX timeout (CSR0=%x)\n", __func__, stat); 233 return 0; 234 } 235 } while ((stat & LE_C0_TINT) == 0); 236 237 lereg->ler_rdp = LE_C0_TINT; 238 239 sc->sc_curtmd = LE_NEXTTMD(sc->sc_curtmd); 240 241 return 1; 242 } 243 244 int 245 lance_end(void *cookie) 246 { 247 struct le_softc *sc = cookie; 248 struct lereg *lereg = sc->sc_reg; 249 250 lereg->ler_rap = LE_CSR0; 251 lereg->ler_rdp = LE_C0_STOP; 252 253 return 1; 254 } 255 256 static int 257 lance_set_initblock(struct le_softc *sc) 258 { 259 struct lereg *lereg = sc->sc_reg; 260 uint32_t addr = (uint32_t)sc->sc_mem; 261 262 lereg->ler_rap = LE_CSR0; 263 lereg->ler_rdp = LE_C0_STOP; /* disable all external activity */ 264 DELAY(100); 265 266 /* Set the correct byte swapping mode */ 267 lereg->ler_rap = LE_CSR3; 268 lereg->ler_rdp = LE_C3_BSWP; 269 270 /* Low address of init block */ 271 lereg->ler_rap = LE_CSR1; 272 lereg->ler_rdp = addr & 0xfffe; 273 274 /* High address of init block */ 275 lereg->ler_rap = LE_CSR2; 276 lereg->ler_rdp = (addr >> 16) & 0x00ff; 277 DELAY(100); 278 279 return 1; 280 } 281 282 static int 283 lance_do_initialize(struct le_softc *sc) 284 { 285 struct lereg *lereg = sc->sc_reg; 286 uint16_t reg; 287 int timeout; 288 289 sc->sc_curtmd = 0; 290 sc->sc_currmd = 0; 291 292 /* Initialize LANCE */ 293 lereg->ler_rap = LE_CSR0; 294 lereg->ler_rdp = LE_C0_INIT; 295 296 /* Wait interrupt */ 297 timeout = 1000000; 298 do { 299 lereg->ler_rap = LE_CSR0; 300 reg = lereg->ler_rdp; 301 if (--timeout == 0) { 302 printf("le: init timeout (CSR=0x%x)\n", reg); 303 return 0; 304 } 305 DELAY(1); 306 } while ((reg & LE_C0_IDON) == 0); 307 308 lereg->ler_rap = LE_CSR0; 309 lereg->ler_rdp = LE_C0_STRT | LE_C0_IDON; 310 311 return 1; 312 } 313 314 static void 315 lance_setup(struct le_softc *sc) 316 { 317 struct lereg *lereg = sc->sc_reg; 318 struct lemem *lemem = sc->sc_mem; 319 uint32_t addr; 320 int i; 321 322 /* make sure to stop LANCE chip before setup memory */ 323 lereg->ler_rap = LE_CSR0; 324 lereg->ler_rdp = LE_C0_STOP; 325 326 memset(lemem, 0, sizeof *lemem); 327 328 /* Init block */ 329 lemem->lem_mode = LE_MODE_NORMAL; 330 lemem->lem_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0]; 331 lemem->lem_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2]; 332 lemem->lem_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4]; 333 /* Logical address filter */ 334 for (i = 0; i < 4; i++) 335 lemem->lem_ladrf[i] = 0x0000; 336 337 /* Location of Rx descriptor ring */ 338 addr = (uint32_t)lemem->lem_rmd; 339 lemem->lem_rdra = addr & 0xffff; 340 lemem->lem_rlen = LE_RLEN | ((addr >> 16) & 0xff); 341 342 /* Location of Tx descriptor ring */ 343 addr = (uint32_t)lemem->lem_tmd; 344 lemem->lem_tdra = addr & 0xffff; 345 lemem->lem_tlen = LE_TLEN | ((addr >> 16) & 0xff); 346 347 /* Rx descriptor */ 348 for (i = 0; i < LERBUF; i++) { 349 addr = (uint32_t)lemem->lem_rbuf[i]; 350 lemem->lem_rmd[i].rmd0 = addr & 0xffff; 351 lemem->lem_rmd[i].rmd1_hadr = (addr >> 16) & 0xff; 352 lemem->lem_rmd[i].rmd1_bits = LE_R1_OWN; 353 lemem->lem_rmd[i].rmd2 = LE_XMD2_ONES | -LEMTU; 354 lemem->lem_rmd[i].rmd3 = 0; 355 } 356 357 /* Tx descriptor */ 358 for (i = 0; i < LETBUF; i++) { 359 addr = (uint32_t)lemem->lem_tbuf[i]; 360 lemem->lem_tmd[i].tmd0 = addr & 0xffff; 361 lemem->lem_tmd[i].tmd1_hadr = (addr >> 16) & 0xff; 362 lemem->lem_tmd[i].tmd1_bits = 0; 363 lemem->lem_tmd[i].tmd2 = LE_XMD2_ONES | 0; 364 lemem->lem_tmd[i].tmd3 = 0; 365 } 366 } 367