1 /* $NetBSD: fxp.c,v 1.2 2011/01/27 17:38:04 phx Exp $ */ 2 3 /* 4 * most of the following code was imported from dev/ic/i82557.c; the 5 * original copyright notice is as below. 6 */ 7 8 /*- 9 * Copyright (c) 1997, 1998, 1999, 2001, 2002 The NetBSD Foundation, Inc. 10 * All rights reserved. 11 * 12 * This code is derived from software contributed to The NetBSD Foundation 13 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 14 * NASA Ames Research Center. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Copyright (c) 1995, David Greenman 40 * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org> 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice unmodified, this list of conditions, and the following 48 * disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * Id: if_fxp.c,v 1.113 2001/05/17 23:50:24 jlemon 66 */ 67 68 #include <sys/param.h> 69 70 #include <netinet/in.h> 71 #include <netinet/in_systm.h> 72 73 #include <lib/libsa/stand.h> 74 #include <lib/libsa/net.h> 75 76 #include <dev/ic/i82557reg.h> 77 78 #include "globals.h" 79 80 #define FRAMESIZE 1536 81 82 /* 83 * 82559ER 8086.1209/1229 84 * 85 * - reverse endian access for 16bit/32bit register. 86 * - no vtophys() translation, vaddr_t == paddr_t. 87 * - PIPT writeback cache aware. 88 */ 89 #define CSR_WRITE_1(l, r, v) *(volatile uint8_t *)((l)->iobase+(r)) = (v) 90 #define CSR_READ_1(l, r) *(volatile uint8_t *)((l)->iobase+(r)) 91 #define CSR_WRITE_2(l, r, v) out16rb((l)->iobase+(r), (v)) 92 #define CSR_READ_2(l, r) in16rb((l)->iobase+(r)) 93 #define CSR_WRITE_4(l, r, v) out32rb((l)->iobase+(r), (v)) 94 #define CSR_READ_4(l, r) in32rb((l)->iobase+(r)) 95 #define VTOPHYS(va) (uint32_t)(va) 96 #define DEVTOV(pa) (uint32_t)(pa) 97 #define wbinv(adr, siz) _wbinv(VTOPHYS(adr), (uint32_t)(siz)) 98 #define inv(adr, siz) _inv(VTOPHYS(adr), (uint32_t)(siz)) 99 #define DELAY(n) delay(n) 100 #define ALLOC(T,A) (T *)allocaligned(sizeof(T),(A)) 101 102 struct txdesc { 103 volatile uint16_t cb_status; 104 volatile uint16_t cb_command; 105 volatile uint32_t link_addr; 106 volatile uint32_t tbd_array_addr; 107 volatile uint16_t byte_count; 108 volatile uint8_t tx_threshold; 109 volatile uint8_t tbd_number; 110 volatile uint32_t tx_buf_addr0; 111 volatile uint32_t tx_buf_size0; 112 volatile uint32_t tx_buf_addr1; 113 volatile uint32_t tx_buf_size1; 114 }; /* mimic extended TxCB layout */ 115 116 struct rxdesc { 117 volatile uint16_t rfa_status; 118 volatile uint16_t rfa_control; 119 volatile uint32_t link_addr; 120 volatile uint32_t rbd_addr; 121 volatile uint16_t actual_size; 122 volatile uint16_t size; 123 }; /* 16B rfa */ 124 125 struct local { 126 struct txdesc txd; 127 uint8_t store[sizeof(struct rxdesc) + FRAMESIZE]; 128 unsigned iobase; 129 unsigned eeprom_addr; 130 }; 131 132 static void autosize_eeprom(struct local *); 133 static int read_eeprom(struct local *, int); 134 static void fxp_scb_wait(struct local *); 135 #ifdef DEBUG 136 static int fxp_mdi_read(struct local *, int, int); 137 #endif 138 139 /* 140 * Template for default configuration parameters. 141 * See struct fxp_cb_config for the bit definitions. 142 */ 143 static uint8_t fxp_cb_config_template[] = { 144 0x0, 0x0, /* cb_status */ 145 0x80, 0x2, /* cb_command */ 146 0xff, 0xff, 0xff, 0xff, /* link_addr */ 147 0x16, /* 0 */ 148 0x8, /* 1 */ 149 0x0, /* 2 */ 150 0x0, /* 3 */ 151 0x0, /* 4 */ 152 0x80, /* 5 */ 153 0xb2, /* 6 */ 154 0x3, /* 7 */ 155 0x1, /* 8 */ 156 0x0, /* 9 */ 157 0x26, /* 10 */ 158 0x0, /* 11 */ 159 0x60, /* 12 */ 160 0x0, /* 13 */ 161 0xf2, /* 14 */ 162 0x48, /* 15 */ 163 0x0, /* 16 */ 164 0x40, /* 17 */ 165 0xf3, /* 18 */ 166 0x0, /* 19 */ 167 0x3f, /* 20 */ 168 0x5 /* 21 */ 169 }; 170 171 static struct fxp_cb_config store_cbc; 172 static struct fxp_cb_ias store_cbi; 173 174 int 175 fxp_match(unsigned tag, void *data) 176 { 177 unsigned v; 178 179 v = pcicfgread(tag, PCI_ID_REG); 180 switch (v) { 181 case PCI_DEVICE(0x8086, 0x1209): 182 case PCI_DEVICE(0x8086, 0x1229): 183 return 1; 184 } 185 return 0; 186 } 187 188 void * 189 fxp_init(unsigned tag, void *data) 190 { 191 struct local *sc; 192 uint8_t *en = data; 193 struct fxp_cb_config *cbp = &store_cbc; 194 struct fxp_cb_ias *cb_ias = &store_cbi; 195 struct rxdesc *rfa; 196 unsigned v, i; 197 198 sc = ALLOC(struct local, sizeof(struct txdesc)); /* desc alignment */ 199 memset(sc, 0, sizeof(struct local)); 200 sc->iobase = DEVTOV(pcicfgread(tag, 0x10)); /* use mem space */ 201 202 CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); 203 DELAY(100); 204 205 autosize_eeprom(sc); 206 v = read_eeprom(sc, 0); en[0] = v; en[1] = v >> 8; 207 v = read_eeprom(sc, 1); en[2] = v; en[3] = v >> 8; 208 v = read_eeprom(sc, 2); en[4] = v; en[5] = v >> 8; 209 210 printf("MAC address %02x:%02x:%02x:%02x:%02x:%02x, ", 211 en[0], en[1], en[2], en[3], en[4], en[5]); 212 213 DPRINTF(("PHY %d (%04x.%04x)\n", fxp_mdi_read(sc, 1, 18), 214 fxp_mdi_read(sc, 1, 2), fxp_mdi_read(sc, 1, 3))); 215 216 /* 217 * Initialize base of CBL and RFA memory. Loading with zero 218 * sets it up for regular linear addressing. 219 */ 220 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0); 221 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE); 222 223 fxp_scb_wait(sc); 224 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE); 225 226 /* 227 * This memcpy is kind of disgusting, but there are a bunch of must be 228 * zero and must be one bits in this structure and this is the easiest 229 * way to initialize them all to proper values. 230 */ 231 memcpy(cbp, fxp_cb_config_template, sizeof(fxp_cb_config_template)); 232 233 #define prm 0 234 #define phy_10Mbps_only 0 235 #define all_mcasts 0 236 cbp->cb_status = 0; 237 cbp->cb_command = htole16(FXP_CB_COMMAND_CONFIG | 238 FXP_CB_COMMAND_EL); 239 cbp->link_addr = -1; /* (no) next command */ 240 cbp->byte_count = 22; /* (22) bytes to config */ 241 cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */ 242 cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */ 243 cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */ 244 cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */ 245 cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */ 246 cbp->dma_mbce = 0; /* (disable) dma max counters */ 247 cbp->late_scb = 0; /* (don't) defer SCB update */ 248 cbp->tno_int_or_tco_en = 0; /* (disable) tx not okay interrupt */ 249 cbp->ci_int = 0; /* interrupt on CU not active */ 250 cbp->save_bf = prm; /* save bad frames */ 251 cbp->disc_short_rx = !prm; /* discard short packets */ 252 cbp->underrun_retry = 1; /* retry mode (1) on DMA underrun */ 253 cbp->mediatype = !phy_10Mbps_only; /* interface mode */ 254 cbp->nsai = 1; /* (don't) disable source addr insert */ 255 cbp->preamble_length = 2; /* (7 byte) preamble */ 256 cbp->loopback = 0; /* (don't) loopback */ 257 cbp->linear_priority = 0; /* (normal CSMA/CD operation) */ 258 cbp->linear_pri_mode = 0; /* (wait after xmit only) */ 259 cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */ 260 cbp->promiscuous = prm; /* promiscuous mode */ 261 cbp->bcast_disable = 0; /* (don't) disable broadcasts */ 262 cbp->crscdt = 0; /* (CRS only) */ 263 cbp->stripping = !prm; /* truncate rx packet to byte count */ 264 cbp->padding = 1; /* (do) pad short tx packets */ 265 cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */ 266 cbp->force_fdx = 0; /* (don't) force full duplex */ 267 cbp->fdx_pin_en = 1; /* (enable) FDX# pin */ 268 cbp->multi_ia = 0; /* (don't) accept multiple IAs */ 269 cbp->mc_all = all_mcasts;/* accept all multicasts */ 270 #undef prm 271 #undef phy_10Mbps_only 272 #undef all_mcasts 273 274 wbinv(cbp, sizeof(*cbp)); 275 fxp_scb_wait(sc); 276 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, VTOPHYS(cbp)); 277 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); 278 i = 1000; 279 while (!(le16toh(cbp->cb_status) & FXP_CB_STATUS_C) && --i > 0) { 280 DELAY(1); 281 inv(&cbp->cb_status, sizeof(cbp->cb_status)); 282 } 283 if (i == 0) 284 printf("cbp config timeout\n"); 285 286 /* 287 * Initialize the station address. 288 */ 289 cb_ias->cb_status = 0; 290 cb_ias->cb_command = htole16(FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL); 291 cb_ias->link_addr = -1; 292 memcpy(cb_ias->macaddr, en, 6); 293 294 /* 295 * Start the IAS (Individual Address Setup) command/DMA. 296 */ 297 wbinv(cb_ias, sizeof(*cb_ias)); 298 fxp_scb_wait(sc); 299 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, VTOPHYS(cb_ias)); 300 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); 301 302 i = 1000; 303 while (!(le16toh(cb_ias->cb_status) & FXP_CB_STATUS_C) && --i > 0) { 304 DELAY(1); 305 inv(&cb_ias->cb_status, sizeof(cb_ias->cb_status)); 306 } 307 if (i == 0) 308 printf("ias config timeout\n"); 309 310 rfa = (struct rxdesc *)sc->store; 311 rfa->rfa_status = 0; 312 rfa->rfa_control = htole16(FXP_RFA_CONTROL_S); 313 rfa->link_addr = htole32(VTOPHYS(rfa)); 314 rfa->rbd_addr = -1; 315 rfa->actual_size = 0; 316 rfa->size = htole16(sizeof(sc->store) - sizeof(struct rxdesc)); 317 wbinv(rfa, sizeof(sc->store)); 318 319 fxp_scb_wait(sc); 320 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, VTOPHYS(rfa)); 321 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START); 322 323 return sc; 324 } 325 326 int 327 fxp_send(void *dev, char *buf, unsigned len) 328 { 329 struct local *l = dev; 330 struct txdesc *txd; 331 int loop; 332 333 if (len > 1520) 334 printf("fxp_send: len > 1520 (%u)\n", len); 335 336 txd = &l->txd; 337 txd->cb_status = 0; 338 txd->cb_command = 339 htole16(FXP_CB_COMMAND_XMIT|FXP_CB_COMMAND_SF|FXP_CB_COMMAND_EL); 340 txd->link_addr = -1; 341 txd->tbd_array_addr = htole32(VTOPHYS(&txd->tx_buf_addr0)); 342 txd->tx_buf_addr0 = htole32(VTOPHYS(buf)); 343 txd->tx_buf_size0 = htole32(len); 344 txd->byte_count = htole16(0x8000); 345 txd->tx_threshold = 0x20; 346 txd->tbd_number = 1; 347 wbinv(buf, len); 348 wbinv(txd, sizeof(*txd)); 349 350 fxp_scb_wait(l); 351 CSR_WRITE_4(l, FXP_CSR_SCB_GENERAL, VTOPHYS(txd)); 352 CSR_WRITE_1(l, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); 353 354 loop = 10000; 355 while (!(le16toh(txd->cb_status) & FXP_CB_STATUS_C) && --loop > 0) { 356 DELAY(1); 357 inv(txd, sizeof(struct txdesc)); 358 } 359 if (loop == 0) 360 printf("send timeout\n"); 361 362 return len; 363 } 364 365 int 366 fxp_recv(void *dev, char *buf, unsigned maxlen, unsigned timo) 367 { 368 struct local *l = dev; 369 struct rxdesc *rfa; 370 unsigned bound, ruscus, len; 371 372 fxp_scb_wait(l); 373 CSR_WRITE_1(l, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME); 374 375 bound = 1000 * timo; 376 do { 377 ruscus = CSR_READ_1(l, FXP_CSR_SCB_RUSCUS); 378 if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_READY 379 && (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_SUSPENDED)) 380 goto gotone; 381 DELAY(1000); /* 1 milli second */ 382 } while (--bound > 0); 383 errno = 0; 384 return -1; 385 gotone: 386 rfa = (struct rxdesc *)l->store; 387 inv(rfa, sizeof(l->store)); /* whole including received frame */ 388 if ((le16toh(rfa->rfa_status) & FXP_RFA_STATUS_C) == 0) 389 return 0; 390 len = le16toh(rfa->actual_size) & 0x7ff; 391 if (len > maxlen) 392 len = maxlen; 393 memcpy(buf, &l->store[sizeof(struct rxdesc)], len); 394 395 rfa->rfa_status = 0; 396 rfa->rfa_control = htole16(FXP_RFA_CONTROL_S); 397 rfa->actual_size = 0; 398 wbinv(rfa, sizeof(struct rxdesc)); 399 #if 0 400 fxp_scb_wait(l); 401 CSR_WRITE_1(l, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME); 402 #endif 403 return len; 404 } 405 406 static void 407 eeprom_shiftin(struct local *sc, int data, int len) 408 { 409 uint16_t reg; 410 int x; 411 412 for (x = 1 << (len - 1); x != 0; x >>= 1) { 413 DELAY(40); 414 if (data & x) 415 reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI; 416 else 417 reg = FXP_EEPROM_EECS; 418 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); 419 DELAY(40); 420 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 421 reg | FXP_EEPROM_EESK); 422 DELAY(40); 423 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); 424 } 425 DELAY(40); 426 } 427 428 void 429 autosize_eeprom(struct local *sc) 430 { 431 int x; 432 433 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); 434 DELAY(40); 435 436 /* Shift in read opcode. */ 437 eeprom_shiftin(sc, FXP_EEPROM_OPC_READ, 3); 438 439 /* 440 * Shift in address, wait for the dummy zero following a correct 441 * address shift. 442 */ 443 for (x = 1; x <= 8; x++) { 444 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); 445 DELAY(40); 446 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 447 FXP_EEPROM_EECS | FXP_EEPROM_EESK); 448 DELAY(40); 449 if ((CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & 450 FXP_EEPROM_EEDO) == 0) 451 break; 452 DELAY(40); 453 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); 454 DELAY(40); 455 } 456 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); 457 DELAY(40); 458 if (x != 6 && x != 8) 459 printf("fxp: strange EEPROM address size (%d)\n", x); 460 else 461 sc->eeprom_addr = x; 462 } 463 464 static int 465 read_eeprom(struct local *sc, int offset) 466 { 467 uint16_t reg; 468 int x, val; 469 470 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); 471 472 /* Shift in read opcode. */ 473 eeprom_shiftin(sc, FXP_EEPROM_OPC_READ, 3); 474 475 /* Shift in address. */ 476 eeprom_shiftin(sc, offset, sc->eeprom_addr); 477 478 reg = FXP_EEPROM_EECS; 479 val = 0; 480 /* 481 * Shift out data. 482 */ 483 for (x = 16; x > 0; x--) { 484 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 485 reg | FXP_EEPROM_EESK); 486 DELAY(1); 487 if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & 488 FXP_EEPROM_EEDO) 489 val |= (1 << (x - 1)); 490 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); 491 DELAY(1); 492 } 493 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); 494 DELAY(1); 495 496 return val; 497 } 498 499 static void 500 fxp_scb_wait(struct local *sc) 501 { 502 int loop = 5000; 503 504 while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --loop > 0) 505 DELAY(2); 506 if (loop == 0) 507 printf("SCB timeout\n"); 508 } 509 510 #ifdef DEBUG 511 static int 512 fxp_mdi_read(struct local *sc, int phy, int reg) 513 { 514 int count = 10000; 515 int value; 516 517 CSR_WRITE_4(sc, FXP_CSR_MDICONTROL, 518 (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21)); 519 520 while (((value = CSR_READ_4(sc, FXP_CSR_MDICONTROL)) & 521 0x10000000) == 0 && count--) 522 DELAY(10); 523 524 if (count <= 0) 525 printf("fxp_mdi_read: timed out\n"); 526 527 return (value & 0xffff); 528 } 529 #endif 530