1 /* $NetBSD: lance.c,v 1.8 2021/12/05 03:04:41 msaitoh Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* LANCE driver for EWS4800/360 */ 33 34 #include <lib/libsa/stand.h> 35 #include <lib/libkern/libkern.h> 36 37 #include <dev/ic/am7990reg.h> 38 #include <dev/ic/lancereg.h> 39 40 #include "local.h" 41 42 /* Register Address Pointer */ 43 #define LANCE_RAP ((volatile uint16_t *)0xbe400006) 44 /* Register Data Port */ 45 #define LANCE_RDP ((volatile uint16_t *)0xbe400000) 46 47 #define RX_DESC_NUM 8 48 #define TX_DESC_NUM 8 49 #define TX_BUFSIZE 0x1000 50 #define RX_BUFSIZE 0x1000 51 struct { 52 struct leinit leinit; 53 struct lermd lermd[RX_DESC_NUM]; 54 struct letmd letmd[TX_DESC_NUM]; 55 uint8_t eaddr[6]; 56 uint8_t txdata[TX_BUFSIZE] __attribute__((__aligned__(0x1000))); 57 uint8_t rxdata[RX_BUFSIZE] __attribute__((__aligned__(0x1000))); 58 } lance_mem __attribute__((__aligned__(64))); 59 60 bool lance_init(void); 61 void lance_eaddr(uint8_t *); 62 bool lance_get(void *, size_t); 63 bool lance_put(void *, size_t); 64 65 void lance_setup(void); 66 bool lance_set_initblock(struct leinit *); 67 bool lance_do_initialize(void); 68 69 bool lance_test(void); 70 bool lance_internal_loopback_test(bool); 71 void lance_internal_loopback_setup(bool); 72 void lance_internal_loopback_testdata(void); 73 bool lance_internal_loopback_data_check(bool); 74 bool __poll_interrupt(void); 75 bool __poll_lance_c0(uint16_t); 76 77 bool 78 lance_init(void) 79 { 80 81 lance_setup(); 82 83 if (!lance_set_initblock(&lance_mem.leinit)) 84 return false; 85 86 if (!lance_do_initialize()) 87 return false; 88 89 *LANCE_RDP = LE_C0_STRT; 90 91 return true; 92 } 93 94 void 95 lance_eaddr(uint8_t *p) 96 { 97 int i; 98 99 for (i = 0; i < 6; i++) 100 p[i] = lance_mem.eaddr[i]; 101 } 102 103 bool 104 lance_get(void *data, size_t len) 105 { 106 static int current; 107 struct lermd *rmd; 108 int i, j, k, n; 109 int start, end; 110 uint8_t *q, *p = data, *p_end = p + len; 111 112 while ((*LANCE_RDP & (LE_C0_RINT | LE_C0_INTR)) == 0) 113 ; 114 *LANCE_RDP = LE_C0_RINT; 115 116 start = end = -1; 117 n = 0; 118 for (i = 0; i < 8; i++) { 119 rmd = &lance_mem.lermd[(current + i) & 0x7]; 120 if (rmd->rmd1_bits & LE_R1_STP) 121 start = i; 122 if (rmd->rmd1_bits & LE_R1_ENP) { 123 end = i; 124 n = rmd->rmd3; /* total amount of packet */ 125 break; 126 } 127 } 128 #ifdef DEBUG 129 printf("%s: %d [%d,%d] %d\n", __func__, len, start, end, n); 130 #endif 131 if (start < 0 || end < 0) 132 return false; 133 134 for (i = start; i <= end; i++) { 135 rmd = &lance_mem.lermd[(current + i) & 0x7]; 136 q = (uint8_t *)((rmd->rmd1_hadr << 16) | rmd->rmd0 | 137 0xa0000000); 138 j = i == end ? n : -rmd->rmd2; 139 for (k = 0; k < j; k++) 140 if (p < p_end) 141 *p++ = *q++; 142 n -= j; 143 rmd->rmd1_bits = LE_R1_OWN; /* return to LANCE */ 144 } 145 current = (current + i) & 0x7; 146 147 return true; 148 } 149 150 bool 151 lance_put(void *data, size_t len) 152 { 153 static int current; 154 struct letmd *tmd; 155 uint16_t r; 156 uint8_t *p, *q = data; 157 int i, j, n, start; 158 159 start = current; 160 tmd = &lance_mem.letmd[current]; 161 tmd->tmd1_bits = LE_T1_STP; 162 for (i = 0; i < 8; i++) { 163 current = (current + 1) & 0x7; 164 n = uimin(len, 512); 165 p = (uint8_t *)((tmd->tmd1_hadr << 16) | tmd->tmd0 | 166 0xa0000000); 167 for (j = 0; j < n; j++) 168 *p++ = *q++; 169 len -= n; 170 #if 1 171 tmd->tmd2 = -uimax(n, 64) | 0xf000; 172 #else 173 tmd->tmd2 = -n | 0xf000; 174 #endif 175 tmd->tmd3 = 0; 176 if (len == 0) { 177 tmd->tmd1_bits |= LE_T1_ENP; 178 break; 179 } 180 tmd = &lance_mem.letmd[current]; 181 } 182 183 n = i + 1; 184 185 for (i = 0; i < n; i++) { 186 tmd = &lance_mem.letmd[start + i]; 187 *LANCE_RDP = LE_C0_INEA; 188 tmd->tmd1_bits |= LE_T1_OWN; 189 j = 0; 190 do { 191 *LANCE_RAP; 192 r = *LANCE_RDP; 193 if (r & LE_C0_ERR) { 194 printf("Error. CSR0=%x\n", r); 195 return false; 196 } 197 if (j++ > 0xa0000) { 198 printf("Timeout CSR0=%x\n", r); 199 return false; 200 } 201 } while ((r & (LE_C0_TINT | LE_C0_INTR)) == 0); 202 203 *LANCE_RDP = LE_C0_TINT; 204 } 205 206 for (i = 0; i < n; i++) { 207 uint8_t *bits = &lance_mem.letmd[i].tmd1_bits; 208 if (*bits & LE_T1_OWN || *bits & LE_T1_ERR) { 209 printf("desc%d not transmitted. cause=%x\n", i, *bits); 210 return false; 211 } 212 *bits = 0; 213 } 214 215 return true; 216 } 217 218 bool 219 lance_set_initblock(struct leinit *leinit) 220 { 221 uint16_t test_data[] = { 0xffff, 0xaaaa, 0x5555, 0x0000 }; 222 uint16_t t; 223 uint32_t addr = (uint32_t)leinit; 224 int i; 225 226 /* Control and status register */ 227 for (i = 3; i >= 0; i--) { 228 *LANCE_RAP = i; 229 if ((*LANCE_RAP & 3) != i) 230 goto reg_rw_error; 231 } 232 *LANCE_RDP = LE_C0_STOP; /* disable all external activity */ 233 if (*LANCE_RDP != LE_C0_STOP) 234 goto reg_rw_error; 235 236 /* Low address of init block */ 237 for (i = 0; i < 4; i++) { 238 t = test_data[i] & 0xfffe; 239 *LANCE_RAP = LE_CSR1; 240 *LANCE_RDP = t; 241 if (*LANCE_RDP != t) 242 goto reg_rw_error; 243 } 244 *LANCE_RDP = addr & 0xfffe; 245 #if DEBUG 246 printf("initblock low addr=%x\n", *LANCE_RDP); 247 #endif 248 249 /* High address of init block */ 250 for (i = 0; i < 4; i++) { 251 t = test_data[i] & 0x00ff; 252 *LANCE_RAP = LE_CSR2; 253 *LANCE_RDP = t; 254 if (*LANCE_RDP != t) 255 goto reg_rw_error; 256 } 257 *LANCE_RDP = (addr >> 16) & 0x00ff; 258 #ifdef DEBUG 259 printf("initblock high addr=%x\n", *LANCE_RDP); 260 #endif 261 262 /* Bus master and control */ 263 *LANCE_RAP = LE_CSR3; 264 *LANCE_RDP = 7; 265 if (*LANCE_RDP != 7) 266 goto reg_rw_error; 267 268 *LANCE_RAP = LE_CSR3; 269 *LANCE_RDP = 0; 270 if (*LANCE_RDP != 0) 271 goto reg_rw_error; 272 273 *LANCE_RDP = LE_C3_BSWP | LE_C3_BCON; 274 275 return true; 276 277 reg_rw_error: 278 printf("LANCE register r/w error.\n"); 279 return false; 280 } 281 282 bool 283 lance_do_initialize(void) 284 { 285 286 /* Initialize LANCE */ 287 *LANCE_RAP = LE_CSR0; 288 *LANCE_RDP = LE_C0_INEA | LE_C0_INIT; 289 290 /* Wait interrupt */ 291 if (!__poll_interrupt()) 292 return false; 293 *LANCE_RDP = *LANCE_RDP; 294 295 return true; 296 } 297 298 void 299 lance_setup(void) 300 { 301 struct leinit *init = &lance_mem.leinit; 302 struct lermd *lermd = lance_mem.lermd; 303 struct letmd *letmd = lance_mem.letmd; 304 uint32_t addr; 305 uint8_t *eaddr; 306 int i; 307 308 memset(&lance_mem, 0, sizeof lance_mem); 309 /* Ethernet address from NVSRAM */ 310 eaddr = lance_mem.eaddr; 311 for (i = 0; i < 6; i++) 312 eaddr[i] = *(uint8_t *)(0xbe491008 + i * 4); 313 314 /* Init block */ 315 init->init_mode = 0; 316 init->init_padr[0] = (eaddr[1] << 8) | eaddr[0]; 317 init->init_padr[1] = (eaddr[3] << 8) | eaddr[2]; 318 init->init_padr[2] = (eaddr[5] << 8) | eaddr[4]; 319 /* Logical address filter */ 320 for (i = 0; i < 4; i++) 321 init->init_ladrf[i] = 0x0000; 322 323 /* Location of Rx descriptor ring */ 324 addr = (uint32_t)lermd; 325 init->init_rdra = addr & 0xffff; 326 init->init_rlen = ((ffs(RX_DESC_NUM) - 1) << 13) | 327 ((addr >> 16) & 0xff); 328 329 /* Location of Tx descriptor ring */ 330 addr = (uint32_t)letmd; 331 init->init_tdra = addr & 0xffff; 332 init->init_tlen = ((ffs(RX_DESC_NUM) - 1) << 13) | 333 ((addr >> 16) & 0xff); 334 335 /* Rx descriptor */ 336 addr = (uint32_t)lance_mem.rxdata; 337 for (i = 0; i < RX_DESC_NUM; i++, lermd++) { 338 lermd->rmd0 = (addr & 0xffff) + i * 512; /* data block size */ 339 lermd->rmd1_hadr = (addr >> 16) & 0xff; 340 lermd->rmd1_bits = LE_R1_OWN; 341 lermd->rmd2 = -512; 342 lermd->rmd3 = 0; 343 } 344 345 /* Tx descriptor */ 346 addr = (uint32_t)lance_mem.txdata; 347 for (i = 0; i < TX_DESC_NUM; i++, letmd++) { 348 letmd->tmd0 = (addr & 0xffff) + i * 512; /* data block size */ 349 letmd->tmd1_hadr = (addr >> 16) & 0xff; 350 letmd->tmd1_bits = 0; 351 letmd->tmd2 = 0; 352 letmd->tmd3 = 0; 353 } 354 } 355 356 /* 357 * Internal loopback test. 358 */ 359 bool 360 lance_test(void) 361 { 362 363 /* Internal loop back test. (no CRC) */ 364 if (!lance_internal_loopback_test(false)) 365 return false; 366 367 /* Internal loop back test. (with CRC) */ 368 if (!lance_internal_loopback_test(true)) 369 return false; 370 371 return true; 372 } 373 374 bool 375 lance_internal_loopback_test(bool crc) 376 { 377 378 lance_internal_loopback_setup(crc); 379 380 if (!lance_set_initblock(&lance_mem.leinit)) 381 return false; 382 383 if (!lance_do_initialize()) 384 return false; 385 386 /* Transmit Start */ 387 *LANCE_RAP = LE_CSR0; /* Control and status register */ 388 *LANCE_RDP = LE_C0_INEA | LE_C0_STRT; 389 390 /* Check trasmited data. */ 391 return lance_internal_loopback_data_check(crc); 392 } 393 394 void 395 lance_internal_loopback_setup(bool crc) 396 { 397 struct leinit *init = &lance_mem.leinit; 398 struct lermd *lermd = lance_mem.lermd; 399 struct letmd *letmd = lance_mem.letmd; 400 uint32_t addr; 401 int i; 402 403 memset(&lance_mem, 0, sizeof lance_mem); 404 405 /* Init block */ 406 init->init_mode = LE_C15_INTL | LE_C15_LOOP; 407 if (!crc) 408 init->init_mode |= LE_C15_DXMTFCS; 409 410 init->init_padr[0] = 0x0000; 411 init->init_padr[1] = 0x8400; 412 init->init_padr[2] = 0x0000; 413 for (i = 0; i < 4; i++) 414 init->init_ladrf[i] = 0x0000; 415 416 addr = (uint32_t)lermd; 417 init->init_rdra = addr & 0xffff; 418 init->init_rlen = (ffs(RX_DESC_NUM) << 13) | ((addr >> 16) & 0xff); 419 addr = (uint32_t)letmd; 420 init->init_tdra = addr & 0xffff; 421 init->init_tlen = (ffs(RX_DESC_NUM) << 13) | ((addr >> 16) & 0xff); 422 423 /* Rx descriptor */ 424 addr = (uint32_t)lance_mem.rxdata; 425 for (i = 0; i < RX_DESC_NUM; i++, lermd++) { 426 lermd->rmd0 = (addr & 0xffff) + i * 64; /* data block size */ 427 lermd->rmd1_hadr = (addr >> 16) & 0xff; 428 lermd->rmd1_bits = LE_R1_OWN; 429 lermd->rmd2 = -64; 430 lermd->rmd3 = 0; 431 } 432 433 /* Tx descriptor */ 434 addr = (uint32_t)lance_mem.txdata; 435 for (i = 0; i < TX_DESC_NUM; i++, letmd++) { 436 letmd->tmd0 = (addr & 0xffff) + i * 64; /* data block size */ 437 letmd->tmd1_hadr = (addr >> 16) & 0xff; 438 letmd->tmd1_bits = LE_T1_STP | LE_T1_ENP; 439 if (crc) 440 letmd->tmd2 = -28; 441 else 442 letmd->tmd2 = -32; 443 letmd->tmd3 = 0; 444 } 445 446 lance_internal_loopback_testdata(); 447 } 448 449 void 450 lance_internal_loopback_testdata(void) 451 { 452 uint16_t test_data[] = { 453 0x55aa, 0xff00, 0x0102, 0x0304, 0x0506, 0x0708, 0x0910, 454 0x40db, 0xdfcf, /* CRC */ 455 0x23dc, 0x23dc, 0x1918, 0x1716, 0x1514, 0x1312, 0x1110, 456 0x7081, 0x90cb, /* CRC */ 457 0x6699, 0xaa55, 0x0515, 0x2535, 0x4555, 0x6575, 0x8595, 458 0x55f6, 0xa448, /* CRC */ 459 0x4e4e, 0x5a5a, 0x6969, 0x7878, 0x0f0f, 0x1e1e, 0x2d2d, 460 0xa548, 0x7404, /* CRC */ 461 }; 462 uint16_t test_header[] = { 463 0x0000, 0x0084, 0x0000, /* dst */ 464 0x0000, 0x0084, 0x0000, /* src */ 465 0x000e 466 }; 467 uint16_t *p = (uint16_t *)lance_mem.txdata; 468 int i, j, k; 469 470 for (i = 0; i < 2; i++) { /* 64byte * 8 */ 471 uint16_t *r = test_data; 472 for (j = 0; j < 4; j++) { /* 64byte * 4 */ 473 uint16_t *q = test_header; 474 for (k = 0; k < 7; k++) /* 14byte */ 475 *p++ = *q++; 476 for (k = 0; k < 9; k++) /* 18byte */ 477 *p++ = *r++; 478 p += 16; /* 32byte skip */ 479 } 480 } 481 } 482 483 bool 484 lance_internal_loopback_data_check(bool crc_check) 485 { 486 uint32_t *p = (uint32_t *)lance_mem.txdata; 487 uint32_t *q = (uint32_t *)lance_mem.rxdata; 488 int i, j; 489 490 /* Read all data block */ 491 for (i = 0; i < 8; i++) { 492 printf("block %d ", i); 493 lance_mem.letmd[i].tmd1_bits |= LE_T1_OWN;/* buffer is filled */ 494 /* wait interrupt */ 495 if (!__poll_interrupt()) 496 goto timeout_error; 497 /* wait LANCE status */ 498 if (!__poll_lance_c0(LE_C0_RINT | LE_C0_TINT | LE_C0_INTR | 499 LE_C0_INEA | LE_C0_RXON | LE_C0_TXON | LE_C0_STRT | 500 LE_C0_INIT)) 501 goto timeout_error; 502 503 /* check Tx descriptor */ 504 if (lance_mem.letmd[i].tmd1_bits & LE_T1_ERR) { 505 printf("tx desc error.\n"); 506 goto tx_rx_error; 507 } 508 509 /* check Rx descriptor */ 510 if (lance_mem.lermd[i].rmd1_bits & LE_R1_ERR) { 511 printf("rx desc error.\n"); 512 goto tx_rx_error; 513 } 514 515 /* Compare transmitted data */ 516 for (j = 0; j < 7; j++) /* first 28byte */ 517 if (*p++ != *q++) { 518 printf("data error.\n"); 519 goto tx_rx_error; 520 } 521 522 /* check CRC */ 523 if (crc_check) { 524 printf("CRC=%x ", *p); 525 if (*p != *q) { /* CRC */ 526 goto crc_error; 527 } 528 } 529 printf("ok.\n"); 530 531 p += 9; /* 36byte skip */ 532 q += 9; 533 } 534 return true; 535 timeout_error: 536 printf("LANCE timeout.\n"); 537 return false; 538 tx_rx_error: 539 printf("LANCE Tx/Rx data error.\n"); 540 return false; 541 crc_error: 542 printf("LANCE CRC error.\n"); 543 return false; 544 } 545 546 bool 547 __poll_interrupt(void) 548 { 549 int j; 550 551 for (j = 0; j < 0x10000; j++) { 552 *LANCE_RAP; 553 if (*(volatile uint32_t *)0xbe40a008 & 1) 554 break; 555 } 556 if (j == 0x10000) { 557 printf ("interrupt timeout.\n"); 558 return false; 559 } 560 561 return true; 562 } 563 564 bool 565 __poll_lance_c0(uint16_t r) 566 { 567 int j; 568 569 for (j = 0; j < 0x60000; j++) 570 if (*LANCE_RDP == r) 571 break; 572 if (j == 0x60000) { 573 printf("lance CSR0 %x != %x\n", *LANCE_RDP, r); 574 return false; 575 } 576 577 *LANCE_RDP = (LE_C0_RINT | LE_C0_TINT| LE_C0_INEA) & r; 578 579 return true; 580 } 581