All reading and writing of blocks is done through the strategy routine. This routine takes no arguments and returns nothing, but it knows where to find a list of requests for I/O (CURRENT, defined by default as blk_dev[MAJOR_NR].current_request), and knows how to get data from the device into the blocks. It is called with interrupts disabled so as to avoid race conditions, and is responsible for turning on interrupts with a call to sti() before returning.
The strategy routine first calls the INIT_REQUEST macro, which makes sure that requests are really on the request list and does some other sanity checking. add_request() will have already sorted the requests in the proper order according to the elevator algorithm (using an insertion sort, as it is called once for every request), so the strategy routine ``merely'' has to satisfy the request, call end_request(1), which will take the request off the list, and then if there is still another request on the list, satisfy it and call end_request(1), until there are no more requests on the list, at which time it returns.
If the driver is interrupt-driven, the strategy routine need only schedule the first request to occur, and have the interrupt-handler call end_request(1) and the call the strategy routine again, in order to schedule the next request. If the driver is not interrupt-driven, the strategy routine may not return until all I/O is complete.
If for some reason I/O fails permanently on the current request, end_request(0) must be called to destroy the request.
A request may be for a read or write. The driver determines whether a request is for a read or write by examining CURRENT->cmd. If CURRENT->cmd == READ, the request is for a read, and if CURRENT->cmd == WRITE, the request is for a write. If the device has seperate interrupt routines for handling reads and writes, SET_INTR(n) must be called to assure that the proper interrupt routine will be called.
[Here I need to include samples of both a polled strategy routine and an interrupt-driven one. The interrupt-driven one should provide seperate read and write interrupt routines to show the use of SET_INTR.]