📄 readme
字号:
Some notes on the RealTek 8139 driver1. Using the driverThis driver follows the customization model used by many other driversto separate those parts of the code that are device specific from thosethat are platform specific by requiring two packages to actually use thedriver -- the driver itself and a platform glue package that containsonly a .cdl and an .inl file (see the devs/i386/pc/rltk8139 package foran example).Both the driver and the glue packages must be added to the packagedatabase before you can use them. My entries look like this:package CYGPKG_DEVS_ETH_RLTK_8139 { alias { "RealTek 8139 ethernet driver" devs_eth_rltk_8139 8139_eth_driver } hardware directory devs/eth/rltk/8139 script rltk_8139_eth_drivers.cdl description "Ethernet driver for RealTek 8139 NIC."}andpackage CYGPKG_DEVS_ETH_I386_RLTK8139 { alias { "Standard PC with RealTek 8139 ethernet device" devs_eth_i386_pc_rltk8139 } hardware directory devs/eth/i386/pc/rltk8139 script i386_pc_rltk8139_eth_drivers.cdl description "Ethernet driver for the RealTek 8139 family of chips."}Finally, you will need to create a new target that includes the RealTekdriver. The easiest way to this is copy an existing target and add thetwo packages defined above (and removing the Intel 82259 packages in caseof an i386 pc target).2. Cache CoherencySince the 8139 reads data directly from memory via the PCI bus, you mayhave to worry about data cache coherency. For eCos, there are basicallythree cases (turning the data cache off is not considered a serious solution):a. Either the CPU has no data cache, or the CPU has cache snooping logicthat will detect memory accesses by PCI bus master devices and flush the cachewhen necessary. In this case, nothing special needs to be done.b. The MMU is configured to access memory uncached in a certain address space.In this case, the macro CYGARC_UNCACHED_ADDRESS() can be used to convertnormal (cached) into uncached accesses. The driver always uses this macro foraccessing the transmit and receive buffers, since if the HAL doesn'tsupport this mechanism, the macro does nothing and no harm is done.c. The data cache needs to be flushed/invalidated by the driver. In this case,you must define CYGPKG_DEVS_ETH_RLTK_8139_SOFTWARE_CACHE_COHERENCY in theplatform specific .inl file. Furthermore, the HAL macros HAL_DCACHE_INVALIDATEand HAL_DCACHE_FLUSH must be defined. Next, you must ensure that the buffersare aligned to cache line boundaries; otherwise, the code could fail inmysterious ways.One way to do this is to define the following in the .inl file:#define CACHE_ALIGNED __attribute__ ((aligned (HAL_DCACHE_LINE_SIZE)))Then, use this attribute on the transmit and receive buffer definitions:static cyg_uint8 rltk8139_eth0_rx_ring[RX_BUF_TOT_LEN] CACHE_ALIGNED;Note that this may fail for long cache lines, since the 'aligned' attributedoes not allow arbitrarily large alignment parameters. Unfortunately, the gccdocumentation does not say what the maximum alignment that can be specifiedis. Additionally, the linker may also be limited in the maximum alignment thatcan be used. In such cases, you'll have to bite the bullet and define morespace than would be strictly necessary, and ensure the necessary alignmentlike this:static cyg_uint8 rltk8139_eth0_rx_ring[RX_BUF_TOT_LEN + HAL_DCACHE_LINE_SIZE];Then, reference the buffers in the Rltk8139 definition like this:(cyg_uint8 *)((int)(&rltk8139_eth0_rx_ring[0] + HAL_DCACHE_LINE_SIZE) & ~(HAL_DCACHE_LINE_SIZE - 1))This assumes the cache line size is a power of 2; this is the case for allCPUs I know of. It also assumes an int can hold a pointer; if this isnot true for your platform, use an integral type that can.Another thing to watch out for is that the buffers should also end ona cache line boundary. If your linker places the buffers sequentially inmemory, you will only have to do this for the last buffer defined (sinceall buffers will start on cache line boundaries):static cyg_uint8rltk8139_eth0_tx_buffer[(TX_BUF_TOT_LEN + HAL_DCACHE_LINE_SIZE - 1) & ~(HAL_DCACHE_LINE_SIZE - 1)] CACHE_ALIGNED;3. Interrupt sharingIf the 8139 must share it's interrupt request line with other devices, theHAL option 'chained interrupts' must be enabled. The 8139 driver does notsupport IRQ muxing like the Intel 82559 driver does (see also *Limitations*).The driver's ISR does not clear the interrupt status bits since I believe thisshould only be done after the conditions that caused those bits to be sethave been handled by the '_deliver' routine. Instead, the interrupt is masked.There are two ways to do this (configurable with a CDL option):a. The interrupt vector is masked. Personally I think this is a bad idea because this will also block interrupts from all other devices sharing this interrupt until the network thread gets around to calling the '_deliver' routine.b. Mask the interrupt request using the 8139's interrupt mask register. This way, other devices' interrupt requests can still be serviced. Enable the CYGPKG_DEVS_ETH_RLTK_8139_MASK_INTERRUPTS_IN_8139 option to use this.4. LimitationsThere are a number of limitations associated with this driver:a. The configuration of the NIC (MAC address, media selection, etc.) is loaded from the serial EEPROM (which is assumed to exist) and cannot be changed either at compile or run time.b. The 'twister' cannot be tuned. As far as I can make out, the 'twister' can be tuned to improve signal quality over long lines. The RealTek data sheet does not document the twister; and the code in the Linux driver that does this is totally incomprehensible to me.c. If multiple 8139s share the same interrupt, chained interrupts have to be used. No IRQ MUXing (like the Intel 82559 driver has) is supported.d. Programming the multicast acceptance filter is now implemented, but not tested because eCos doesn't have such a test program (or at least I couldn't find any). Since I have never used multicasting myself, I don't feel competent to write one. Someone suggested setting up an IPv6 network for testing, since it seems IPv6 makes use of multicasting in normal operation, but I haven't got around to doing that.e. It's fairly slow. This is not really the driver's fault - the 8139 requires a fast CPU to get anything approaching decent speed because all messages have to be copied around in memory.5. CreditsThe 8139's data sheet is not really all that helpful, since it containsa lot of omissions and some data that is simply incorrect. As such, I amindebted to Bill Paul for his well-documented OpenBSD driver, which wasinvaluable for figuring out how the chip is supposed to work. The idea ofusing 'enum' instead of '#define' came from the Linux 8139 driver, which Iinitially wanted to port to eCos, but didn't because I found it extremelyhard to read and understand. (Note that I didn't copy any code from thosedrivers to avoid tainting eCos' license). The basic structure of the driverand .cdl files was taken from the eCos i82559 driver.I'd also like all the people who have downloaded and tested the driver, andcontributed bug reports and fixes.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -