DOC PREVIEW
USF CS 635 - Lecture Notes

This preview shows page 1-2-24-25 out of 25 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

Our ‘recv1000.c’ driverSimilarities‘push’ versus ‘pull’Sleep/wakeupSlide 5How NIC’s interrupts workInterrupt event-typesInterrupt Mask Set/ReadInterrupt Mask ClearInterrupt Cause ReadInterrupt Cause SetOur interrupt-handlerWe ‘tweak’ our packet-formatOur ‘read()’ methodHardware’s initializationSlide 16Packet-Split Rx Control (0x2170)Receive Filter Control (0x5008)RX Checksum Control (0x5000)Slide 20Maximum-size buffersNIC “owns” our rx-descriptorsDriver ‘defects’In-class exercise #1In-class exercise #2Our ‘recv1000.c’ driverImplementing a ‘packet-receive’ capability with the Intel 82573L network interface controllerSimilarities•There exist quite a few similarities between implementing the ‘transmit-capability’ and the ‘receive-capability’ in a device-driver for Intel’s 82573L ethernet controller:–Identical device-discovery and ioremap steps–Same steps for ‘global reset’ of the hardware–Comparable data-structure initializations–Parallel setups for the TX and RX registers •But there also are a few fundamental differences (such as ‘active’ versus ‘passive’ roles for driver)‘push’ versus ‘pull’Host memorytransmitpacketbuffertransmit-FIFO pushEthernet controllerreceive-FIFOreceivepacketbufferpullto/from LAN The ‘write()’ routine in our ‘xmit1000.c’ driver could transfer data at any time, but the ‘read()’ routine in our ‘recv1000.c’ driver has to wait for data to arrive. So to avoid doing any wasteful busy-waiting, our ‘recv1000.c’ driver can use the Linux kernel’s sleep/wakeup mechanism – if it enables NIC’s interrupts!Sleep/wakeup•We will need to employ a wait-queue, we will need to enable device-interrupts, and we will need to write and install the code for an interrupt service routine (ISR)•So our ‘recv1000.c’ driver will have a few additional code and data components that were absent in our ‘xmit1000.c’ driverThis function will program the actual data-transferDriver’s componentsreadmy_fops my_read() module_init() module_exit()This function will allow us to inspect the receive-descriptors This function will detect and configure the hardware, define page-mappings, allocate and initialize the descriptors, install our ISR and enable interrupts, start the ‘receive’ engine, create the pseudo-file and register ‘my_fops’ This function will do needed ‘cleanup’ when it’s time to unload our driver – turn off the ‘receive’ engine, disable interrupts and remove our ISR, free memory, delete page-table entries, the pseudo-file, and the ‘my_fops’ ‘struct’ holds one function-pointer my_get_info()This function will awaken any sleeping reader-task my_isr()wait_queue_headHow NIC’s interrupts work•There are four interrupt-related registers which are essential for us to understandICR0x00C00x00C80x00D00x00D8ICSIMSIMCInterrupt Cause ReadInterrupt Cause SetInterrupt Mask Set/ReadInterrupt Mask ClearInterrupt event-typesreservedreserved82573L31: INT_ASSERTED (1=yes,0=no)31 30 18 17 16 15 14 10 9 8 7 6 5 4 2 1 017: ACK (Rx-ACK Frame detected)16: SRPD (Small Rx-Packet detected)15: TXD_LOW (Tx-Descr Low Thresh hit) 9: MDAC (MDI/O Access Completed) 7: RXT0 ( Receiver Timer expired) 6: RXO (Receiver Overrun) 4: RXDMT0 (Rx-Desc Min Thresh hit) 2: LSC (Link Status Change) 1: TXQE( Transmit Queue Empty) 0: TXDW (Transmit Descriptor Written Back)Interrupt Mask Set/Read•This register is used to enable a selection of the device’s interrupts which the driver will be prepared to recognize and handle•A particular interrupt becomes ‘enabled’ if software writes a ‘1’ to the corresponding bit of this Interrupt Mask Set register•Writing ‘0’ to any register-bit has no effect, so interrupts can be enabled one-at-a-timeInterrupt Mask Clear•Your driver can discover which interrupts have been enabled by reading IMS – but your driver cannot ‘disable’ any interrupts by writing to that register•Instead a specific interrupt can be disabled by writing a ‘1’ to the corresponding bit in the Interrupt Mask Clear register •Writing ‘0’ to a register-bit has no effect on the interrupt controller’s Interrupt MaskInterrupt Cause Read•Whenever interrupts occur, your driver’s interrupt service routine can discover the specific conditions that triggered them if it reads the Interrupt Cause Read register•In this case your driver can clear any selection of these bits (except bit #31) by writing ‘1’s to them (writing ‘0’s to this register will have no effect) •If case no interrupt has occurred, reading this register may have the side-effect of clearing itInterrupt Cause Set•For testing your driver’s interrupt-handler, you can artificially trigger any particular combination of interrupts by writing ‘1’s into the corresponding register-bits of this Interrupt Cause Set register (assuming your combination of bits corresponds to interrupts that are ‘enabled’ by ‘1’s being present for them in the Interrupt Mask)Our interrupt-handler•We decided to enable all possible causes (and we ‘log’ them via ‘printk()’ messages we’ve omitted in the code-fragment here): irqreturn_t my_isr( int irq, void *dev_id ) {int intr_cause = ioread32( io + E1000_ICR );if ( intr_cause == 0 ) return IRQ_NONE;wake_up_interruptible( &wq_rd );iowrite32( intr_cause, io + E1000_ICR );return IRQ_HANDLED;}We ‘tweak’ our packet-format•Our ‘xmit1000.c’ driver elected to have the NIC append ‘padding’ to any short packets•But this prevents a receiver from knowing how many bytes represent actual data •To solve this problem, we added our own ‘count’ field to each packet’s payload actual bytes of user-data0 6 12 14destination MAC-address source MAC-addressType/LencountOur ‘read()’ methodssize_t my_read( struct file *file, char *buf, size_t len, loff_t *pos ){static int rxhead = 0; // to remember where we left offunsigned char *from = phys_to_virt( rxdesc[ rxhead ].base_addr );unsigned int count;// go to sleep if no new data-packets have been received yetif ( ioread32( io + E1000_RDH ) == rxhead )if ( wait_event_interruptible( wq_rd, ioread32( io + E1000_RDH ) != rxhead ) ) return –EINTR;// get the number of actual data-bytes in the new (possibly padded)


View Full Document

USF CS 635 - Lecture Notes

Download Lecture Notes
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Lecture Notes and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Lecture Notes 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?