|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2007, 2011 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: /* ! 13: * e1000 Gigabit Ethernet Driver for SLOF ! 14: * ! 15: * Reference: ! 16: * PCI/PCI-X Family of Gigabit Ethernet Controllers ! 17: * Software Developer's Manual Rev. 3.3, Intel, December 2006 ! 18: */ ! 19: ! 20: #include <stdint.h> ! 21: #include <string.h> ! 22: #include <byteorder.h> ! 23: #include "e1k.h" ! 24: ! 25: ! 26: /* ! 27: * local defines ! 28: ****************************************************************************** ! 29: */ ! 30: #define E1K_NUM_RX_DESC 128 // do not change ! 31: #define E1K_NUM_TX_DESC 128 // do not change ! 32: #define E1K_BUF_SIZE 2096 // do not change ! 33: ! 34: #define NUM_MAC_ADDR 16 // number of mac address register pairs ! 35: #define EEPROM_MAC_OFFS 0 // position of mac address in eeprom ! 36: ! 37: /* ! 38: * local types ! 39: ****************************************************************************** ! 40: */ ! 41: typedef struct { ! 42: uint32_t m_dev_u32; ! 43: uint64_t m_devmsk_u64; ! 44: char *m_name; ! 45: } e1k_dev_t; ! 46: ! 47: /* ! 48: * e1k common data structures ! 49: */ ! 50: ! 51: /* ! 52: * transmit buffer descriptor ! 53: */ ! 54: typedef struct { ! 55: uint64_t m_buffer_u64; ! 56: uint16_t m_len_u16; ! 57: uint8_t m_cso_u08; ! 58: uint8_t m_cmd_u08; ! 59: uint8_t m_sta_u08; ! 60: uint8_t m_css_u08; ! 61: uint16_t m_spe_u16; ! 62: } __attribute__ ((packed)) e1k_tx_desc_st; ! 63: ! 64: ! 65: /* ! 66: * receive buffer descriptor ! 67: */ ! 68: typedef struct { ! 69: uint64_t m_buffer_u64; ! 70: uint16_t m_len_u16; ! 71: uint16_t m_csm_u16; ! 72: uint8_t m_sta_u08; ! 73: uint8_t m_err_u08; ! 74: uint16_t m_spe_u16; ! 75: } __attribute__ ((packed)) e1k_rx_desc_st; ! 76: ! 77: /* ! 78: * e1k device structure ! 79: */ ! 80: typedef struct { ! 81: /* ! 82: * device identification mask ! 83: */ ! 84: uint64_t m_device_u64; ! 85: ! 86: /* ! 87: * memory mapped base address of NIC ! 88: */ ! 89: uint64_t m_baseaddr_u64; ! 90: ! 91: /* ! 92: * transmit & receive rings ! 93: * must be 16 byte aligned ! 94: */ ! 95: e1k_tx_desc_st m_tx_ring_pst[E1K_NUM_TX_DESC]; ! 96: e1k_rx_desc_st m_rx_ring_pst[E1K_NUM_RX_DESC]; ! 97: ! 98: /* ! 99: * transmit & receive buffers ! 100: * must be 16 byte aligned ! 101: */ ! 102: uint8_t m_tx_buffer_pu08[E1K_NUM_TX_DESC][E1K_BUF_SIZE]; ! 103: uint8_t m_rx_buffer_pu08[E1K_NUM_RX_DESC][E1K_BUF_SIZE]; ! 104: ! 105: /* ! 106: * next receive descriptor index ! 107: */ ! 108: uint32_t m_rx_next_u32; ! 109: ! 110: /* ! 111: * command register storage ! 112: */ ! 113: uint16_t m_com_r_u16; ! 114: ! 115: /* ! 116: * padding to make the size of the structure a multiple of 16 byte ! 117: */ ! 118: uint16_t m_pad16_u16; ! 119: uint64_t m_pad64_u32; ! 120: ! 121: /* ! 122: * PCI related data ! 123: */ ! 124: uint64_t pcicfg_puid; ! 125: uint8_t pcicfg_bus; ! 126: uint8_t pcicfg_devfn; ! 127: } __attribute__ ((packed)) e1k_st; ! 128: ! 129: /* ! 130: * local constants ! 131: ****************************************************************************** ! 132: */ ! 133: #define E1K_82540 ((uint64_t) 0x1) ! 134: #define E1K_82541 ((uint64_t) 0x2) ! 135: #define E1K_82544 ((uint64_t) 0x4) ! 136: #define E1K_82545 ((uint64_t) 0x8) ! 137: #define E1K_82546 ((uint64_t) 0x10) ! 138: #define E1K_82547 ((uint64_t) 0x20) ! 139: ! 140: #define IS_82541 ((m_e1k.m_device_u64 & E1K_82541) != 0) ! 141: #define IS_82546 ((m_e1k.m_device_u64 & E1K_82546) != 0) ! 142: #define IS_82547 ((m_e1k.m_device_u64 & E1K_82547) != 0) ! 143: ! 144: static const e1k_dev_t e1k_dev[] = { ! 145: { 0x1019, E1K_82547, "82547EI/GI Copper" }, ! 146: { 0x101A, E1K_82547, "82547EI Mobile" }, ! 147: { 0x1010, E1K_82546, "52546EB Copper, Dual Port" }, ! 148: { 0x1012, E1K_82546, "82546EB Fiber, Dual Port" }, ! 149: /* { 0x101D, E1K_82546, "82546EB Copper, Quad Port" }, */ ! 150: { 0x1079, E1K_82546, "82546GB Copper, Dual Port" }, ! 151: { 0x107A, E1K_82546, "82546GB Fiber, Dual Port" }, ! 152: { 0x107B, E1K_82546, "82546GB SerDes, Dual Port" }, ! 153: { 0x100F, E1K_82545, "82545EM Copper" }, ! 154: { 0x1011, E1K_82545, "82545EM Fiber" }, ! 155: { 0x1026, E1K_82545, "82545GM Copper" }, ! 156: { 0x1027, E1K_82545, "82545GM Fiber" }, ! 157: { 0x1028, E1K_82545, "82545GM SerDes" }, ! 158: { 0x1107, E1K_82544, "82544EI Copper" }, ! 159: { 0x1112, E1K_82544, "82544GC Copper" }, ! 160: { 0x1013, E1K_82541, "82541EI Copper" }, ! 161: { 0x1018, E1K_82541, "82541EI Mobile" }, ! 162: { 0x1076, E1K_82541, "82541GI Copper" }, ! 163: { 0x1077, E1K_82541, "82541GI Mobile" }, ! 164: { 0x1078, E1K_82541, "82541ER Copper" }, ! 165: { 0x107C, E1K_82541, "82541PI" }, ! 166: { 0x1015, E1K_82540, "82540EM Mobile" }, ! 167: { 0x1016, E1K_82540, "82540EP Mobile" }, ! 168: { 0x1017, E1K_82540, "82540EP Desktop" }, ! 169: { 0x100E, E1K_82540, "82540EM Desktop" }, ! 170: { 0 , 0 } ! 171: }; ! 172: ! 173: /* ! 174: * local variables ! 175: ****************************************************************************** ! 176: */ ! 177: static e1k_st m_e1k __attribute__ ((aligned(16))); ! 178: static long dma_offset; ! 179: ! 180: /* ! 181: * global functions ! 182: ****************************************************************************** ! 183: */ ! 184: int ! 185: check_driver(pci_config_t *pci_conf); ! 186: ! 187: ! 188: /* ! 189: * snk module interface ! 190: ****************************************************************************** ! 191: */ ! 192: static int e1k_init(void); ! 193: static int e1k_term(void); ! 194: static int e1k_xmit(char *f_buffer_pc, int f_len_i); ! 195: static int e1k_receive(char *f_buffer_pc, int f_len_i); ! 196: static int e1k_ioctl(int request, void* data); ! 197: ! 198: snk_module_t snk_module_interface = { ! 199: .version = 1, ! 200: .type = MOD_TYPE_NETWORK, ! 201: .running = 0, ! 202: .init = e1k_init, ! 203: .term = e1k_term, ! 204: .write = e1k_xmit, ! 205: .read = e1k_receive, ! 206: .ioctl = e1k_ioctl ! 207: }; ! 208: ! 209: ! 210: /** ! 211: * Translate virtual to "physical" address, ie. an address ! 212: * which can be used for DMA transfers. ! 213: */ ! 214: static uint64_t ! 215: virt2dma(void *addr) ! 216: { ! 217: return (uint64_t)addr + dma_offset; ! 218: } ! 219: ! 220: static void * ! 221: dma2virt(uint64_t addr) ! 222: { ! 223: return (void *)(addr - dma_offset); ! 224: } ! 225: ! 226: ! 227: /* ! 228: * local inline functions for e1k register access ! 229: ****************************************************************************** ! 230: */ ! 231: static uint32_t ! 232: e1k_rd32(uint16_t f_offs_u16) ! 233: { // caution: shall only be used after initialization! ! 234: return bswap_32(rd32(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16)); ! 235: } ! 236: ! 237: /* not used so far ! 238: static uint16_t ! 239: e1k_rd16(uint16_t f_offs_u16) ! 240: { // caution: shall only be used after initialization! ! 241: return bswap_16(rd16(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16)); ! 242: }*/ ! 243: ! 244: /* not used so far ! 245: static uint8_t ! 246: e1k_rd08(uint16_t f_offs_u16) ! 247: { // caution: shall only be used after initialization! ! 248: return rd08(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16); ! 249: }*/ ! 250: ! 251: static void ! 252: e1k_wr32(uint16_t f_offs_u16, uint32_t f_val_u32) ! 253: { // caution: shall only be used after initialization! ! 254: wr32(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16, bswap_32(f_val_u32)); ! 255: } ! 256: ! 257: /* not used so far ! 258: static void ! 259: e1k_wr16(uint16_t f_offs_u16, uint16_t f_val_u16) ! 260: { // caution: shall only be used after initialization! ! 261: wr16(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16, bswap_16(f_val_u16)); ! 262: }*/ ! 263: ! 264: /* not used so far ! 265: static void ! 266: e1k_wr08(uint16_t f_offs_u16, uint8_t f_val_u08) ! 267: { // caution: shall only be used after initialization! ! 268: wr08(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16, f_val_u08); ! 269: }*/ ! 270: ! 271: static void ! 272: e1k_setb32(uint16_t f_offs_u16, uint32_t f_mask_u32) ! 273: { ! 274: uint32_t v; ! 275: ! 276: v = e1k_rd32(f_offs_u16); ! 277: v |= f_mask_u32; ! 278: e1k_wr32(f_offs_u16, v); ! 279: } ! 280: ! 281: /* not used so far ! 282: static void ! 283: e1k_setb16(uint16_t f_offs_u16, uint16_t f_mask_u16) ! 284: { ! 285: uint16_t v; ! 286: v = e1k_rd16(f_offs_u16); ! 287: v |= f_mask_u16; ! 288: e1k_wr16(f_offs_u16, v); ! 289: }*/ ! 290: ! 291: /* not used so far ! 292: static void ! 293: e1k_setb08(uint16_t f_offs_u16, uint8_t f_mask_u08) ! 294: { ! 295: uint8_t v; ! 296: v = e1k_rd08(f_offs_u16); ! 297: v |= f_mask_u08; ! 298: e1k_wr08(f_offs_u16, v); ! 299: }*/ ! 300: ! 301: static void ! 302: e1k_clrb32(uint16_t f_offs_u16, uint32_t f_mask_u32) ! 303: { ! 304: uint32_t v; ! 305: ! 306: v = e1k_rd32(f_offs_u16); ! 307: v &= ~f_mask_u32; ! 308: e1k_wr32(f_offs_u16, v); ! 309: } ! 310: ! 311: /* not used so far ! 312: static void ! 313: e1k_clrb16(uint16_t f_offs_u16, uint16_t f_mask_u16) ! 314: { ! 315: uint16_t v; ! 316: ! 317: v = e1k_rd16(f_offs_u16); ! 318: v &= ~f_mask_u16; ! 319: e1k_wr16(f_offs_u16, v); ! 320: }*/ ! 321: ! 322: /* not used so far ! 323: static void ! 324: e1k_clrb08(uint16_t f_offs_u16, uint8_t f_mask_u08) ! 325: { ! 326: uint8_t v; ! 327: v = e1k_rd08(f_offs_u16); ! 328: v &= ~f_mask_u08; ! 329: e1k_wr08(f_offs_u16, v); ! 330: }*/ ! 331: ! 332: static int32_t ! 333: e1k_eep_rd16(uint8_t f_offs_u08, uint16_t *f_data_pu16) ! 334: { ! 335: uint32_t i; ! 336: uint32_t v; ! 337: int32_t done_shft; ! 338: int32_t addr_shft; ! 339: ! 340: if(IS_82541 || IS_82547) { ! 341: addr_shft = 2; ! 342: done_shft = 1; ! 343: } else { ! 344: addr_shft = 8; ! 345: done_shft = 4; ! 346: } ! 347: ! 348: /* ! 349: * initiate eeprom read ! 350: */ ! 351: e1k_wr32(EERD, ((uint32_t) f_offs_u08 << addr_shft) | // address ! 352: BIT32(0)); // start read ! 353: ! 354: /* ! 355: * wait for read done bit to be set ! 356: */ ! 357: i = 1000; ! 358: v = e1k_rd32(EERD); ! 359: while ((--i) && ! 360: ((v & BIT32(done_shft)) == 0)) { ! 361: ms_delay(1); ! 362: v = e1k_rd32(EERD); ! 363: } ! 364: ! 365: /* ! 366: * return on error ! 367: */ ! 368: if ((v & BIT32(done_shft)) == 0) { ! 369: return -1; ! 370: } ! 371: ! 372: /* ! 373: * return data ! 374: */ ! 375: *f_data_pu16 = (uint16_t) ((v >> 16) & 0xffff); ! 376: ! 377: return 0; ! 378: } ! 379: ! 380: /* ! 381: * ring initialization ! 382: */ ! 383: static void ! 384: e1k_init_receiver(void) ! 385: { ! 386: uint32_t i; ! 387: uint64_t addr; ! 388: ! 389: /* ! 390: * disable receiver for initialization ! 391: */ ! 392: e1k_wr32(RCTL, 0); ! 393: ! 394: /* ! 395: * clear receive desciptors and setup buffer pointers ! 396: */ ! 397: for (i = 0; i < E1K_NUM_RX_DESC; i++) { ! 398: memset((uint8_t *) &m_e1k.m_rx_ring_pst[i], 0, ! 399: sizeof(e1k_rx_desc_st)); ! 400: mb(); ! 401: ! 402: m_e1k.m_rx_ring_pst[i].m_buffer_u64 = ! 403: bswap_64(virt2dma(&m_e1k.m_rx_buffer_pu08[i][0])); ! 404: } ! 405: ! 406: /* ! 407: * initialize previously received index ! 408: */ ! 409: m_e1k.m_rx_next_u32 = 0; ! 410: ! 411: /* ! 412: * setup the base address and the length of the rx descriptor ring ! 413: */ ! 414: addr = virt2dma(&m_e1k.m_rx_ring_pst[0]); ! 415: e1k_wr32(RDBAH, (uint32_t) ((uint64_t) addr >> 32)); ! 416: e1k_wr32(RDBAL, (uint32_t) ((uint64_t) addr & 0xffffffff)); ! 417: e1k_wr32(RDLEN, E1K_NUM_RX_DESC * sizeof(e1k_rx_desc_st)); ! 418: ! 419: /* ! 420: * setup the rx head and tail descriptor indices ! 421: */ ! 422: e1k_wr32(RDH, 0); ! 423: e1k_wr32(RDT, E1K_NUM_RX_DESC - 1); ! 424: ! 425: /* ! 426: * setup the receive delay timer register ! 427: */ ! 428: e1k_wr32(RDTR, 0); ! 429: ! 430: /* ! 431: * setup the receive control register ! 432: */ ! 433: e1k_wr32(RCTL, BIT32( 1) | // enable receiver ! 434: BIT32( 4) | // enable multicast reception ! 435: BIT32(15)); // broadcast accept mode ! 436: // packet size 2048 ! 437: // no buffer extension ! 438: } ! 439: ! 440: static void ! 441: e1k_init_transmitter(void) ! 442: { ! 443: uint32_t i; ! 444: uint64_t addr; ! 445: ! 446: /* ! 447: * clear transmit desciptors and setup buffer pointers ! 448: */ ! 449: for (i = 0; i < E1K_NUM_TX_DESC; i++) { ! 450: memset((uint8_t *) &m_e1k.m_tx_ring_pst[i], 0, ! 451: sizeof(e1k_tx_desc_st)); ! 452: mb(); ! 453: ! 454: m_e1k.m_tx_ring_pst[i].m_buffer_u64 = ! 455: bswap_64(virt2dma(&m_e1k.m_tx_buffer_pu08[i][0])); ! 456: } ! 457: ! 458: /* ! 459: * setup the base address and the length of the tx descriptor ring ! 460: */ ! 461: addr = virt2dma(&m_e1k.m_tx_ring_pst[0]); ! 462: e1k_wr32(TDBAH, (uint32_t) ((uint64_t) addr >> 32)); ! 463: e1k_wr32(TDBAL, (uint32_t) ((uint64_t) addr & 0xffffffff)); ! 464: e1k_wr32(TDLEN, E1K_NUM_TX_DESC * sizeof(e1k_tx_desc_st)); ! 465: ! 466: /* ! 467: * setup the rx head and tail descriptor indices ! 468: */ ! 469: e1k_wr32(TDH, 0); ! 470: e1k_wr32(TDT, 0); ! 471: ! 472: /* ! 473: * initialize the transmit control register ! 474: */ ! 475: e1k_wr32(TCTL, BIT32(1) | // enable transmitter ! 476: BIT32(3) | // pad short packets ! 477: ((uint32_t) 0x0f << 4) | // collision threshhold ! 478: ((uint32_t) 0x40 << 12)); // collision distance ! 479: } ! 480: ! 481: static int32_t ! 482: e1k_mac_init(uint8_t *f_mac_pu08) ! 483: { ! 484: uint32_t l_ah_u32; ! 485: uint32_t l_al_u32; ! 486: uint32_t i; ! 487: uint32_t v; ! 488: ! 489: /* ! 490: * Use MAC address from device tree if possible ! 491: */ ! 492: for (i = 0, v = 0; i < 6; i++) { ! 493: v += (uint32_t) f_mac_pu08[i]; ! 494: } ! 495: ! 496: if (v != 0) { ! 497: /* ! 498: * use passed mac address for transmission to nic ! 499: */ ! 500: l_al_u32 = ((uint32_t) f_mac_pu08[3] << 24); ! 501: l_al_u32 |= ((uint32_t) f_mac_pu08[2] << 16); ! 502: l_al_u32 |= ((uint32_t) f_mac_pu08[1] << 8); ! 503: l_al_u32 |= ((uint32_t) f_mac_pu08[0] << 0); ! 504: l_ah_u32 = ((uint32_t) f_mac_pu08[5] << 8); ! 505: l_ah_u32 |= ((uint32_t) f_mac_pu08[4] << 0); ! 506: } else { ! 507: /* ! 508: * read mac address from eeprom ! 509: */ ! 510: uint16_t w[3]; // 3 16 bit words from eeprom ! 511: ! 512: for (i = 0; i < 3; i++) { ! 513: if (e1k_eep_rd16(EEPROM_MAC_OFFS + i, &w[i]) != 0) { ! 514: printk("Failed to read MAC address from EEPROM!\n"); ! 515: return -1; ! 516: } ! 517: } ! 518: ! 519: /* ! 520: * invert the least significant bit for 82546 dual port ! 521: * if the second device is in use (remember word is byteswapped) ! 522: */ ! 523: if ((IS_82546) && ! 524: ((e1k_rd32(STATUS) & BIT32(2)) != 0)) { ! 525: w[2] ^= (uint16_t) 0x100; ! 526: } ! 527: ! 528: /* ! 529: * store mac address for transmission to nic ! 530: */ ! 531: l_ah_u32 = ((uint32_t) w[2] << 0); ! 532: l_al_u32 = ((uint32_t) w[1] << 16); ! 533: l_al_u32 |= ((uint32_t) w[0] << 0); ! 534: ! 535: /* ! 536: * return mac address ! 537: * mac address in eeprom is stored byteswapped ! 538: */ ! 539: f_mac_pu08[1] = (uint8_t) ((w[0] >> 8) & 0xff); ! 540: f_mac_pu08[0] = (uint8_t) ((w[0] >> 0) & 0xff); ! 541: f_mac_pu08[3] = (uint8_t) ((w[1] >> 8) & 0xff); ! 542: f_mac_pu08[2] = (uint8_t) ((w[1] >> 0) & 0xff); ! 543: f_mac_pu08[5] = (uint8_t) ((w[2] >> 8) & 0xff); ! 544: f_mac_pu08[4] = (uint8_t) ((w[2] >> 0) & 0xff); ! 545: } ! 546: ! 547: /* ! 548: * insert mac address in receive address register ! 549: * and set AV bit ! 550: */ ! 551: e1k_wr32(RAL0, l_al_u32); ! 552: e1k_wr32(RAH0, l_ah_u32 | BIT32(31)); ! 553: ! 554: /* ! 555: * clear remaining receive address registers ! 556: */ ! 557: for (i = 1; i < NUM_MAC_ADDR; i++) { ! 558: e1k_wr32(RAL0 + i * sizeof(uint64_t), 0); ! 559: e1k_wr32(RAH0 + i * sizeof(uint64_t), 0); ! 560: } ! 561: ! 562: return 0; ! 563: } ! 564: ! 565: ! 566: /* ! 567: * interface ! 568: ****************************************************************************** ! 569: */ ! 570: ! 571: /* ! 572: * e1k_receive ! 573: */ ! 574: static int ! 575: e1k_receive(char *f_buffer_pc, int f_len_i) ! 576: { ! 577: uint32_t l_rdh_u32 = e1k_rd32(RDH); // this includes needed dummy read ! 578: e1k_rx_desc_st *rx; ! 579: int l_ret_i; ! 580: ! 581: #ifdef E1K_DEBUG ! 582: #ifdef E1K_SHOW_RCV_DATA ! 583: int i; ! 584: #endif ! 585: #endif ! 586: ! 587: /* ! 588: * check whether new packets have arrived ! 589: */ ! 590: if (m_e1k.m_rx_next_u32 == l_rdh_u32) { ! 591: return 0; ! 592: } ! 593: ! 594: /* ! 595: * get a pointer to the next rx descriptor for ease of use ! 596: */ ! 597: rx = &m_e1k.m_rx_ring_pst[m_e1k.m_rx_next_u32]; ! 598: ! 599: /* ! 600: * check whether the descriptor done bit is set ! 601: */ ! 602: if ((rx->m_sta_u08 & 0x1) == 0) { ! 603: return 0; ! 604: } ! 605: ! 606: /* ! 607: * get the length of the packet, throw away checksum ! 608: */ ! 609: l_ret_i = (int) bswap_16(rx->m_len_u16) - (int) 4; ! 610: ! 611: /* ! 612: * copy the data ! 613: */ ! 614: memcpy((uint8_t *) f_buffer_pc, dma2virt(bswap_64(rx->m_buffer_u64)), ! 615: (size_t) l_ret_i); ! 616: ! 617: #ifdef E1K_DEBUG ! 618: #if defined(E1K_SHOW_RCV) || defined(E1K_SHOW_RCV_DATA) ! 619: printk("e1k: %d bytes received\n", l_ret_i); ! 620: #endif ! 621: ! 622: #ifdef E1K_SHOW_RCV_DATA ! 623: for (i = 0; i < l_ret_i; i++) { ! 624: ! 625: if ((i & 0x1f) == 0) { ! 626: printk("\n "); ! 627: } ! 628: ! 629: printk("%02X ", f_buffer_pc[i]); ! 630: } ! 631: ! 632: printk("\n\n"); ! 633: #endif ! 634: #endif ! 635: ! 636: /* ! 637: * clear descriptor for reusage, but leave buffer pointer untouched ! 638: */ ! 639: memset((uint8_t *) &rx->m_len_u16, 0, ! 640: sizeof(e1k_rx_desc_st) - sizeof(uint64_t)); ! 641: mb(); ! 642: ! 643: /* ! 644: * write new tail pointer ! 645: */ ! 646: e1k_wr32(RDT, m_e1k.m_rx_next_u32); ! 647: ! 648: /* ! 649: * update next receive index ! 650: */ ! 651: m_e1k.m_rx_next_u32 = (m_e1k.m_rx_next_u32 + 1) & (E1K_NUM_RX_DESC - 1); ! 652: ! 653: return l_ret_i; ! 654: } ! 655: ! 656: static int ! 657: e1k_xmit(char *f_buffer_pc, int f_len_i) ! 658: { ! 659: uint32_t l_tdh_u32 = e1k_rd32(TDH); ! 660: uint32_t l_tdt_u32 = e1k_rd32(TDT); ! 661: uint32_t l_pre_u32 = (l_tdh_u32 + (E1K_NUM_TX_DESC - 1)) & ! 662: (E1K_NUM_TX_DESC - 1); ! 663: e1k_tx_desc_st *tx; ! 664: #if defined(E1K_DEBUG) && defined(E1K_SHOW_XMIT_DATA) ! 665: int i; ! 666: #endif ! 667: ! 668: /* ! 669: * check for available buffers ! 670: */ ! 671: if (l_pre_u32 == l_tdt_u32) { ! 672: return 0; ! 673: } ! 674: ! 675: /* ! 676: * get a pointer to the next tx descriptor for ease of use ! 677: */ ! 678: tx = &m_e1k.m_tx_ring_pst[l_tdt_u32]; ! 679: ! 680: /* ! 681: * copy the data ! 682: */ ! 683: memcpy(dma2virt(bswap_64(tx->m_buffer_u64)), (uint8_t *) f_buffer_pc, ! 684: (size_t) f_len_i); ! 685: ! 686: /* ! 687: * insert length & command flags ! 688: */ ! 689: tx->m_len_u16 = bswap_16((uint16_t) f_len_i); ! 690: tx->m_cmd_u08 = (BIT08(0) | // EOP ! 691: BIT08(1)); // IFCS ! 692: tx->m_sta_u08 = 0; ! 693: mb(); ! 694: ! 695: /* ! 696: * update tail index ! 697: */ ! 698: l_tdt_u32 = (l_tdt_u32 + 1) & (E1K_NUM_TX_DESC - 1); ! 699: e1k_wr32(TDT, l_tdt_u32); ! 700: ! 701: #ifdef E1K_DEBUG ! 702: #if defined(E1K_SHOW_XMIT) || defined(E1K_SHOW_XMIT_DATA) ! 703: printk("e1k: %d bytes transmitted\n", bswap_16(tx->m_len_u16)); ! 704: #endif ! 705: ! 706: #ifdef E1K_SHOW_XMIT_DATA ! 707: for (i = 0; i < bswap_16(tx->m_len_u16); i++) { ! 708: ! 709: if ((i & 0x1f) == 0) { ! 710: printk("\n "); ! 711: } ! 712: ! 713: f_buffer_pc = dma2virt(bswap_64(tx->m_buffer_u64)); ! 714: printk("%02X ", f_buffer_pc[i]); ! 715: } ! 716: ! 717: printk("\n\n"); ! 718: #endif ! 719: #endif ! 720: ! 721: return f_len_i; ! 722: } ! 723: ! 724: int ! 725: check_driver(pci_config_t *pci_conf) ! 726: { ! 727: uint64_t i; ! 728: ! 729: /* ! 730: * checks whether the driver is handling this device ! 731: * by verifying vendor & device id ! 732: * vendor id 0x8086 == Intel ! 733: */ ! 734: if (pci_conf->vendor_id != 0x8086) { ! 735: #ifdef E1K_DEBUG ! 736: printk("e1k: netdevice with vendor id %04X not supported\n", ! 737: pci_conf->vendor_id); ! 738: #endif ! 739: return -1; ! 740: } ! 741: ! 742: for (i = 0; e1k_dev[i].m_dev_u32 != 0; i++) { ! 743: if (e1k_dev[i].m_dev_u32 == (uint32_t) pci_conf->device_id) { ! 744: break; ! 745: } ! 746: } ! 747: ! 748: if (e1k_dev[i].m_dev_u32 == 0) { ! 749: #ifdef E1K_DEBUG ! 750: printk("e1k: netdevice with device id %04X not supported\n", ! 751: pci_conf->device_id); ! 752: #endif ! 753: return -1; ! 754: } ! 755: ! 756: /* ! 757: * initialize static variables ! 758: */ ! 759: m_e1k.m_device_u64 = e1k_dev[i].m_devmsk_u64; ! 760: m_e1k.m_baseaddr_u64 = 0; ! 761: m_e1k.pcicfg_puid = pci_conf->puid; ! 762: m_e1k.pcicfg_bus = pci_conf->bus; ! 763: m_e1k.pcicfg_devfn = pci_conf->devfn; ! 764: ! 765: // success ! 766: #ifdef E1K_DEBUG ! 767: printk("e1k: found device %s\n", e1k_dev[i].m_name); ! 768: #endif ! 769: ! 770: return 0; ! 771: } ! 772: ! 773: static int ! 774: e1k_init(void) ! 775: { ! 776: uint32_t i; ! 777: uint32_t v; ! 778: char *mac_addr = snk_module_interface.mac_addr; ! 779: ! 780: if (snk_module_interface.running != 0) { ! 781: return 0; ! 782: } ! 783: ! 784: #ifdef E1K_DEBUG ! 785: printk("\ne1k: initializing\n"); ! 786: #endif ! 787: ! 788: dma_offset = snk_kernel_interface->dma_map_in(&m_e1k, sizeof(m_e1k), 0); ! 789: #ifdef E1K_DEBUG ! 790: printk("e1k: dma offset: %lx - %lx = %lx\n", dma_offset, (long)&m_e1k, ! 791: dma_offset - (long)&m_e1k); ! 792: #endif ! 793: dma_offset = dma_offset - (long)&m_e1k; ! 794: ! 795: /* ! 796: * setup register & memory base addresses of NIC ! 797: */ ! 798: m_e1k.m_baseaddr_u64 = (uint64_t) ((uint32_t) ~0xf & (uint32_t) ! 799: snk_kernel_interface->pci_config_read(m_e1k.pcicfg_puid, ! 800: 4, ! 801: m_e1k.pcicfg_bus, ! 802: m_e1k.pcicfg_devfn, ! 803: PCI_BAR1_R)); ! 804: #ifdef E1K_DEBUG ! 805: printk("e1k: base address register = 0x%lx\n", m_e1k.m_baseaddr_u64); ! 806: #endif ! 807: ! 808: snk_kernel_interface->translate_addr(((void *) &m_e1k.m_baseaddr_u64)); ! 809: ! 810: #ifdef E1K_DEBUG ! 811: printk("e1k: PCI-Puid = 0x%llX\n", m_e1k.pcicfg_puid); ! 812: printk("e1k: PCI-Bus = 0x%X\n", m_e1k.pcicfg_bus); ! 813: printk("e1k: PCI-DevFn = 0x%X\n", m_e1k.pcicfg_devfn); ! 814: printk("e1k: device's register base address = 0x%lx\n", ! 815: m_e1k.m_baseaddr_u64); ! 816: #endif ! 817: ! 818: /* ! 819: * e1k hardware initialization ! 820: */ ! 821: ! 822: /* ! 823: * save pci command register ! 824: */ ! 825: m_e1k.m_com_r_u16 = (uint16_t) ! 826: snk_kernel_interface->pci_config_read(m_e1k.pcicfg_puid, ! 827: 2, ! 828: m_e1k.pcicfg_bus, ! 829: m_e1k.pcicfg_devfn, ! 830: PCI_COM_R); ! 831: ! 832: /* ! 833: * bus mastering does not need to be enabled, it is already set ! 834: // enable bus master & memory space in command reg ! 835: i = (BIT32(10) | BIT32(2) | BIT32(1)); ! 836: snk_kernel_interface->pci_config_write(m_e1k.pcicfg_puid, ! 837: 2, ! 838: m_e1k.pcicfg_bus, ! 839: m_e1k.pcicfg_devfn, ! 840: PCI_COM_R, ! 841: (int) i); ! 842: */ ! 843: ! 844: /* ! 845: * at first disable all interrupts ! 846: */ ! 847: e1k_wr32(IMC, (uint32_t) ~0); ! 848: ! 849: /* ! 850: * check for link up ! 851: */ ! 852: #ifdef E1K_DEBUG ! 853: printk("e1k: checking link status..\n"); ! 854: #endif ! 855: ! 856: i = 50; ! 857: v = e1k_rd32(STATUS); ! 858: while ((--i) && ! 859: ((v & BIT32(1)) == 0)) { ! 860: ms_delay(100); ! 861: v = e1k_rd32(STATUS); ! 862: } ! 863: ! 864: if ((v & BIT32(1)) == 0) { ! 865: #ifdef E1K_DEBUG ! 866: printk("e1k: link is down.\n"); ! 867: printk(" terminating.\n"); ! 868: #endif ! 869: ! 870: return -1; ! 871: } ! 872: ! 873: #ifdef E1K_DEBUG ! 874: printk("e1k: link is up\n"); ! 875: ! 876: switch ((v >> 6) & 0x3) { ! 877: case 0: { ! 878: printk(" 10 Mb/s\n"); ! 879: } break; ! 880: case 1: { ! 881: printk(" 100 Mb/s\n"); ! 882: } break; ! 883: case 2: ! 884: case 3: { ! 885: printk(" 1000 Mb/s\n"); ! 886: } break; ! 887: } ! 888: ! 889: if ((v & BIT32(0)) == 0) { ! 890: printk(" half-duplex\n"); ! 891: } else { ! 892: printk(" full-duplex\n"); ! 893: } ! 894: #endif ! 895: ! 896: /* ! 897: * initialize mac address ! 898: */ ! 899: #ifdef E1K_DEBUG ! 900: printk("e1k: initializing mac address.. "); ! 901: #endif ! 902: if (e1k_mac_init((uint8_t *)mac_addr) != 0) { ! 903: #ifdef E1K_DEBUG ! 904: printk("failed.\n"); ! 905: printk(" terminating.\n"); ! 906: #endif ! 907: ! 908: return -1; ! 909: } ! 910: ! 911: #ifdef E1K_DEBUG ! 912: printk("done.\n"); ! 913: printk(" mac address = %02X:%02X:%02X:%02X:%02X:%02X\n", ! 914: mac_addr[0], mac_addr[1], mac_addr[2], ! 915: mac_addr[3], mac_addr[4], mac_addr[5]); ! 916: #endif ! 917: ! 918: /* ! 919: * initialize transmitter ! 920: */ ! 921: #ifdef E1K_DEBUG ! 922: printk("e1k: initializing transmitter.. "); ! 923: #endif ! 924: e1k_init_transmitter(); ! 925: #ifdef E1K_DEBUG ! 926: printk("done.\n"); ! 927: #endif ! 928: ! 929: /* ! 930: * initialize receiver ! 931: */ ! 932: #ifdef E1K_DEBUG ! 933: printk("e1k: initializing receiver.. "); ! 934: #endif ! 935: e1k_init_receiver(); ! 936: #ifdef E1K_DEBUG ! 937: printk("done.\n"); ! 938: printk("e1k: initialization complete\n"); ! 939: #endif ! 940: ! 941: snk_module_interface.running = 1; ! 942: ! 943: return 0; ! 944: } ! 945: ! 946: static int ! 947: e1k_reset(void) ! 948: { ! 949: /* ! 950: * reset the PHY ! 951: */ ! 952: e1k_setb32(CTRL, BIT32(31)); ! 953: ms_delay(10); ! 954: ! 955: /* ! 956: * reset the MAC ! 957: */ ! 958: e1k_setb32(CTRL, BIT32(26)); ! 959: ms_delay(10); ! 960: ! 961: return 0; ! 962: } ! 963: ! 964: static int ! 965: e1k_term(void) ! 966: { ! 967: if (snk_module_interface.running == 0) { ! 968: return 0; ! 969: } ! 970: ! 971: #ifdef E1K_DEBUG ! 972: printk("e1k: shutdown.. "); ! 973: #endif ! 974: ! 975: /* ! 976: * disable receiver & transmitter ! 977: */ ! 978: e1k_wr32(RCTL, 0); ! 979: e1k_wr32(TCTL, 0); ! 980: ms_delay(10); ! 981: ! 982: /* ! 983: * reset the ring indices ! 984: */ ! 985: e1k_wr32(RDH, 0); ! 986: e1k_wr32(RDT, 0); ! 987: e1k_wr32(TDH, 0); ! 988: e1k_wr32(TDT, 0); ! 989: ! 990: /* ! 991: * disable receive address ! 992: */ ! 993: e1k_clrb32(RAH0, BIT32(31)); ! 994: ! 995: /* ! 996: * reset the mac/phy ! 997: */ ! 998: e1k_reset(); ! 999: ! 1000: /* ! 1001: * reset pci command register ! 1002: */ ! 1003: snk_kernel_interface->pci_config_write(m_e1k.pcicfg_puid, ! 1004: 2, ! 1005: m_e1k.pcicfg_bus, ! 1006: m_e1k.pcicfg_devfn, ! 1007: PCI_COM_R, ! 1008: (int) m_e1k.m_com_r_u16); ! 1009: ! 1010: /* ! 1011: * Disable DMA translation ! 1012: */ ! 1013: snk_kernel_interface->dma_map_out(&m_e1k, virt2dma(&m_e1k), ! 1014: sizeof(m_e1k)); ! 1015: ! 1016: #ifdef E1K_DEBUG ! 1017: printk("done.\n"); ! 1018: #endif ! 1019: ! 1020: snk_module_interface.running = 0; ! 1021: return 0; ! 1022: } ! 1023: ! 1024: static int ! 1025: e1k_ioctl(int request, void* data) ! 1026: { ! 1027: return 0; ! 1028: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.