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