#include <const.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <arch/i386.h>
#include <arch/interrupt.h>
#include <arch/mem.h>
#include <arch/paging.h>
#include <kernel/clock.h>
#include <kernel/dma.h>
#include <kernel/kmalloc.h>
#include <kernel/pci.h>
#include <kernel/semaphore.h>
#include <kernel/video.h>
#include <net/arp.h>
#include <net/eth.h>
#include <net/ip.h>
#include <net/network.h>
#include <net/rtl8139.h>
Go to the source code of this file.
Enumerations | |||||||
| enum | RTL8139_registers { MAC0 = 0, MAR0 = 8, TxStatus0 = 0x10, TxAddr0 = 0x20, RxBuf = 0x30, RxEarlyCnt = 0x34, RxEarlyStatus = 0x36, ChipCmd = 0x37, RxBufPtr = 0x38, RxBufAddr = 0x3A, IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, RxConfig = 0x44, Timer = 0x48, RxMissed = 0x4C, Cfg9346 = 0x50, Config0 = 0x51, Config1 = 0x52, TimerIntrReg = 0x54, MediaStatus = 0x58, Config3 = 0x59, HltClk = 0x5B, MultiIntr = 0x5C, RevisionID = 0x5E, TxSummary = 0x60, MII_BMCR = 0x62, MII_BMSR = 0x64, NWayAdvert = 0x66, NWayLPAR = 0x68, NWayExpansion = 0x6A, DisconnectCnt = 0x6C, FalseCarrierCnt = 0x6E, NWayTestReg = 0x70, RxCnt = 0x72, CSCR = 0x74, PhyParm1 = 0x78, TwisterParm = 0x7c, PhyParm2 = 0x80 } | ||||||
| Symbolic RTL8139 offsets to registers. More... | |||||||
| enum | ChipCmdBits { CmdReset = 0x10, CmdRxEnb = 0x08, CmdTxEnb = 0x04, RxBufEmpty = 0x01 } | ||||||
| enum | IntrStatusBits { PCIErr = 0x8000, PCSTimeout = 0x4000, CableLenChange = 0x2000, RxFIFOOver = 0x40, RxUnderrun = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, RxErr = 0x02, RxOK = 0x01, IntrDefault = RxOK | TxOK } | ||||||
| Interrupt Status Register bits. More... | |||||||
| enum | TxStatusBits { TxHostOwns = 0x2000, TxUnderrun = 0x4000, TxStatOK = 0x8000, TxOutOfWindow = 0x20000000, TxAborted = 0x40000000, TxCarrierLost = 0x80000000 } | ||||||
| Transmit Status Register bits. More... | |||||||
| enum | RxStatusBits { RxMulticast = 0x8000, RxPhysical = 0x4000, RxBroadcast = 0x2000, RxBadSymbol = 0x0020, RxRunt = 0x0010, RxTooLong = 0x0008, RxCRCErr = 0x0004, RxBadAlign = 0x0002, RxStatusOK = 0x0001 } | ||||||
| Receive Status Register bits. More... | |||||||
| enum | MediaStatusBits { MSRTxFlowEnable = 0x80, MSRRxFlowEnable = 0x40, MSRSpeed10 = 0x08, MSRLinkFail = 0x04, MSRRxPauseFlag = 0x02, MSRTxPauseFlag = 0x01 } | ||||||
| Media Status Register bits. More... | |||||||
| enum | MIIBMCRBits { BMCRReset = 0x8000, BMCRSpeed100 = 0x2000, BMCRNWayEnable = 0x1000, BMCRRestartNWay = 0x0200, BMCRDuplex = 0x0100 } | ||||||
| enum | CSCRBits { CSCR_LinkOKBit = 0x0400, CSCR_LinkChangeBit = 0x0800, CSCR_LinkStatusBits = 0x0f000, CSCR_LinkDownOffCmd = 0x003c0, CSCR_LinkDownCmd = 0x0f3c0 } | ||||||
| enum | rx_mode_bits { RxCfgWrap = 0x80, AcceptErr = 0x20, AcceptRunt = 0x10, AcceptBroadcast = 0x08, AcceptMulticast = 0x04, AcceptMyPhys = 0x02, AcceptAllPhys = 0x01 } | ||||||
| Bits in Receive Configuration Register. More... | |||||||
Functions | |||||||
| void | rtl8139_close (rtl8139_t **rtl) | ||||||
Halt the RTL8139 card and free the logical device.
| |||||||
| unsigned | rtl8139_read_eeprom (rtl8139_t *rtl, unsigned location) | ||||||
Read RTL8139 informations from the EEPROM.
| |||||||
| void | rtl8139_promisc (rtl8139_t *rtl, bool on) | ||||||
Enable/disable the promiscuous mode for the RTL8139 card.
| |||||||
| void | rtl8139_reset (rtl8139_t *rtl) | ||||||
Reset the RTL8139 ethernet card.
| |||||||
| int | rtl8139_init (bool promisc) | ||||||
Initialize the RTL8139 driver.
| |||||||
| uint8_t * | get_eth_mac_addr () | ||||||
Get the MAC hardware address of the RTL8139 ethernet card.
| |||||||
| rtl8139_t * | get_rtl8139_device () | ||||||
Get the pointer of the RTL8139 device structure.
| |||||||
| int | send_rtl8139_packet (rtl8139_t *rtl, const void *data, size_t len) | ||||||
Send an ethernet packet to the physiscal layer.
| |||||||
| void | rtl8139_handle_tx (rtl8139_t *rtl) | ||||||
Handle a transmitted packet event.
| |||||||
| void | rtl8139_handle_rx (rtl8139_t *rtl) | ||||||
Handle a received packet event.
| |||||||
| void | rtl8139_handler () | ||||||
| The RTL8139 interrupt handler routine. It is invoked every time that an ethernet packet is received or when a packet has been transmitted. | |||||||
| void | rtl8139_dump_info (rtl8139_t *rtl) | ||||||
Print the current RTL8139 card configuration on the console.
| |||||||
Variables | |||||||
| rtl8139_t * | rtl = NULL | ||||||
| Pointer to the RTL8139 structure. | |||||||
Definition in file rtl8139.c.
|
|
Definition at line 93 of file rtl8139.c.
00094 {
00095 CmdReset=0x10,
00096 CmdRxEnb=0x08,
00097 CmdTxEnb=0x04,
00098 RxBufEmpty=0x01,
00099 };
|
|
|
Definition at line 162 of file rtl8139.c.
00163 {
00164 CSCR_LinkOKBit=0x0400,
00165 CSCR_LinkChangeBit=0x0800,
00166 CSCR_LinkStatusBits=0x0f000,
00167 CSCR_LinkDownOffCmd=0x003c0,
00168 CSCR_LinkDownCmd=0x0f3c0,
00169 };
|
|
|
Interrupt Status Register bits.
Definition at line 102 of file rtl8139.c.
00103 {
00104 PCIErr=0x8000,
00105 PCSTimeout=0x4000,
00106 CableLenChange= 0x2000,
00107 RxFIFOOver=0x40,
00108 RxUnderrun=0x20,
00109 RxOverflow=0x10,
00110 TxErr=0x08,
00111 TxOK=0x04,
00112 RxErr=0x02,
00113 RxOK=0x01,
00114 IntrDefault = RxOK | TxOK,
00115 };
|
|
|
Media Status Register bits.
Definition at line 143 of file rtl8139.c.
00144 {
00145 MSRTxFlowEnable=0x80,
00146 MSRRxFlowEnable=0x40,
00147 MSRSpeed10=0x08,
00148 MSRLinkFail=0x04,
00149 MSRRxPauseFlag=0x02,
00150 MSRTxPauseFlag=0x01,
00151 };
|
|
|
Definition at line 153 of file rtl8139.c.
00154 {
00155 BMCRReset=0x8000,
00156 BMCRSpeed100=0x2000,
00157 BMCRNWayEnable=0x1000,
00158 BMCRRestartNWay=0x0200,
00159 BMCRDuplex=0x0100,
00160 };
|
|
|
Symbolic RTL8139 offsets to registers.
Definition at line 36 of file rtl8139.c.
00037 {
00038 MAC0=0, //!< Ethernet hardware address.
00039 MAR0=8, //!< Multicast filter.
00040 TxStatus0=0x10, //!< Transmit status: 4 32bit registers.
00041 TxAddr0=0x20, //!< Tx descriptors (also 4 32bit).
00042
00043 RxBuf=0x30,
00044 RxEarlyCnt=0x34,
00045 RxEarlyStatus=0x36,
00046
00047 ChipCmd=0x37,
00048 RxBufPtr=0x38,
00049 RxBufAddr=0x3A,
00050
00051 IntrMask=0x3C,
00052 IntrStatus=0x3E,
00053 TxConfig=0x40,
00054 RxConfig=0x44,
00055
00056 Timer=0x48, //!< General-purpose counter.
00057 RxMissed=0x4C, //!< 24 bits valid, write clears.
00058
00059 Cfg9346=0x50,
00060 Config0=0x51,
00061 Config1=0x52,
00062
00063 TimerIntrReg=0x54, //!< INTR if gp counter reaches this value.
00064 MediaStatus=0x58,
00065 Config3=0x59,
00066 HltClk=0x5B,
00067 MultiIntr=0x5C,
00068 RevisionID=0x5E, //!< Revision of the RTL8139 chip.
00069 TxSummary=0x60,
00070
00071 MII_BMCR=0x62,
00072 MII_BMSR=0x64,
00073
00074 NWayAdvert=0x66,
00075 NWayLPAR=0x68,
00076 NWayExpansion=0x6A,
00077
00078 DisconnectCnt=0x6C,
00079 FalseCarrierCnt=0x6E,
00080 NWayTestReg=0x70,
00081
00082 RxCnt=0x72, //!< Packet received counter.
00083 CSCR=0x74, //!< Chip status and configuration register.
00084
00085 PhyParm1=0x78, //!< Undocumented.
00086 TwisterParm=0x7c, //!< Undocumented.
00087 PhyParm2=0x80, //!< Undocumented.
00088
00089 // From 0x84 onwards are a number of power management/wakeup //
00090 // frame definitions we will probably never need to know about. //
00091 };
|
|
|
Bits in Receive Configuration Register.
Definition at line 172 of file rtl8139.c.
00173 {
00174 RxCfgWrap=0x80,
00175 AcceptErr=0x20,
00176 AcceptRunt=0x10,
00177 AcceptBroadcast=0x08,
00178 AcceptMulticast=0x04,
00179 AcceptMyPhys=0x02,
00180 AcceptAllPhys=0x01,
00181 };
|
|
|
Receive Status Register bits.
Definition at line 129 of file rtl8139.c.
00130 {
00131 RxMulticast=0x8000,
00132 RxPhysical=0x4000,
00133 RxBroadcast=0x2000,
00134 RxBadSymbol=0x0020,
00135 RxRunt=0x0010,
00136 RxTooLong=0x0008,
00137 RxCRCErr=0x0004,
00138 RxBadAlign=0x0002,
00139 RxStatusOK=0x0001,
00140 };
|
|
|
Transmit Status Register bits.
Definition at line 118 of file rtl8139.c.
00119 {
00120 TxHostOwns=0x2000,
00121 TxUnderrun=0x4000,
00122 TxStatOK=0x8000,
00123 TxOutOfWindow=0x20000000,
00124 TxAborted=0x40000000,
00125 TxCarrierLost=0x80000000,
00126 };
|
|
|
Get the MAC hardware address of the RTL8139 ethernet card.
Definition at line 455 of file rtl8139.c.
00456 {
00457 if (rtl)
00458 return(rtl->station_address);
00459 else
00460 return(NULL);
00461 }
|
|
|
Get the pointer of the RTL8139 device structure.
Definition at line 468 of file rtl8139.c.
00469 {
00470 return( rtl );
00471 }
|
|
|
Halt the RTL8139 card and free the logical device.
Definition at line 191 of file rtl8139.c.
00192 {
00193 // Disable interrupts by clearing the interrupt mask //
00194 out16((*rtl)->iobase + IntrMask, 0);
00195 // Stop the chip's Tx and Rx DMA processes //
00196 out((*rtl)->iobase + ChipCmd, 0);
00197
00198 // Put the chip in low-power mode //
00199 out((*rtl)->iobase + Cfg9346, 0xC0);
00200 out((*rtl)->iobase + Config1, 0x03);
00201 // 'R' would leave the clock running //
00202 out((*rtl)->iobase + HltClk, 'H');
00203
00204 if ( (*rtl) != NULL )
00205 {
00206 // Disable the IRQ line //
00207 disable_IRQ((*rtl)->irq);
00208
00209 // Deallocate the ring buffers //
00210 dma_phys_free((*rtl)->rx_phys, RX_BUF_LEN);
00211 dma_phys_free((*rtl)->tx_phys, TX_BUF_SIZE*NUM_TX_DESC);
00212
00213 // Deallocate the logical structure //
00214 kfree((*rtl));
00215 *rtl = NULL;
00216 }
00217 }
|
|
|
Print the current RTL8139 card configuration on the console.
Definition at line 654 of file rtl8139.c.
00655 {
00656 in_addr_t ip, netmask, ip_bcast;
00657
00658 if ( !rtl )
00659 {
00660 // The card is not configured //
00661 kprintf("\n\rUsage: ifconfig [up|down]");
00662 kprintf("\n\rRTL8139: ethernet card not configured!\n\r");
00663 return;
00664 }
00665
00666 // Dump the device informations //
00667 kprintf("\n\rRTL8139: card configured @ I/O base=%04X IRQ=%u", rtl->iobase, rtl->irq);
00668 // Dump the MAC address //
00669 kprintf("\n\rRTL8139: MAC address %02x:%02x:%02x:%02x:%02x:%02x",
00670 rtl->station_address[0], rtl->station_address[1], rtl->station_address[2],
00671 rtl->station_address[3], rtl->station_address[4], rtl->station_address[5]
00672 );
00673 // Dump the media informations //
00674 kprintf("\n\rRTL8139: %sMbps %s-duplex",
00675 rtl->speed10 ? "10" : "100",
00676 rtl->fullduplex ? "full" : "half"
00677 );
00678 // Print the promiscuous mode flag //
00679 kprintf("\n\rRTL8139: promiscuous mode %s", (rtl->promisc) ? "ENABLED" : "DISABLED");
00680 // Print virtual memory rings pointers //
00681 kprintf("\n\rRTL8139: rx_ring=%p<->%p, tx_ring=%p<->%p",
00682 rtl->rx_ring, rtl->rx_ring + RX_BUF_LEN,
00683 rtl->tx_ring, rtl->tx_ring + PAGE_ALIGN_UP(TX_BUF_SIZE*NUM_TX_DESC)
00684 );
00685 // Well done! //
00686 kprintf("\n\rRTL8139: OK, ethernet card is ready!");
00687
00688 ip = ntohl( get_host_ip() );
00689 netmask = ntohl( get_host_netmask() );
00690 ip_bcast = (~netmask) | (ip & netmask);
00691 kprintf("\n\n\rhost ip=%u.%u.%u.%u netmask=%u.%u.%u.%u broadcast=%u.%u.%u.%u\n\r",
00692 IP_A(ip), IP_B(ip), IP_C(ip), IP_D(ip),
00693 IP_A(netmask), IP_B(netmask), IP_C(netmask), IP_D(netmask),
00694 IP_A(ip_bcast), IP_B(ip_bcast), IP_C(ip_bcast), IP_D(ip_bcast)
00695 );
00696 }
|
|
|
Handle a received packet event.
Definition at line 549 of file rtl8139.c.
00550 {
00551 uint32_t ring_offs, rx_size, rx_status;
00552 rxpacket_t *packet;
00553
00554 while ((in(rtl->iobase + ChipCmd) & RxBufEmpty) == 0)
00555 {
00556 ring_offs = rtl->cur_rx % RX_BUF_LEN;
00557
00558 // Read status+size of the next frame from DMA //
00559 // ring buffer //
00560 rx_status = *(uint32_t *)(rtl->rx_ring + ring_offs);
00561 rx_size = rx_status >> 16;
00562 rx_status &= 0xFFFF;
00563
00564 if (
00565 (rx_status & (RxBadSymbol | RxRunt | RxTooLong | RxCRCErr | RxBadAlign)) ||
00566 (rx_size < ETH_MIN_LEN) ||
00567 (rx_size > ETH_FRAME_LEN + 4)
00568 )
00569 {
00570 #ifdef DEBUG
00571 kprintf("\n\rRX error! status=%#010x rx_size=%#010x\n\r", rx_status, rx_size);
00572 #endif
00573 rtl8139_reset(rtl);
00574 return;
00575 }
00576
00577 // Allocate a buffer to store the packet //
00578 packet = kmalloc(sizeof(rxpacket_t) - 1 + rx_size - 4);
00579 if (packet == NULL)
00580 return;
00581
00582 // No one cares about the FCS //
00583 packet->length = rx_size - 4;
00584
00585 // Received a good packet //
00586 if (ring_offs + 4 + rx_size - 4 > RX_BUF_LEN)
00587 {
00588 int semi_count = RX_BUF_LEN - ring_offs - 4;
00589
00590 memcpy(packet->data, rtl->rx_ring + ring_offs + 4, semi_count);
00591 memcpy(packet->data + semi_count, rtl->rx_ring, rx_size - 4 - semi_count);
00592 #ifdef DEBUG
00593 kprintf("\n\rRX packet (%u+%u bytes)", semi_count, rx_size - 4 - semi_count);
00594 #endif
00595 }
00596 else
00597 {
00598 memcpy(packet->data, rtl->rx_ring + ring_offs + 4, packet->length);
00599 #ifdef DEBUG
00600 kprintf("\n\rRX packet (%u bytes)", rx_size-4);
00601 #endif
00602 }
00603 #if 0
00604 // Dump the received packet content //
00605 kprintf("\n\r");
00606 for (i=0; i<packet->length; i++)
00607 kprintf("%02X ", packet->data[i]);
00608 #endif
00609 rtl->cur_rx = (rtl->cur_rx + rx_size + 4 + 3) & ~3;
00610 out16(rtl->iobase + RxBufPtr, rtl->cur_rx - 16);
00611
00612 // Send the packet to the upper layer //
00613 to_eth_layer((ethernet_t *)packet->data, packet->length);
00614
00615 // Free the packet sturcture //
00616 kfree(packet);
00617 }
00618 return;
00619 }
|
|
|
Handle a transmitted packet event.
Definition at line 532 of file rtl8139.c.
00533 {
00534 unsigned int i, status;
00535
00536 for(i=0; i<NUM_TX_DESC; i++)
00537 {
00538 // We must read the status of every descriptor when //
00539 // a Tx interrupt occurs //
00540 status = in32(rtl->iobase + TxStatus0 + (i * 4));
00541 #ifdef DEBUG
00542 kprintf("\n\rbuffer %u status %#010x", i, status);
00543 #endif
00544 }
00545 }
|
|
|
Initialize the RTL8139 driver.
Definition at line 358 of file rtl8139.c.
00359 {
00360 pci_cfg_t cfg;
00361 unsigned i;
00362 dword IF = GET_IF();
00363
00364 // Search an ethernet device on PCI and enable it! //
00365 cfg.base_class = 0x02; // Ethernet class //
00366 cfg.sub_class = 0x00; // Ethernet sub_class //
00367 cfg.interface = 0x00; // Ethernet interface //
00368
00369 if ( !pci_find_cfg(&cfg, TRUE) )
00370 {
00371 return(-ENXIO);
00372 }
00373
00374 // Close a previous RTL8139 structure if present //
00375 if ( rtl != NULL )
00376 {
00377 rtl8139_close(&rtl);
00378 }
00379
00380 // Allocate the RTL8139 structure //
00381 rtl = kmalloc(sizeof(rtl8139_t));
00382 if ( !rtl )
00383 return(-ENOMEM);
00384
00385 memset(rtl, 0, sizeof(rtl8139_t));
00386
00387 // Setup the I/O base register //
00388 for (i=0; i<6; i++)
00389 if ( (rtl->iobase=cfg.base[i]) != 0 ) break;
00390
00391 // Check if the device I/O base address is valid //
00392 if ( rtl->iobase == 0 )
00393 {
00394 kfree(rtl);
00395 return(-EIO);
00396 }
00397
00398 // Setup the IRQ line //
00399 disable();
00400 rtl->irq = cfg.irq;
00401 install_irq_handler( rtl->irq, (void *)&rtl8139_handler );
00402
00403 // Bring the chip out of low-power mode //
00404 out(rtl->iobase + Config1, 0x00);
00405
00406 // Read the MAC address //
00407 if (rtl8139_read_eeprom(rtl, 0) != 0xFFFF)
00408 {
00409 // Read from EEPROM //
00410 unsigned short *ap = (unsigned short*)rtl->station_address;
00411 for (i = 0; i < 3; i++)
00412 *ap++ = rtl8139_read_eeprom(rtl, i + 7);
00413 }
00414 else
00415 {
00416 // Read from MAC0 register //
00417 unsigned char *ap = (unsigned char*)rtl->station_address;
00418 for (i = 0; i < 6; i++)
00419 *ap++ = in(rtl->iobase + MAC0 + i);
00420 }
00421
00422 // Read the media informations //
00423 rtl->speed10 = (in(rtl->iobase + MediaStatus) & MSRSpeed10) != 0;
00424 rtl->fullduplex = (in16(rtl->iobase + MII_BMCR) & BMCRDuplex) != 0;
00425
00426 // Setup the promiscuous mode //
00427 rtl->promisc = promisc;
00428
00429 // Initialize the Rx and Tx rings buffer //
00430 if ( !(rtl->rx_ring) )
00431 {
00432 rtl->rx_phys = (addr_t)dma_phys_alloc(RX_BUF_LEN);
00433 rtl->rx_ring = PHYSICAL( (uint8_t *)(rtl->rx_phys) );
00434 }
00435 if ( !(rtl->tx_ring) )
00436 {
00437 rtl->tx_phys = (addr_t)dma_phys_alloc(TX_BUF_SIZE*NUM_TX_DESC);
00438 rtl->tx_ring = PHYSICAL( (uint8_t *)(rtl->tx_phys) );
00439 }
00440
00441 // Initialize the RTL8139 mutex semaphore //
00442 INIT_MUTEX(&rtl->mutex);
00443
00444 // Hardware reset of the RTL8139 //
00445 rtl8139_reset(rtl);
00446
00447 // Well done! //
00448 SET_IF(IF);
00449 return(0);
00450 }
|
|
||||||||||||
|
Enable/disable the promiscuous mode for the RTL8139 card.
Definition at line 265 of file rtl8139.c.
00266 {
00267 uint8_t rxc;
00268 dword IF = GET_IF();
00269
00270 disable();
00271 rxc = in(rtl->iobase + RxConfig);
00272 if ( on )
00273 out(rtl->iobase + RxConfig, rxc | AcceptAllPhys);
00274 else
00275 out(rtl->iobase + RxConfig, rxc & (~AcceptAllPhys));
00276 rtl->promisc = on;
00277 SET_IF(IF);
00278 }
|
|
||||||||||||
|
Read RTL8139 informations from the EEPROM.
Definition at line 223 of file rtl8139.c.
00224 {
00225 int i;
00226 unsigned int retval = 0;
00227 long ee_addr = rtl->iobase + Cfg9346;
00228 int read_cmd = location | EE_READ_CMD;
00229
00230 out(ee_addr, EE_ENB & ~EE_CS);
00231 out(ee_addr, EE_ENB);
00232
00233 // Shift the read command bits out //
00234 for (i = 10; i >= 0; i--)
00235 {
00236 int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
00237 out(ee_addr, EE_ENB | dataval);
00238 eeprom_delay();
00239 out(ee_addr, EE_ENB | dataval | EE_SHIFT_CLK);
00240 eeprom_delay();
00241 }
00242
00243 out(ee_addr, EE_ENB);
00244 eeprom_delay();
00245
00246 for (i = 16; i > 0; i--)
00247 {
00248 out(ee_addr, EE_ENB | EE_SHIFT_CLK);
00249 eeprom_delay();
00250 retval = (retval << 1) | ((in(ee_addr) & EE_DATA_READ) ? 1 : 0);
00251 out(ee_addr, EE_ENB);
00252 eeprom_delay();
00253 }
00254
00255 // Terminate the EEPROM access //
00256 out(ee_addr, ~EE_CS);
00257 return(retval);
00258 }
|
|
|
Reset the RTL8139 ethernet card.
Definition at line 282 of file rtl8139.c.
00283 {
00284 unsigned i;
00285 timeout_t elapsed;
00286 dword IF = GET_IF();
00287
00288 // Send the software-reset command //
00289 out(rtl->iobase + ChipCmd, CmdReset);
00290
00291 // Reset the Rx and Tx rings //
00292 rtl->cur_rx = 0;
00293 rtl->cur_tx = 0;
00294
00295 // Give the chip 10ms to finish the reset //
00296 enable();
00297 set_timeout(&elapsed, 10);
00298 while ( (in(rtl->iobase + ChipCmd) & CmdReset) != 0 )
00299 if ( is_timeout(&elapsed) ) break;
00300 SET_IF(IF);
00301
00302 // Set-up the card MAC address register //
00303 for (i=0; i<_countof(rtl->station_address); i++)
00304 out(rtl->iobase + MAC0 + i, rtl->station_address[i]);
00305
00306 // Must enable Tx/Rx before setting transfer thresholds! //
00307 out(rtl->iobase + ChipCmd, CmdRxEnb | CmdTxEnb);
00308 // Accept no frames yet! //
00309 out32(rtl->iobase + RxConfig,
00310 (RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8));
00311 out32(rtl->iobase + TxConfig, (TX_DMA_BURST<<8) | 0x03000000);
00312
00313 // Configure the RX buffer //
00314 out32(rtl->iobase + RxBuf, rtl->rx_phys);
00315
00316 // Init Tx buffer DMA addresses //
00317 for (i = 0; i < NUM_TX_DESC; i++)
00318 out32(rtl->iobase + TxAddr0 + (i * 4), rtl->tx_phys + (TX_BUF_SIZE*i));
00319
00320 // Reset the missed packets counter //
00321 out32(rtl->iobase + RxMissed, 0);
00322
00323 // Set RX mode //
00324 if ( rtl->promisc )
00325 out(rtl->iobase + RxConfig, AcceptBroadcast | AcceptMyPhys | AcceptAllPhys);
00326 else
00327 out(rtl->iobase + RxConfig, AcceptBroadcast | AcceptMyPhys);
00328
00329 // If we add multicast support, the MAR0 register would have to //
00330 // be initialized to 0xFFFFFFFF.FFFFFFFF (two 32 bit accesses). //
00331 // Etherboot only needs broadcast (for ARP/RARP/BOOTP/DHCP) and //
00332 // unicast. //
00333
00334 // Start the chip's Tx and Rx process //
00335 out(rtl->iobase + ChipCmd, CmdRxEnb | CmdTxEnb);
00336
00337 // Disable all known interrupts by setting the interrupt mask //
00338 // out16(rtl->iobase + IntrMask, 0x0000);
00339
00340 // Enable all known interrupts //
00341 // out16(rtl->iobase + IntrMask, PCIErr | PCSTimeout | RxUnderrun |
00342 // RxOverflow | RxFIFOOver |
00343 // TxErr | TxOK | RxErr | RxOK);
00344
00345 // Enable default interrupt mask (RxOK | TxOK) //
00346 out16(rtl->iobase + IntrMask, IntrDefault);
00347 }
|
|
||||||||||||||||
|
Send an ethernet packet to the physiscal layer.
Definition at line 481 of file rtl8139.c.
00482 {
00483 // Check if the RTL8139 card has been configured //
00484 if ( !rtl ) return(-1);
00485
00486 // Adapt the packet length to the Tx buffer size //
00487 // This should be done by the ethernet layer... //
00488 len = MIN(len, TX_BUF_SIZE);
00489
00490 // Enter critical region //
00491 DOWN(&rtl->mutex);
00492
00493 // kprintf("\n\rlooking for buffer %u", desc);
00494 if ( in32(rtl->iobase + TxStatus0 + (rtl->cur_tx * 4)) & TxHostOwns )
00495 {
00496 // Found a free buffer! //
00497
00498 // Copy the raw data to the Tx ring //
00499 memcpy(rtl->tx_ring + (TX_BUF_SIZE*rtl->cur_tx), data, len);
00500
00501 // NOTE: RTL8139 doesn't auto-pad! Be sure that //
00502 // the ethernet layer has done it correctly //
00503 while (len < ETH_MIN_LEN)
00504 (rtl->tx_ring + (TX_BUF_SIZE*rtl->cur_tx))[len++] = '\0';
00505
00506 // Move the data from the Tx buffer to the //
00507 // internal transmit FIFO in PCI bus master //
00508 // mode //
00509 out32(rtl->iobase + TxAddr0 + rtl->cur_tx * 4,
00510 rtl->tx_phys + (TX_BUF_SIZE * rtl->cur_tx));
00511 out32(rtl->iobase + TxStatus0 + rtl->cur_tx * 4,
00512 ((TX_FIFO_THRESH<<11) & 0x003F0000) | len);
00513
00514 // Select new descriptor for transmition //
00515 rtl->cur_tx = (rtl->cur_tx + 1) % NUM_TX_DESC;
00516
00517 // End of critical region //
00518 UP(&rtl->mutex);
00519
00520 // Return the byte transmitted //
00521 return(len);
00522 }
00523 // End of critical region //
00524 UP(&rtl->mutex);
00525
00526 // Buffer not available! //
00527 return(-1);
00528 }
|
|
|
Pointer to the RTL8139 structure.
|
1.2.18