I. Overview
The first thing to note is that each time the kernel reads and writes data, the Unit is a logical block, that is, 1024b, and the block device controller is a sector (512b.
Read/write operations on hard disks are interruptedProgramThe read/write request items are waiting for the queue to buffer the read/write operations of multiple logical blocks at a time in sequence. Process read
When a logical block on the hard disk is applied to the buffer management program, and then enters the sleep state. The buffer manager checks whether the buffer has been read before.
This piece of data, if any, directly returns the corresponding buffer block header pointer to the process and wake it up, otherwise, calls ll_rw_block () to send the corresponding Device Driver
An operation request for reading data blocks. This function creates a request structure item and inserts it into the queue. Elevator is used during insertion.Algorithm(The elevator algorithm has not been read yet ). For example
If the device Request queue is empty, the device is not busy and immediately sends a READ command to the device controller. When the device controller reads data into the specified buffer
The system sends an interrupt request signal and calls the corresponding READ command post-processing function to process the process of continuing the read sector operation or ending the request item. (From instructor Zhao Yu)
Ii. Data Structure
Block device item
Struct blk_dev_struct {
Void (* request_fn) (void); // function pointer of the request item operation
Struct Request * current_request; // current request item pointer
};
Block device table
Extern struct blk_dev_struct blk_dev [nr_blk_dev]; // each block device occupies one of the seven items in the table
Request item
Struct request {
Int dev;/*-1 if no request */
Int cmd;/* read or write */
Int errors; // number of errors
Unsigned long sector; // start slice (********? *******)
Unsigned long nr_sectors; // Number of read/write sectors
Char * buffer; // data buffer
Struct task_struct * Waiting; // process that sends the request
Struct buffer_head * BH; // buffer Header
Struct Request * next;
};
Request item Array
Extern struct request [nr_request]; // 32 items in total
The request item queue consists of items in the request item array,
3. Hard drive program
Files involved: BLK. H, HD. C, ll_rw_block.c
BLK. h defines the data structure listed above, the elevator algorithm (which is actually implemented using a macro definition), and the extern inline type such as unlocking the specified buffer block and ending request processing.
(Only used as an embedded function ).
HD. c is the hardware controller driver. When controlling the hard disk controller, both the parameter (6B) and command (1B) must be sent ). Follow these steps to concatenate almost all functions in the HD. c file.
1. Check controller idle status: read Master Status Register. If busy_stat (bit 7) is 0, it indicates idle. If the Controller is always busy within the specified time, a timeout error occurs. This part is composed
Controller_ready function implementation:
Static int controller_ready (void)
{
Int retries = 10000;
While (-- retries & (inb_p (hd_status) & 0xc0 )! = 0x40 );
Return (retries );
}
2. Check that the drive is ready: Determine whether the ready_stat (bit 6) of the Master Status Register is 1;
Static int drive_busy (void)
{
Unsigned int I;
For (I = 0; I <10000; I ++)
If (ready_stat = (inb_p (hd_status) & (busy_stat | ready_stat )))
Break;
I = INB (hd_status );
I & = busy_stat | ready_stat | seek_stat;
If (I = (ready_stat | seek_stat ))
Return (0 );
Printk ("HD controller times out/n/R ");
Return (1 );
}
3. The output command block outputs parameters and commands to the corresponding port. hd_out function is implemented.
Static void hd_out (unsigned int drive, unsigned int nsect, unsigned int sect,
Unsigned int head, unsigned int cyl, unsigned int cmd,
Void (* intr_addr) (void ))
{
Register int port ASM ("dx ");
If (drive> 1 | HEAD> 15)
Panic ("trying to write bad sector ");
If (! Controller_ready ())
Panic ("HD controller not ready ");
Do_hd = intr_addr;
Outb_p (hd_info [Drive]. CTL, hd_cmd );
Port = hd_data;
Outb_p (hd_info [Drive]. wpcom> 2, ++ port );
Outb_p (nsect, ++ port );
Outb_p (sect, ++ port );
Outb_p (CYL, ++ port );
Outb_p (CYL> 8, ++ port );
Outb_p (0xa0 | (drive <4) | head, ++ port );
Outb (CMD, ++ port );
}
4. Wait for the interruption to occur. After the command is executed, the hard disk controller generates an interrupt request signal or sets the status of the Controller to idle, indicating that the operation is complete or the request is transmitted in a sector. Interruption in HD. c
Five functions are called during the processing, namely, void unexpected_hd_interrupt (void), static void bad_rw_intr (void), static void read_intr (void), static void write_intr (void ), static void recal_intr (void ).
5. operation Check Result: the CPU reads the Master Status Register again. If the bit 0 is 0, the command is successfully executed; otherwise, the command fails. If the bit 0 is 0, the error register (hd_error) can be further queried) get the error code. The related function is static int win_result (void ).
Static int win_result (void)
{
Int I = inb_p (hd_status );
If (I & (busy_stat | ready_stat | wrerr_stat | seek_stat | err_stat ))
==( Ready_stat | seek_stat ))
Return (0);/* OK */
If (I & 1) I = INB (hd_error );
Return (1 );
}
The whole process is controlled and executed by void do_hd_request (void.
The ll_rw_block.c program is mainly used to perform read and write operations on the underlying block device. It creates a device read/write entry for the fast device and inserts it into the request queue of the specified block device. Its call relationship,
To the file system.