====== Differences ====== This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
soc:2008:mdeck:journal:week3 [2008/06/12 13:35] mdeck |
soc:2008:mdeck:journal:week3 [2008/06/15 14:00] (current) mdeck |
||
---|---|---|---|
Line 53: | Line 53: | ||
Things are starting to pick up now with a live, breathing driver to play with! :-D | Things are starting to pick up now with a live, breathing driver to play with! :-D | ||
+ | |||
+ | === 14 June === | ||
+ | |||
+ | I spent some time today reading up on **how to transition to dynamic allocation for the tx & rx descriptors**. I started with the Intel datasheet, wherein I recalled some mention of simple and flexible memory modes, which allow separation of the data buffer from the descriptor. | ||
+ | |||
+ | From the beginning of Chapter 6: | ||
+ | <file>Note: Although references are made to both simplified and flexible memory modes for transmit and | ||
+ | receive commands, only the simplified mode is supported. All bit settings and silicon | ||
+ | configurations only refer to the simplified memory mode.</file> | ||
+ | So, is flexible memory mode supported or not? | ||
+ | |||
+ | Section 6.4.3.1.2 details the RFD (receive frame descriptor) format. The SF bit: | ||
+ | <file>SF (Bit 19) The SF bit equals 0 for simplified mode.</file> | ||
+ | So then, does setting this =1 support flexible mode? | ||
+ | |||
+ | Then I found this blurb on the H bit: | ||
+ | <file>H (Bit 20) The H bit indicates if the current RFD is a header RFD. If it equals 1, the current RFD is | ||
+ | a header RFD, and if it is 0, it is not a header RFD. | ||
+ | NOTE: If a load HDS command was not previously issued, the device disregards this | ||
+ | bit.</file> | ||
+ | It appears, if you request 'early interrupts', an interrupt occurs when the header portion of an Ethernet packet is received. This early data goes into a header RFD. | ||
+ | The load HDS command: | ||
+ | <file>101 Load Header Data Size (HDS). After a load HDS command is issued, the | ||
+ | device expects to only find header RFDs or to be used in Receive DMA mode | ||
+ | until it is reset. This value defines the size of the header portion of the RFDs or | ||
+ | receive buffers. The HDS value is defined by the lower 14 bits of the SCB | ||
+ | General Pointer; thus, bits 15 through 31 should always be set to zeros when | ||
+ | using this command. The value of HDS should be an even non-zero number</file> | ||
+ | So now, what is 'Receive DMA mode'? | ||
+ | I found a mention of it: | ||
+ | <file>011 Receive DMA Redirect. This command is only valid for the 82558 and later | ||
+ | devices. The buffers are indicated by an RBD chain, which is pointed to by an | ||
+ | offset stored in the general pointer register (in the RU base).</file> | ||
+ | Aha! So it seems this 'Receive DMA mode' is what allows your rx data to be separate from the rx descriptor. This blurb seems to indicate such functionality is only available on the 82558 and later. | ||
+ | |||
+ | So then I looked at how the linux drivers are handling their rx buffers. There are actually two linux drivers for these NICs - eepro100.c and e100.c. The former is what the gPXE driver is based on, the latter is written by Intel. | ||
+ | |||
+ | Both linux drivers appear to use the simplified rx mode, and store both the RFD header and rx data within their buffers. Prior to handing off the rx data to the network subsystem, the buffer's internal data pointer is adjusted to point at the packet data. | ||
+ | |||
+ | Looking at gPXE's io_buffer structure, it appears I can do the same: | ||
+ | <code c> | ||
+ | /** | ||
+ | * A persistent I/O buffer | ||
+ | * | ||
+ | * This data structure encapsulates a long-lived I/O buffer. The | ||
+ | * buffer may be passed between multiple owners, queued for possible | ||
+ | * retransmission, etc. | ||
+ | */ | ||
+ | struct io_buffer { | ||
+ | /** List of which this buffer is a member | ||
+ | * | ||
+ | * The list must belong to the current owner of the buffer. | ||
+ | * Different owners may maintain different lists (e.g. a | ||
+ | * retransmission list for TCP). | ||
+ | */ | ||
+ | struct list_head list; | ||
+ | |||
+ | /** Start of the buffer */ | ||
+ | void *head; | ||
+ | /** Start of data */ | ||
+ | void *data; | ||
+ | /** End of data */ | ||
+ | void *tail; | ||
+ | /** End of the buffer */ | ||
+ | void *end; | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | I then decided it'd be best to make my planned **formatting changes** //now//, rather than continue to prolong the inevitable changes. Thus, I spent some time making //purely formatting changes//, that is, no changes to what the code actually does changed, except for a few debug statements. | ||
+ | The diff probably won't be of use, as it's all different :-) | ||
+ | * [[http://git.etherboot.org/?p=people/mdeck/gpxe.git;a=commit;h=b7ff5f923bdc7970839819c48942c22ac79c7454|[Drivers-eepro100] Purely formatting changes. New header. IFEC.]] | ||
+ | I removed the description of operation as it's all changing. I'll write in a new description once the final driver operation is set. IFEC = Intel Fast Ethernet Controller. From what I can find, it seems only these controllers are referred to as Fast Ethernet Controllers by Intel. It's short and simple. | ||
+ | |||
+ | === 15 June === | ||
+ | |||
+ | I rewrote ''ifec_scb_cmd_wait()''. Now it returns an error code if the command unit doesn't become ready within a timeout interval. The timeout is a configurable ''#define CU_CMD_TIMEOUT''. The return code is propagated through ''ifec_scb_cmd()'', so the caller can check that if they want. | ||
+ | * Commit: [[http://git.etherboot.org/?p=people/mdeck/gpxe.git;a=commit;h=e629a17b8b74b74a759a5ef4bfe971976837cce3|[Drivers-eepro100] Update ifec_scb_cmd_wait, more formatting.]] | ||
+ | I rearranged operations in ''ifec_net_open()'', to give a seemingly more logical order. It seems to work the same, I wonder if this makes a difference. | ||
+ | * Commit: [[http://git.etherboot.org/?p=people/mdeck/gpxe.git;a=commit;h=c7e921e8b2dba0d40a81cbee32f5dd265b86dae1|[Drivers-eepro100] Rearranged ifec_net_open() operations.]] | ||
+ | After the last commit, I considered there may be some nuance to the hardware design that makes the original ordering always work, and the new ordering occasionally fail. I wouldn't notice this for a while. | ||
+ | |||
+ | This got me wondering if I should strive to keep the drivers as close to the original Linux version as possible. This could take advantage of any subtle hardware problems that their code has evolved to avert. | ||
+ | |||
+ | Although I may just be over-thinking things. One would hope any hardware defects would be clearly identified. Would the Intel engineers releasing open-source drivers for their hardware spell out how they worked around hardware bugs..? I wonder if my work over the past few days hasn't been a waste. | ||
+ | |||
+ | I haven't spoken to Marty since making these changes, so we'll see what he says. | ||
+ | |||
+ | Tomorrow I hope to integrate dynamic allocation for the tx & rx, as well as expand tx to multiple descriptors. |