The ATA/IDE Interface Can we write a character-mode device driver for the hard disk? Persistent data storage • Our ‘dram.c’ module implemented a Linux driver for the processor’s physical memory • That primary storage was ‘volatile’ – all its data disappears when power is turned off • But secondary storage, provided by disks, is ‘persistent’ – the data is preserved even when the power supply gets interrupted Hardware interfacing • To gain experience with writing drivers for actual hardware, we propose to construct a character-mode device driver, similar to our ‘dram.c’ module, which will allow us to read and write to a portion of the hard disk • This will acquaint us – at an elementary level -- with many of the key issues that hardware interfacing typically involves A few cautions • Our classroom and laboratory computers are shared by many users who are taking various computer sciences courses • Writing to the hard disk in a careless way can do damage to the operating systems (making a machine completely unusable) • Our first job will be to discover what areas on our hard disk can be safely modified Fixed-Size ‘blocks’ • All data-transfers to and from the hard disk are comprised of fixed-size blocks called ‘sectors’ (whose size equals 512 bytes) • On modern hard disks, these sectors are identified by sector-numbers starting at 0 • This scheme for addressing disk sectors is known as Logical Block Addressing (LBA) • So the hard disk is just an array of sectors Visualizing the hard disk A large array of 512-byte disk sectors 0 1 2 3 ….. Disk storage-capacity (in bytes) = (total number of sectors) x (512 bytes/sector) Disk Partitions • The total storage-area of the hard disk is usually subdivided into non-overlapping regions called ‘disk partitions’ Partition #1 Partition #2 Partition #3 unused Master Boot Record • A small area at the beginning of the disk is dedicated to ‘managing’ the disk partitions 0 1 2 … MBR partition #1 • In particular, sector number 0 is known as the Master Boot Record (very important!) Format of the MBR • The MBR is subdivided into three areas: – The bootstrap loader program – The ‘partition table’ data-structure – The MBR signature (i.e., 0x55, 0xAA) 512 bytes Bootstrap Loader (446 bytes) Partition Table (64 bytes) signature (2 bytes) ‘Safe’ areas • If our hard disk contains ‘unused’ sectors, then we could safely modify their contents • Or if our hard disk contains a partition that nobody currently uses, then we could just take over its sectors for our own purposes -- at least during this current semester • So we need to look at the ‘partition table’ to find out if any ‘safe areas’ are available ‘Reading’ the MBR • To get the hard disk’s Partition Table, we must ‘read’ the entire Master Boot Record • (We ignore the boot-loader and signature) • But we will need to understand the format of the data stored in that Partition Table • And we will need to know how to devise a privileged code-fragment that can transfer the MBR (sector 0) from disk to memory Partition Table Entries • The MBR is an array containing four datastructures (called ‘partition table entries’): 16 bytes S T A T U S T Y P E Starting sector ID-number Partition length (in sectors) Some fields contain ‘obsolete’ information TYPE-ID • Each partition-table entry has a TYPE-ID – TYPE-ID is 0x07 for a ‘Windows’ partition – TYPE-ID is 0x83 for our ‘Linux’ partition – TYPE-ID is 0x00 when the entry is ‘unused’ • You can find a list of TYPE-ID numbers posted on the internet (see our website) • Our hard disks have a ‘Minix’ partition that nobody is using during Spring semester How can we read the MBR? • Our device-driver must send a command to the Hard Disk Controller, together with command-parameters that specify which disk sector we want to read (i.e., sector 0) • But we can’t issue a fresh command if the controller is still busy processing an earlier command (e.g., issued by the OS kernel) • So we also need to get controller ‘status’ The ATA/IDE Interface • All communication between our driver and the Hard Disk Controller is performed with ‘in’ and ‘out’ instructions that refer to ports • PCs have standard i/o port-numbers for communicating with the Disk Controller • Altogether twelve registers are involved, using nine different I/O Port-Numbers Command Block registers • When reading… – – – – – – – – Data Error Sector Count LBA Low LBA Mid LBA High Device Status • When writing… – – – – – – – – Data Features Sector Count LBA Low LBA Mid LBA High Device Command Control Block Registers • When reading… • When writing… – Alternate Status – Device Control INCRITS InterNational Committee on Information Technology Standards Committee T-13 Algorithm overview • First select the device to read from: – Wait until the controller is not busy and does not have any data that it wants to transfer – Write to Command Block’s Device register to select the disk to send the command to – Wait until the controller indicates that it is ready to receive your new command Overview (continued) • Place the command’s parameters into the appropriate Command Block registers • Put command-code in Command register • Then wait until the controller indicates that it has read the requested sector’s data and is ready to transfer it to your device driver • Use a loop to input 256 words (one sector) from the Command Block’s Data register Overview (conclusion) • After your driver has transferred a sector, check the Controller Status to see if there was any error (if so read the Error register) • To implement this algorithm, we need to look at the meaning of some individual bits in the Status register (and Error register) Status register (port 0x1F7) 7 6 5 BSY DRDY DF 4 3 DRQ 2 1 0 ERR Legend: BSY (Device still Busy with prior command): 1=yes, 0=no DRDY (Device is Ready for a new command): 1=yes, 0=no DF (Device Fault – command cannot finish): 1=yes, 0=no DRQ (Data-transfer is currently Requested): 1=yes, 0=no ERR (Error information is in Error Register): 1 = yes, 0=no Device register (0x1F6) 7 6 5 4 1 LBA (=1) 1 DEV (0/1) 3 2 1 0 Sector-ID[ 27..24 ] Legend: LBA (Logical Block Addressing): 1=yes, 0=no DEV (Device selection): 1=slave, 0=master Sector-ID: Most significant 4-bits of 28-bit Sector-Address Error register (0x1F1) 7 6 5 4 3 2 1 UNC MC IDNF MCR ABRT NM Legend: UNC (Data error was UnCorrectable): 1=yes, 0=no MC (Media was Changed): 1=yes, 0=no IDNF (ID Not Found): 1=yes, 0=no MCR (Media Change was Requested): 1=yes, 0=no ABRT (Command was Aborted): 1 = yes, 0=no NM (No Media was present): 1=yes, 0=no 0 Device Control register (0x3F6) 7 6 5 4 3 2 1 0 HOB 0 0 0 0 SRST nIEN 0 Legend: HOB (High-Order Byte): 1=yes, 0=no SRST (Software Reset requested): 1=yes, 0=no nIEN (negate Interrupt Enabled): 1=yes, 0=no NOTE: The HOB-bit is unimplemented on our machines; it is for large-capacity disks that require 44-bit sector-addresses Demo module: ‘mbr.c’ • We have created a miniature device-driver which implements read-only access to our hard disk’s Master Boot Record (sector 0) • Its purpose is two-fold: – It shows how you can read a disk sector – It lets you find out where the ‘minix’ partition begins and ends on our disk (the ‘safe’ area) In-Class Exercise • Compile and install the ‘mbr.c’ driver • Then write an application program that a user can execute to open the ‘/dev/hd’ device-file, seek to the proper offset, read the 64-byte Partition Table data-structure, and display its four Partition Table Entries on the screen (in hexadecimal format) • Identify the TYPE-ID of each partition, and see where the ‘minix’ area starts and ends