|
|
1.1 ! root 1: /* Advanced Micro Devices Inc. AMD8111E Linux Network Driver ! 2: * Copyright (C) 2004 Advanced Micro Devices ! 3: * Copyright (C) 2005 Liu Tao <[email protected]> [etherboot port] ! 4: * ! 5: * Copyright 2001,2002 Jeff Garzik <[email protected]> [ 8139cp.c,tg3.c ] ! 6: * Copyright (C) 2001, 2002 David S. Miller ([email protected])[ tg3.c] ! 7: * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ] ! 8: * Derived from the lance driver written 1993,1994,1995 by Donald Becker. ! 9: * Copyright 1993 United States Government as represented by the ! 10: * Director, National Security Agency.[ pcnet32.c ] ! 11: * Carsten Langgaard, [email protected] [ pcnet32.c ] ! 12: * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. ! 13: * ! 14: * ! 15: * This program is free software; you can redistribute it and/or modify ! 16: * it under the terms of the GNU General Public License as published by ! 17: * the Free Software Foundation; either version 2 of the License, or ! 18: * (at your option) any later version. ! 19: * ! 20: * This program is distributed in the hope that it will be useful, ! 21: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 22: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 23: * GNU General Public License for more details. ! 24: * ! 25: * You should have received a copy of the GNU General Public License ! 26: * along with this program; if not, write to the Free Software ! 27: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ! 28: * USA ! 29: */ ! 30: ! 31: FILE_LICENCE ( GPL2_OR_LATER ); ! 32: ! 33: #include "etherboot.h" ! 34: #include "nic.h" ! 35: #include "mii.h" ! 36: #include <ipxe/pci.h> ! 37: #include <ipxe/ethernet.h> ! 38: #include "string.h" ! 39: #include "stdint.h" ! 40: #include "amd8111e.h" ! 41: ! 42: ! 43: /* driver definitions */ ! 44: #define NUM_TX_SLOTS 2 ! 45: #define NUM_RX_SLOTS 4 ! 46: #define TX_SLOTS_MASK 1 ! 47: #define RX_SLOTS_MASK 3 ! 48: ! 49: #define TX_BUF_LEN 1536 ! 50: #define RX_BUF_LEN 1536 ! 51: ! 52: #define TX_PKT_LEN_MAX (ETH_FRAME_LEN - ETH_HLEN) ! 53: #define RX_PKT_LEN_MIN 60 ! 54: #define RX_PKT_LEN_MAX ETH_FRAME_LEN ! 55: ! 56: #define TX_TIMEOUT 3000 ! 57: #define TX_PROCESS_TIME 10 ! 58: #define TX_RETRY (TX_TIMEOUT / TX_PROCESS_TIME) ! 59: ! 60: #define PHY_RW_RETRY 10 ! 61: ! 62: ! 63: struct amd8111e_tx_desc { ! 64: u16 buf_len; ! 65: u16 tx_flags; ! 66: u16 tag_ctrl_info; ! 67: u16 tag_ctrl_cmd; ! 68: u32 buf_phy_addr; ! 69: u32 reserved; ! 70: }; ! 71: ! 72: struct amd8111e_rx_desc { ! 73: u32 reserved; ! 74: u16 msg_len; ! 75: u16 tag_ctrl_info; ! 76: u16 buf_len; ! 77: u16 rx_flags; ! 78: u32 buf_phy_addr; ! 79: }; ! 80: ! 81: struct eth_frame { ! 82: u8 dst_addr[ETH_ALEN]; ! 83: u8 src_addr[ETH_ALEN]; ! 84: u16 type; ! 85: u8 data[ETH_FRAME_LEN - ETH_HLEN]; ! 86: } __attribute__((packed)); ! 87: ! 88: struct amd8111e_priv { ! 89: struct amd8111e_tx_desc tx_ring[NUM_TX_SLOTS]; ! 90: struct amd8111e_rx_desc rx_ring[NUM_RX_SLOTS]; ! 91: unsigned char tx_buf[NUM_TX_SLOTS][TX_BUF_LEN]; ! 92: unsigned char rx_buf[NUM_RX_SLOTS][RX_BUF_LEN]; ! 93: unsigned long tx_idx, rx_idx; ! 94: int tx_consistent; ! 95: ! 96: char opened; ! 97: char link; ! 98: char speed; ! 99: char duplex; ! 100: int ext_phy_addr; ! 101: u32 ext_phy_id; ! 102: ! 103: struct pci_device *pdev; ! 104: struct nic *nic; ! 105: void *mmio; ! 106: }; ! 107: ! 108: static struct amd8111e_priv amd8111e; ! 109: ! 110: ! 111: /******************************************************** ! 112: * locale functions * ! 113: ********************************************************/ ! 114: static void amd8111e_init_hw_default(struct amd8111e_priv *lp); ! 115: static int amd8111e_start(struct amd8111e_priv *lp); ! 116: static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val); ! 117: #if 0 ! 118: static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val); ! 119: #endif ! 120: static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp); ! 121: static void amd8111e_disable_interrupt(struct amd8111e_priv *lp); ! 122: static void amd8111e_enable_interrupt(struct amd8111e_priv *lp); ! 123: static void amd8111e_force_interrupt(struct amd8111e_priv *lp); ! 124: static int amd8111e_get_mac_address(struct amd8111e_priv *lp); ! 125: static int amd8111e_init_rx_ring(struct amd8111e_priv *lp); ! 126: static int amd8111e_init_tx_ring(struct amd8111e_priv *lp); ! 127: static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index); ! 128: static void amd8111e_wait_link(struct amd8111e_priv *lp); ! 129: static void amd8111e_poll_link(struct amd8111e_priv *lp); ! 130: static void amd8111e_restart(struct amd8111e_priv *lp); ! 131: ! 132: ! 133: /* ! 134: * This function clears necessary the device registers. ! 135: */ ! 136: static void amd8111e_init_hw_default(struct amd8111e_priv *lp) ! 137: { ! 138: unsigned int reg_val; ! 139: void *mmio = lp->mmio; ! 140: ! 141: /* stop the chip */ ! 142: writel(RUN, mmio + CMD0); ! 143: ! 144: /* Clear RCV_RING_BASE_ADDR */ ! 145: writel(0, mmio + RCV_RING_BASE_ADDR0); ! 146: ! 147: /* Clear XMT_RING_BASE_ADDR */ ! 148: writel(0, mmio + XMT_RING_BASE_ADDR0); ! 149: writel(0, mmio + XMT_RING_BASE_ADDR1); ! 150: writel(0, mmio + XMT_RING_BASE_ADDR2); ! 151: writel(0, mmio + XMT_RING_BASE_ADDR3); ! 152: ! 153: /* Clear CMD0 */ ! 154: writel(CMD0_CLEAR, mmio + CMD0); ! 155: ! 156: /* Clear CMD2 */ ! 157: writel(CMD2_CLEAR, mmio + CMD2); ! 158: ! 159: /* Clear CMD7 */ ! 160: writel(CMD7_CLEAR, mmio + CMD7); ! 161: ! 162: /* Clear DLY_INT_A and DLY_INT_B */ ! 163: writel(0x0, mmio + DLY_INT_A); ! 164: writel(0x0, mmio + DLY_INT_B); ! 165: ! 166: /* Clear FLOW_CONTROL */ ! 167: writel(0x0, mmio + FLOW_CONTROL); ! 168: ! 169: /* Clear INT0 write 1 to clear register */ ! 170: reg_val = readl(mmio + INT0); ! 171: writel(reg_val, mmio + INT0); ! 172: ! 173: /* Clear STVAL */ ! 174: writel(0x0, mmio + STVAL); ! 175: ! 176: /* Clear INTEN0 */ ! 177: writel(INTEN0_CLEAR, mmio + INTEN0); ! 178: ! 179: /* Clear LADRF */ ! 180: writel(0x0, mmio + LADRF); ! 181: ! 182: /* Set SRAM_SIZE & SRAM_BOUNDARY registers */ ! 183: writel(0x80010, mmio + SRAM_SIZE); ! 184: ! 185: /* Clear RCV_RING0_LEN */ ! 186: writel(0x0, mmio + RCV_RING_LEN0); ! 187: ! 188: /* Clear XMT_RING0/1/2/3_LEN */ ! 189: writel(0x0, mmio + XMT_RING_LEN0); ! 190: writel(0x0, mmio + XMT_RING_LEN1); ! 191: writel(0x0, mmio + XMT_RING_LEN2); ! 192: writel(0x0, mmio + XMT_RING_LEN3); ! 193: ! 194: /* Clear XMT_RING_LIMIT */ ! 195: writel(0x0, mmio + XMT_RING_LIMIT); ! 196: ! 197: /* Clear MIB */ ! 198: writew(MIB_CLEAR, mmio + MIB_ADDR); ! 199: ! 200: /* Clear LARF */ ! 201: writel( 0, mmio + LADRF); ! 202: writel( 0, mmio + LADRF + 4); ! 203: ! 204: /* SRAM_SIZE register */ ! 205: reg_val = readl(mmio + SRAM_SIZE); ! 206: ! 207: /* Set default value to CTRL1 Register */ ! 208: writel(CTRL1_DEFAULT, mmio + CTRL1); ! 209: ! 210: /* To avoid PCI posting bug */ ! 211: readl(mmio + CMD2); ! 212: } ! 213: ! 214: /* ! 215: * This function initializes the device registers and starts the device. ! 216: */ ! 217: static int amd8111e_start(struct amd8111e_priv *lp) ! 218: { ! 219: struct nic *nic = lp->nic; ! 220: void *mmio = lp->mmio; ! 221: int i, reg_val; ! 222: ! 223: /* stop the chip */ ! 224: writel(RUN, mmio + CMD0); ! 225: ! 226: /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */ ! 227: writew(0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0); ! 228: ! 229: /* enable the port manager and set auto negotiation always */ ! 230: writel(VAL1 | EN_PMGR, mmio + CMD3 ); ! 231: writel(XPHYANE | XPHYRST, mmio + CTRL2); ! 232: ! 233: /* set control registers */ ! 234: reg_val = readl(mmio + CTRL1); ! 235: reg_val &= ~XMTSP_MASK; ! 236: writel(reg_val | XMTSP_128 | CACHE_ALIGN, mmio + CTRL1); ! 237: ! 238: /* initialize tx and rx ring base addresses */ ! 239: amd8111e_init_tx_ring(lp); ! 240: amd8111e_init_rx_ring(lp); ! 241: writel(virt_to_bus(lp->tx_ring), mmio + XMT_RING_BASE_ADDR0); ! 242: writel(virt_to_bus(lp->rx_ring), mmio + RCV_RING_BASE_ADDR0); ! 243: writew(NUM_TX_SLOTS, mmio + XMT_RING_LEN0); ! 244: writew(NUM_RX_SLOTS, mmio + RCV_RING_LEN0); ! 245: ! 246: /* set default IPG to 96 */ ! 247: writew(DEFAULT_IPG, mmio + IPG); ! 248: writew(DEFAULT_IPG - IFS1_DELTA, mmio + IFS1); ! 249: ! 250: /* AutoPAD transmit, Retransmit on Underflow */ ! 251: writel(VAL0 | APAD_XMT | REX_RTRY | REX_UFLO, mmio + CMD2); ! 252: ! 253: /* JUMBO disabled */ ! 254: writel(JUMBO, mmio + CMD3); ! 255: ! 256: /* Setting the MAC address to the device */ ! 257: for(i = 0; i < ETH_ALEN; i++) ! 258: writeb(nic->node_addr[i], mmio + PADR + i); ! 259: ! 260: /* set RUN bit to start the chip, interrupt not enabled */ ! 261: writel(VAL2 | RDMD0 | VAL0 | RUN, mmio + CMD0); ! 262: ! 263: /* To avoid PCI posting bug */ ! 264: readl(mmio + CMD0); ! 265: return 0; ! 266: } ! 267: ! 268: /* ! 269: This function will read the PHY registers. ! 270: */ ! 271: static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val) ! 272: { ! 273: void *mmio = lp->mmio; ! 274: unsigned int reg_val; ! 275: unsigned int retry = PHY_RW_RETRY; ! 276: ! 277: reg_val = readl(mmio + PHY_ACCESS); ! 278: while (reg_val & PHY_CMD_ACTIVE) ! 279: reg_val = readl(mmio + PHY_ACCESS); ! 280: ! 281: writel(PHY_RD_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16), ! 282: mmio + PHY_ACCESS); ! 283: do { ! 284: reg_val = readl(mmio + PHY_ACCESS); ! 285: udelay(30); /* It takes 30 us to read/write data */ ! 286: } while (--retry && (reg_val & PHY_CMD_ACTIVE)); ! 287: ! 288: if (reg_val & PHY_RD_ERR) { ! 289: *val = 0; ! 290: return -1; ! 291: } ! 292: ! 293: *val = reg_val & 0xffff; ! 294: return 0; ! 295: } ! 296: ! 297: /* ! 298: This function will write into PHY registers. ! 299: */ ! 300: #if 0 ! 301: static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val) ! 302: { ! 303: void *mmio = lp->mmio; ! 304: unsigned int reg_val; ! 305: unsigned int retry = PHY_RW_RETRY; ! 306: ! 307: reg_val = readl(mmio + PHY_ACCESS); ! 308: while (reg_val & PHY_CMD_ACTIVE) ! 309: reg_val = readl(mmio + PHY_ACCESS); ! 310: ! 311: writel(PHY_WR_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16) | val, ! 312: mmio + PHY_ACCESS); ! 313: do { ! 314: reg_val = readl(mmio + PHY_ACCESS); ! 315: udelay(30); /* It takes 30 us to read/write the data */ ! 316: } while (--retry && (reg_val & PHY_CMD_ACTIVE)); ! 317: ! 318: if(reg_val & PHY_RD_ERR) ! 319: return -1; ! 320: ! 321: return 0; ! 322: } ! 323: #endif ! 324: ! 325: static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp) ! 326: { ! 327: int i; ! 328: ! 329: lp->ext_phy_id = 0; ! 330: lp->ext_phy_addr = 1; ! 331: ! 332: for (i = 0x1e; i >= 0; i--) { ! 333: u32 id1, id2; ! 334: ! 335: if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1)) ! 336: continue; ! 337: if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2)) ! 338: continue; ! 339: lp->ext_phy_id = (id1 << 16) | id2; ! 340: lp->ext_phy_addr = i; ! 341: break; ! 342: } ! 343: ! 344: if (lp->ext_phy_id) ! 345: printf("Found MII PHY ID 0x%08x at address 0x%02x\n", ! 346: (unsigned int) lp->ext_phy_id, lp->ext_phy_addr); ! 347: else ! 348: printf("Couldn't detect MII PHY, assuming address 0x01\n"); ! 349: } ! 350: ! 351: static void amd8111e_disable_interrupt(struct amd8111e_priv *lp) ! 352: { ! 353: void *mmio = lp->mmio; ! 354: unsigned int int0; ! 355: ! 356: writel(INTREN, mmio + CMD0); ! 357: writel(INTEN0_CLEAR, mmio + INTEN0); ! 358: int0 = readl(mmio + INT0); ! 359: writel(int0, mmio + INT0); ! 360: readl(mmio + INT0); ! 361: } ! 362: ! 363: static void amd8111e_enable_interrupt(struct amd8111e_priv *lp) ! 364: { ! 365: void *mmio = lp->mmio; ! 366: ! 367: writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0); ! 368: writel(VAL0 | INTREN, mmio + CMD0); ! 369: readl(mmio + CMD0); ! 370: } ! 371: ! 372: static void amd8111e_force_interrupt(struct amd8111e_priv *lp) ! 373: { ! 374: void *mmio = lp->mmio; ! 375: ! 376: writel(VAL0 | UINTCMD, mmio + CMD0); ! 377: readl(mmio + CMD0); ! 378: } ! 379: ! 380: static int amd8111e_get_mac_address(struct amd8111e_priv *lp) ! 381: { ! 382: struct nic *nic = lp->nic; ! 383: void *mmio = lp->mmio; ! 384: int i; ! 385: ! 386: /* BIOS should have set mac address to PADR register, ! 387: * so we read PADR to get it. ! 388: */ ! 389: for (i = 0; i < ETH_ALEN; i++) ! 390: nic->node_addr[i] = readb(mmio + PADR + i); ! 391: ! 392: DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) ); ! 393: ! 394: return 0; ! 395: } ! 396: ! 397: static int amd8111e_init_rx_ring(struct amd8111e_priv *lp) ! 398: { ! 399: int i; ! 400: ! 401: lp->rx_idx = 0; ! 402: ! 403: /* Initilaizing receive descriptors */ ! 404: for (i = 0; i < NUM_RX_SLOTS; i++) { ! 405: lp->rx_ring[i].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[i])); ! 406: lp->rx_ring[i].buf_len = cpu_to_le16(RX_BUF_LEN); ! 407: wmb(); ! 408: lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT); ! 409: } ! 410: ! 411: return 0; ! 412: } ! 413: ! 414: static int amd8111e_init_tx_ring(struct amd8111e_priv *lp) ! 415: { ! 416: int i; ! 417: ! 418: lp->tx_idx = 0; ! 419: lp->tx_consistent = 1; ! 420: ! 421: /* Initializing transmit descriptors */ ! 422: for (i = 0; i < NUM_TX_SLOTS; i++) { ! 423: lp->tx_ring[i].tx_flags = 0; ! 424: lp->tx_ring[i].buf_phy_addr = 0; ! 425: lp->tx_ring[i].buf_len = 0; ! 426: } ! 427: ! 428: return 0; ! 429: } ! 430: ! 431: static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index) ! 432: { ! 433: volatile u16 status; ! 434: int retry = TX_RETRY; ! 435: ! 436: status = le16_to_cpu(lp->tx_ring[index].tx_flags); ! 437: while (--retry && (status & OWN_BIT)) { ! 438: mdelay(TX_PROCESS_TIME); ! 439: status = le16_to_cpu(lp->tx_ring[index].tx_flags); ! 440: } ! 441: if (status & OWN_BIT) { ! 442: printf("Error: tx slot %d timeout, stat = 0x%x\n", index, status); ! 443: amd8111e_restart(lp); ! 444: return -1; ! 445: } ! 446: ! 447: return 0; ! 448: } ! 449: ! 450: static void amd8111e_wait_link(struct amd8111e_priv *lp) ! 451: { ! 452: unsigned int status; ! 453: u32 reg_val; ! 454: ! 455: do { ! 456: /* read phy to update STAT0 register */ ! 457: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, ®_val); ! 458: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, ®_val); ! 459: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, ®_val); ! 460: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, ®_val); ! 461: status = readl(lp->mmio + STAT0); ! 462: } while (!(status & AUTONEG_COMPLETE) || !(status & LINK_STATS)); ! 463: } ! 464: ! 465: static void amd8111e_poll_link(struct amd8111e_priv *lp) ! 466: { ! 467: unsigned int status, speed; ! 468: u32 reg_val; ! 469: ! 470: if (!lp->link) { ! 471: /* read phy to update STAT0 register */ ! 472: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, ®_val); ! 473: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, ®_val); ! 474: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, ®_val); ! 475: amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, ®_val); ! 476: status = readl(lp->mmio + STAT0); ! 477: ! 478: if (status & LINK_STATS) { ! 479: lp->link = 1; ! 480: speed = (status & SPEED_MASK) >> 7; ! 481: if (speed == PHY_SPEED_100) ! 482: lp->speed = 1; ! 483: else ! 484: lp->speed = 0; ! 485: if (status & FULL_DPLX) ! 486: lp->duplex = 1; ! 487: else ! 488: lp->duplex = 0; ! 489: ! 490: printf("Link is up: %s Mbps %s duplex\n", ! 491: lp->speed ? "100" : "10", lp->duplex ? "full" : "half"); ! 492: } ! 493: } else { ! 494: status = readl(lp->mmio + STAT0); ! 495: if (!(status & LINK_STATS)) { ! 496: lp->link = 0; ! 497: printf("Link is down\n"); ! 498: } ! 499: } ! 500: } ! 501: ! 502: static void amd8111e_restart(struct amd8111e_priv *lp) ! 503: { ! 504: printf("\nStarting nic...\n"); ! 505: amd8111e_disable_interrupt(lp); ! 506: amd8111e_init_hw_default(lp); ! 507: amd8111e_probe_ext_phy(lp); ! 508: amd8111e_get_mac_address(lp); ! 509: amd8111e_start(lp); ! 510: ! 511: printf("Waiting link up...\n"); ! 512: lp->link = 0; ! 513: amd8111e_wait_link(lp); ! 514: amd8111e_poll_link(lp); ! 515: } ! 516: ! 517: ! 518: /******************************************************** ! 519: * Interface Functions * ! 520: ********************************************************/ ! 521: ! 522: static void amd8111e_transmit(struct nic *nic, const char *dst_addr, ! 523: unsigned int type, unsigned int size, const char *packet) ! 524: { ! 525: struct amd8111e_priv *lp = nic->priv_data; ! 526: struct eth_frame *frame; ! 527: unsigned int index; ! 528: ! 529: /* check packet size */ ! 530: if (size > TX_PKT_LEN_MAX) { ! 531: printf("amd8111e_transmit(): too large packet, drop\n"); ! 532: return; ! 533: } ! 534: ! 535: /* get tx slot */ ! 536: index = lp->tx_idx; ! 537: if (amd8111e_wait_tx_ring(lp, index)) ! 538: return; ! 539: ! 540: /* fill frame */ ! 541: frame = (struct eth_frame *)lp->tx_buf[index]; ! 542: memset(frame->data, 0, TX_PKT_LEN_MAX); ! 543: memcpy(frame->dst_addr, dst_addr, ETH_ALEN); ! 544: memcpy(frame->src_addr, nic->node_addr, ETH_ALEN); ! 545: frame->type = htons(type); ! 546: memcpy(frame->data, packet, size); ! 547: ! 548: /* start xmit */ ! 549: lp->tx_ring[index].buf_len = cpu_to_le16(ETH_HLEN + size); ! 550: lp->tx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(frame)); ! 551: wmb(); ! 552: lp->tx_ring[index].tx_flags = ! 553: cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT | ADD_FCS_BIT | LTINT_BIT); ! 554: writel(VAL1 | TDMD0, lp->mmio + CMD0); ! 555: readl(lp->mmio + CMD0); ! 556: ! 557: /* update slot pointer */ ! 558: lp->tx_idx = (lp->tx_idx + 1) & TX_SLOTS_MASK; ! 559: } ! 560: ! 561: static int amd8111e_poll(struct nic *nic, int retrieve) ! 562: { ! 563: /* return true if there's an ethernet packet ready to read */ ! 564: /* nic->packet should contain data on return */ ! 565: /* nic->packetlen should contain length of data */ ! 566: ! 567: struct amd8111e_priv *lp = nic->priv_data; ! 568: u16 status, pkt_len; ! 569: unsigned int index, pkt_ok; ! 570: ! 571: amd8111e_poll_link(lp); ! 572: ! 573: index = lp->rx_idx; ! 574: status = le16_to_cpu(lp->rx_ring[index].rx_flags); ! 575: pkt_len = le16_to_cpu(lp->rx_ring[index].msg_len) - 4; /* remove 4bytes FCS */ ! 576: ! 577: if (status & OWN_BIT) ! 578: return 0; ! 579: ! 580: if (status & ERR_BIT) ! 581: pkt_ok = 0; ! 582: else if (!(status & STP_BIT)) ! 583: pkt_ok = 0; ! 584: else if (!(status & ENP_BIT)) ! 585: pkt_ok = 0; ! 586: else if (pkt_len < RX_PKT_LEN_MIN) ! 587: pkt_ok = 0; ! 588: else if (pkt_len > RX_PKT_LEN_MAX) ! 589: pkt_ok = 0; ! 590: else ! 591: pkt_ok = 1; ! 592: ! 593: if (pkt_ok) { ! 594: if (!retrieve) ! 595: return 1; ! 596: nic->packetlen = pkt_len; ! 597: memcpy(nic->packet, lp->rx_buf[index], nic->packetlen); ! 598: } ! 599: ! 600: lp->rx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[index])); ! 601: lp->rx_ring[index].buf_len = cpu_to_le16(RX_BUF_LEN); ! 602: wmb(); ! 603: lp->rx_ring[index].rx_flags = cpu_to_le16(OWN_BIT); ! 604: writel(VAL2 | RDMD0, lp->mmio + CMD0); ! 605: readl(lp->mmio + CMD0); ! 606: ! 607: lp->rx_idx = (lp->rx_idx + 1) & RX_SLOTS_MASK; ! 608: return pkt_ok; ! 609: } ! 610: ! 611: static void amd8111e_disable(struct nic *nic) ! 612: { ! 613: struct amd8111e_priv *lp = nic->priv_data; ! 614: ! 615: /* disable interrupt */ ! 616: amd8111e_disable_interrupt(lp); ! 617: ! 618: /* stop chip */ ! 619: amd8111e_init_hw_default(lp); ! 620: ! 621: /* unmap mmio */ ! 622: iounmap(lp->mmio); ! 623: ! 624: /* update status */ ! 625: lp->opened = 0; ! 626: } ! 627: ! 628: static void amd8111e_irq(struct nic *nic, irq_action_t action) ! 629: { ! 630: struct amd8111e_priv *lp = nic->priv_data; ! 631: ! 632: switch (action) { ! 633: case DISABLE: ! 634: amd8111e_disable_interrupt(lp); ! 635: break; ! 636: case ENABLE: ! 637: amd8111e_enable_interrupt(lp); ! 638: break; ! 639: case FORCE: ! 640: amd8111e_force_interrupt(lp); ! 641: break; ! 642: } ! 643: } ! 644: ! 645: static struct nic_operations amd8111e_operations = { ! 646: .connect = dummy_connect, ! 647: .poll = amd8111e_poll, ! 648: .transmit = amd8111e_transmit, ! 649: .irq = amd8111e_irq, ! 650: }; ! 651: ! 652: static int amd8111e_probe(struct nic *nic, struct pci_device *pdev) ! 653: { ! 654: struct amd8111e_priv *lp = &amd8111e; ! 655: unsigned long mmio_start, mmio_len; ! 656: ! 657: nic->ioaddr = pdev->ioaddr; ! 658: nic->irqno = pdev->irq; ! 659: ! 660: mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0); ! 661: mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0); ! 662: ! 663: memset(lp, 0, sizeof(*lp)); ! 664: lp->pdev = pdev; ! 665: lp->nic = nic; ! 666: lp->mmio = ioremap(mmio_start, mmio_len); ! 667: lp->opened = 1; ! 668: adjust_pci_device(pdev); ! 669: ! 670: nic->priv_data = lp; ! 671: ! 672: amd8111e_restart(lp); ! 673: ! 674: nic->nic_op = &amd8111e_operations; ! 675: return 1; ! 676: } ! 677: ! 678: static struct pci_device_id amd8111e_nics[] = { ! 679: PCI_ROM(0x1022, 0x7462, "amd8111e", "AMD8111E", 0), ! 680: }; ! 681: ! 682: PCI_DRIVER ( amd8111e_driver, amd8111e_nics, PCI_NO_CLASS ); ! 683: ! 684: DRIVER ( "AMD8111E", nic_driver, pci_driver, amd8111e_driver, ! 685: amd8111e_probe, amd8111e_disable ); ! 686: ! 687: /* ! 688: * Local variables: ! 689: * c-basic-offset: 8 ! 690: * c-indent-level: 8 ! 691: * tab-width: 8 ! 692: * End: ! 693: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.