---
created_at: '2017-12-12T08:36:23.000Z'
title: Using an IDE Hard Drive with a 8051 Board and 82C55 Chip (2005)
url: https://www.pjrc.com/tech/8051/ide/index.html
author: peter_d_sherman
points: 72
story_text: 
comment_text: 
num_comments: 18
story_id: 
story_title: 
story_url: 
parent_id: 
created_at_i: 1513067783
_tags:
- story
- author_peter_d_sherman
- story_15903938
objectID: '15903938'

---
[Source](https://www.pjrc.com/tech/8051/ide/index.html "Permalink to Paul's 8051 Code Library, IDE Hard Drive Interface")

# Paul's 8051 Code Library, IDE Hard Drive Interface



| ----- |
| 

|  ![skip navigational links][1]![PJRC][2] | 

 |   |  
|  [Shopping Cart][3] ![][4] [Checkout][5] ![][4] [Shipping Cost][6] ![][4] [Download Website][7]  | 

| ----- |
|  [Home][8] |  [Products][9] |  [Teensy][10] |  [Blog][11] |  [Forum][12] | 

| ----- |
|  You are here: [8051 Tools][13] ![][14] [Code Library][15] ![][14] [IDE Hard Drive][16] ![][14] Main Page  |   | 

| ----- |
| 

|  **PJRC Store**  |  
|  ![][4] [8051 Board, $79][17]  

![][4] [LCD 128x64 Pixel, $29][18]  
![][4] [LCD 16x2 Char, $14][19]  
![][4] [Serial Cable, $5][20]  
![][4] [9 Volt Power, $6][21]  
![][4] [More Components...][22]  

                             |  |  
| -------------------------- |  
| **8051 Tools**             |  
| ![][4] [Main Page][23]    

![][24][ **Software**][25]  
![][24][ **PAULMON Monitor**][26]  
![][24][ **Development Board**][27]  
![][14] **Code Library**  

![][4] [Serial I/O, Polled][15]  
![][4] [Automatic Baud Rate][28]  
![][4] [Serial I/O, Intr.][29]  
![][4] [Lexer][30]  
![][4] [Random Numbers][31]  
![][4] [Serial EEPROM][32]  
![][4] [AMD 28F256 Flash][33]  
![][4] [Xilinx 3000][34]  
![][14] **IDE Hard Drive**  

![selected][14] Main Page  
![][4] [FAT32 Info][35]  
![][4] [Peter Faasse][36]  

![][4] [Tiny Basic][37]  

![][24][ **89C2051 Programmer**][38]  
![][24][ **Other Resources**][39]  
 |  
|  | 

  
 |   | 

# Using an IDE Hard Drive with a 8051 Board and 82C55 Chip

* [Overview][40]
* [Limitations][41]
* [Credit Where Credit Is Due][42]
* [Physcial Connection & Schematic][43]
* [Logical Block Addressing][44]
* [Routines - How You Use This Code][45]
* [Master and Slave Device Settings][46]
* [Usage - The Included Demo Program][47]
* [Pinout Troubleshooting Utility][48]
* [Download The Code][49]

### Overview

This page describes a simple design that connects a standard IDE interface hard drive to a 8051 board, such as the [newer development board][50], using the 82C55 chip. Figure 1 shows the board and drive that was used to test this code. 

| ----- |
|  ![Photo: Dev Board With IDE Drive Attached][51] |  
| **Figure 1**: Development Board With IDE Drive Connected |  | |

  

### Limitations

This code only provides the ability to access raw sectors. It does **not** implement a filesystem, such as FAT16 or FAT32 or even Linux romfs. If you want to access data stored by DOS/Windows, or store data that will be readable without special drivers... well, you'll have a lot of code to write! If your project is well funded, you could buy the filesystem code from a company such as _US Software_ (now defunct). 

Update: the [New MP3 Player project][52] has [firmware with FAT32 support][53]. 

The speed is **slow**. Data transfer is not fast, compared with a PC computer. The 8051 isn't fast, and there is overhead dealing with the 82C55 chip. There is a somewhat faster (optimized) version of this code available, but without much information about the optimizations. The faster version was used in a project that sustained reads of 24 kbytes/sec, while also doing some serial communication, with a 14.7456 MHz system clock. The normal version is believed to be able to read at about 16 kbytes/sec, but this hasn't been verified. 

These routines wait for the drive to complete its operations using busy loops. There are no timeouts, so if the drive fails or becomes disconnected, the code may hang forever waiting for the drive. For any sort of serious application, at least timeouts should be added, and some applications must not have busy loops, so this code would need to be restructured somewhat. Still, it is a working example that should provide a reasonable start for a 8051-based project that needs to access a hard disk drive. 

And of course, there is no warranty of any kind (see the [download section][49]), but it's free. 

### Credit Where Credit Is Due

Peter Faasse, some time ago wrote a very nice text file about interfacing an IDE hard drive to a 63B03 using a 8255 chip. Copies may be found at [Wesley's PIC Pages][54] (nice HTML version), or this [zip file containing the original text file][55]. Peter's paper was very helpful and was the primary source I used to learn about the IDE interface. Peter's paper gives a very good example to follow and it explains the IDE interface very nicely. Peter's project interfaced an IDE drive with an 8255 chip, which luckily was the same one I wanted to use. I would not have initially used the inverters, without his warning about the 8255's funny behaviour when it is reconfigured. 

Alex T. Ivopol's [IDE - Hardware Reference][56] in a good technical summary of IDE/ATA. This is where I first learned about the 0x91 command (see the [LBA][44] section). Peter den Haan's [Enhanced IDE FAQ][57] is also a great place to look for information, though it's more oriented towards PC users than embedded systems developers. Peter has links to most of the on-line resources. 

The ATA specs appear to no longer be available on-line, and need to be ordered $$$ from ANSI. I did not order any of them, so bear in mind that some of this material was based on a bit of guesswork, and the prior work of Peter Faasse did. **Update**: it looks like you can get copies on-line now, the [docs page at Peter Kovacs's mp3projects.com site][58] seems to have a good set of links. Other home-built MP3 player project pages also have copies or links now. 

After doing this project, I found other similar pages. The one at [Zel Electronics][59] claims to interface to an 8255 chip. They give details about the hardware, but they don't show a copy of their code. [Carsten Groen][60] has a page that gives C code, but not much info about the hardware required. 

### Physcial Connection

It's remarkably easy to connect an IDE drive to the 8255. Figure 2 shows the the construction used to add the IDE interface to a development board. It is important to keep in mind where pin 1 is located. Many of the diagrams available on the net, including Peter's text file, show the pinout for the IDC (ribbon cable mount) socket, looking into the holes. If you build this circuit, it's a good idea to refer to these figures or a known-correct board with the pins clearly labeled. 

| ----- |
|  ![Photo: Close-Up of IDE Circuit][61]  |  
| **Figure 2**: IDE Interface Circuit. Very few parts are needed. Pin 1 is located at the upper right. Pin 20 is removed. Had a connecter with a polarizing notch been used, the notch would appear at the top of this picture, opposite the even numbered side, with pin 20 removed. | 

A 74HC04 (or similar inverter chip), the IDE connector, and wires are about all you will need. The LED shows drive activity, just like one on the front of a PC. I used the inverter because of Peter's suggestion of the troubles with the 8255. I did not try without the inverter and inverting the signals in the code. Figure 3 shows the schematic between the 82C55 chip and the IDE connector. For the board itself, see the [development board schematic page][62]. 

| ----- |
|  ![Schematic Diagram][63] 
| **Figure 3**: Schematic Diagram, only one chip and a few passive parts are required to connect the IDE drive to the 82C55 chip.  | 

Making the connections with point-to-point wiring is relatively easy. Figure 4 shows the wiring I used. Pay careful attention to which port is which and where pin 1 is located. It can be easy to get it backwards... or at least it was easy for me on my first attempt. 

| ----- |
|  ![Photo: Close-Up of Point-to-Point Wiring][64]  |  
| **Figure 4**: Point to Point Wiring, to connect the components as shown above. Note the dot on the left side of the IDE connector, which marks pin 1. Along the top, Port A is on the left, Port B is in the middle, and Port C is on the right.  | 

### Logical Block Addressing

Originally I tried to access the hard drive using Cylinder/Head/Sector (CHS) addressing, and it would not work properly. All of these early attempts were with a Western Digital 1.2 gig drive. I could read the first sector, C=0, S=0, H=0, also known as the _Master Boot Record_ (MBR), but reading from other parts of the drive would not work. After much frustration, I discovered that the drive wanted to receive the Initialize Drive Parameters (0x91) command. I didn't find much documentation about this command on-line. I deleted all the code I wrote for CHS (except for printing info from the drive ID command). 

Logical Block Addressing (LBA) is much simpler and easier to use than CHS, and it's supported by all modern drives. With LBA, the entire drive appears as one giant array of 512 byte sectors. To access any sector, you just use one 28 bit unsigned integer to specify which one you want. The numbering is zero based, so to read the MBR, you specify 0. The code uses a 32 bit parameter, with the upper 4 bits ignored. 

The PC computer world has known a number of _barriers_ regarding hard drive size, at 32M, 528M, 2G, and 8G. These limits have been due to the filesystems used by DOS/Windows, and the parameter passing between the BIOS and DOS/Windows, and how the bits were allocated in those parameters, between Cylinders, Heads and Sectors. This code passes a single 32 bit (LBA) number, instead of 24 bits (CHS) used in the legacy PC bios calls. If you're quick with binary numbers (I am not past 65536), you probably already know that 28 bits allows 268435456 512 byte sectors, which is 128 gigabytes in computer speak, or 137 gig for hard drive marketing speak. I wonder what they'll do when the LBA address space runs out. With IBM's new 75 gig drive, it won't be long... 

### Routines - Using the Code

The example program contains four sections. The first part (not described much here) implements a small one-line menu program that lets you easily excersize the various functions from Paulmon2, without having to write any code. The IDE interface code is in two sections, one that is intended to be used by a program, and a group of low level routines. The last portion of the code are a few misc serial I/O routines not available in Paulmon2, such as the 8-byte version of ghex, used for entering a 32 bit LBA address at the menu. 

#### IDE Access Routines

`read_sector` : Read a 512 byte sector, specified by the 32 bit number in the **lba** variable (internal memory). The 512 bytes are transfered to extern memory specified by **buffer**. A status code is returned in Acc. Acc is cleared to zero on success, or set to a non-zero value if an error occurs. The error code returned is the error status code from the IDE drive. `write_sector` : Write a sector to the drive, at the location specified by **lba**. The 512 bytes from the **buffer** are written. A status code is returned in Acc. Acc is cleared to zero on success, or set to a non-zero value if an error occurs. The error code returned is the error status code from the IDE drive. `drive_id` : Ask the drive to return info about itself. This work almost exactly like the read_sector routine, except the drive's ID info is returned in the 512 byte buffer instead of a sector. The example program prints out a few of the fields from this data. For a list of which bytes mean what, grab the Linux source code. On my linux machine (2.2.13), the info is in this file: /usr/src/linux/include/linux/hdreg.h, expressed as a "struct hd_driveid", beginning on line 147. `spindown` : Ask the drive to shut down. It will stop spinning. There is not check to make sure the drive really does shut down. `spinup` : Ask the drive to power up. This routine will wait until the drive says that it is ready to execute commands. `ide_init` : This routine should be called before attempting to use the drive. It selects the master device, and waits for it to be ready. If this is called shortly after applying power to the drive, it will end up waiting until the drive spins up and finished its self check. This routine sends the Init Parameters command. You may need to edit the constants sent to the drive. It also sends the Recal command, which may be totally unnecessary. There is no return value for success or failure. If there is no drive connected, this code will probably hang and never return. 

#### Low-Level Routines

Ordinarily you wouldn't call these routines from your main program. They are intended to be used by the above routines. 

`read_data` : Transfer 512 bytes from the drive to the 8051's buffer in external memory. `wr_lba` : Copy the LBA number from the 4-byte **lba** variable in internal ram to the drive's registers. `ide_busy` : Wait while the drive is busy. This will wait forever if the drive stays busy for some reason. A timeout should probably be added. `ide_drq` : Wait for the drive to be ready to transfer data. This will wait forever if the drive never says it is ready. A timeout should probably be added. `ide_rd` : Read from one of the drive's registers. Acc specifies which register to read, and R2/R3 contain the 16 bit data. For 8 bit reads, just ignore R3. `ide_wr` : Write to one of the drive's registers. Acc specifies which register to write into, and R2/R3 contain the 16 bit data. For 8 bit writes, the drive ignores whatever is in R3. `ide_hard_reset` : Give the drive a physical reset signal. 

### Master and Slave Device Settings

This code always attempts to access the Master IDE device. It will not work correctly if you connect one device, configured to be a IDE Slave device. Many hard drives, including the Western Digital drives I've used, can be configured as Master, Slave, Stand Alone, and Cable Select. For the Western Digital drive, the stand alone mode is with no jumpers installed, and the other three correspond to placing a jumper in one of three positions. 

The stand alone mode configures the drive as a Master, but it differs from the Master setting in that it doesn't wait for the Slave device when doing the self test after a hard reset. Other than starting up much sooner, I could not find other differences between the Master and stand alone setting. 

Pin 34 (PDIAG) should not be connected. Without the ATA spec, I can only make some guesses about this pin. It seems to be used by the drives during their self-test. It is not used to select which drive will execute a command. 

There is no specific hardware pin that select which drive will execute a command. The Master vs Slave selection is done by setting or clearing a bit in the **Head** register. Both drives hear the computer writing, but only the drive that heard its setting will respond to the command. To use a Slave device, this bit would need to be changed in **ide_init** and **wr_lba**. 

### Using The Included Demo Program

The example code includes a small one-line menu program which let's excersize the functions easily. The program is intended to run with PAULMON2. Here is simple session using the program. 

First, download the code to PAULMON2, just like any other normal program. 

| ----- |
| 
    
    
                                                                                    
                   Welcome to PAULMON2, by Paul Stoffregen
    
      See PAULMON2.DOC, PAULMON2.EQU and PAULMON2.HDR for more information.
    
    
    Program Name                     Location      Type
    
    PAULMON2 Loc:2000 > Download
    
    Begin ascii transfer of Intel hex file, or ESC to abort
    
    ...........................................................................
    Download completed
    
    Summary:
     75  lines received
     1166  bytes received
     1166  bytes written
    No errors detected
    

 | 

Just press **R** to run the program. 

| ----- |
| 
    
    
    
    PAULMON2 Loc:2000 > Run program
    
      A - IDE Disk Drive Test
    run which program(A-A), or ESC to quit: A
    
    IDE Disk Drive Test Program
    
    Model: 7200 H                             
    S/N:   DWW-2T68303516 8    
    Cylinders: 1416, Heads: 16, Sectors: 63
                                                                                    
    LBA=0x00000000, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    

 | 

When you first run the program, it will initialize the drive, which should cause it to begin spinning. Most drives will spin up without a computer attached, but with the drive connected, it should wait until the program is run. Once the drive says it is ready, the program asks the drive for its ID info, and prints a few of the items. In this case, the drive is a Western Digital Caviar 2700. The Cylinders, Heads and Sectors shown are only the values that the drive reported. All of the code here uses [Logical Block Addressing][44]. These CHS values aren't used, but they should correspond to the ones printed on the drive's label. 

As a first step, let's read a sector. When the program starts up, the default address is 00000000, the first sector on the drive, which is the Master Boot Record that contains the partition table. To read the sector, just press **R** to read, and **H** to hexdump the buffer. 

| ----- |
| 
    
    
    Sector Read OK
    LBA=0x00000000, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
                                                                                    
    0000: FA 33 C0 8E D0 BC 00 7C 8B F4 50 07 50 1F FB FC    z3@ P< | tP P {|
    0010: BF 00 06 B9 00 01 F2 A5 EA 1D 06 00 00 BE BE 07    ?  9  r%j    >> 
    0020: B3 04 80 3C 80 74 0E 80 3C 00 75 1C 83 C6 10 FE    3  < t  < u  F ~
    0030: CB 75 EF CD 18 8B 14 8B 4C 02 8B EE 83 C6 10 FE    KuoM    L  n F ~
    0040: CB 74 1A 80 3C 00 74 F4 BE 8B 06 AC 3C 00 74 0B    Kt  < tt>  ,< t 
    0050: 56 BB 07 00 B4 0E CD 10 5E EB F0 EB FE BF 05 00    V;  4 M ^kpk~?  
    0060: BB 00 7C B8 01 02 57 CD 13 5F 73 0C 33 C0 CD 13    ; |8  WM _s 3@M 
    0070: 4F 75 ED BE A3 06 EB D3 BE C2 06 BF FE 7D 81 3D    Oum># kS>B ?~} =
    0080: 55 AA 75 C7 8B F5 EA 00 7C 00 00 49 6E 76 61 6C    U*uG uj |  Inval
    0090: 69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 62    id partition tab
    00A0: 6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E 67    le Error loading
    00B0: 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 65     operating syste
    00C0: 6D 00 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 74    m Missing operat
    00D0: 69 6E 67 20 73 79 73 74 65 6D 00 00 81 59 42 17    ing system   YB 
    00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01                    
    01C0: 01 00 0B 1F BF C2 3F 00 00 00 61 BF 15 00 00 00        ?B?   a?    
    01D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA                  U*
    

 | 

This is the MBR on this drive. The first 192 are the bootloader that is run by the bios after it reads this sector. The sixteen bytes shown in red are the first entry of the partition table. The last eight bytes indicate the where the partition begins, and how many sectors it contains, both in LBA units. The `3F 00 00 00` indicates that the first sector is at address 0000003F. The partition is 0015BF61 sectors long. That's 1425249 sectors, each 512 bytes long, which is 695.92 megabytes of data. 

Next, let's read the first sector of the partition, at LBA address 3F. 

| ----- |
| 
    
    
    LBA=0x00000000, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Enter LBA (in hex): 3F
    LBA=0x0000003F, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Sector Read OK
    LBA=0x0000003F, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
                                                                                    
    0000: EB 58 90 4D 53 57 49 4E 34 2E 31 00 02 08 20 00    kX MSWIN4.1     
    0010: 02 00 00 00 00 F8 00 00 3F 00 20 00 3F 00 00 00         x  ?   ?   
    0020: 61 BF 15 00 6F 05 00 00 00 00 00 00 02 00 00 00    a?  o           
    0030: 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0040: 80 00 29 FE 18 37 05 4E 4F 20 4E 41 4D 45 20 20      )~ 7 NO NAME  
    0050: 20 20 46 41 54 33 32 20 20 20 FA 33 C9 8E D1 BC      FAT32   z3I Q<
    0060: F8 7B 8E C1 BD 78 00 C5 76 00 1E 56 16 55 BF 22    x{ A=x Ev  V U?"
    0070: 05 89 7E 00 89 4E 02 B1 0B FC F3 A4 8E D9 BD 00      ~  N 1 |s$ Y= 
    0080: 7C C6 45 FE 0F 8B 46 18 88 45 F9 38 4E 40 7D 25    |FE~  F  Ey8N@}%
    0090: 8B C1 99 BB 00 07 E8 97 00 72 1A 83 EB 3A 66 A1     A ;  h  r  k:f!
    00A0: 1C 7C 66 3B 07 8A 57 FC 75 06 80 CA 02 88 56 02     |f;  W|u  J  V 
    00B0: 80 C3 10 73 ED BF 02 00 83 7E 16 00 75 45 8B 46     C sm?   ~  uE F
    00C0: 1C 8B 56 1E B9 03 00 49 40 75 01 42 BB 00 7E E8      V 9  I@u B; ~h
    00D0: 5F 00 73 26 B0 F8 4F 74 1D 8B 46 32 33 D2 B9 03    _ s&0xOt  F23R9 
    00E0: 00 3B C8 77 1E 8B 76 0E 3B CE 73 17 2B F1 03 46     ;Hw  v ;Ns +q F
    00F0: 1C 13 56 1E EB D1 73 0B EB 27 83 7E 2A 00 77 03      V kQs k' ~* w 
    0100: E9 FD 02 BE 7E 7D AC 98 03 F0 AC 84 C0 74 17 3C    i} >~},  p, @t <
    0110: FF 74 09 B4 0E BB 07 00 CD 10 EB EE BE 81 7D EB     t 4 ;  M kn> }k
    0120: E5 BE 7F 7D EB E0 98 CD 16 5E 1F 66 8F 04 CD 19    e> }k` M ^ f  M 
    0130: 41 56 66 6A 00 52 50 06 53 6A 01 6A 10 8B F4 60    AVfj RP Sj j  t`
    0140: 80 7E 02 0E 75 04 B4 42 EB 1D 91 92 33 D2 F7 76     ~  u 4Bk   3Rwv
    0150: 18 91 F7 76 18 42 87 CA F7 76 1A 8A F2 8A E8 C0      wv B Jwv  r h@
    0160: CC 02 0A CC B8 01 02 8A 56 40 CD 13 61 8D 64 10    L  L8   V@M a d 
    0170: 5E 72 0A 40 75 01 42 03 5E 0B 49 75 B4 C3 03 18    ^r @u B ^ Iu4C  
    0180: 01 27 0D 0A 49 6E 76 61 6C 69 64 20 73 79 73 74     '  Invalid syst
    0190: 65 6D 20 64 69 73 6B FF 0D 0A 44 69 73 6B 20 49    em disk   Disk I
    01A0: 2F 4F 20 65 72 72 6F 72 FF 0D 0A 52 65 70 6C 61    /O error   Repla
    01B0: 63 65 20 74 68 65 20 64 69 73 6B 2C 20 61 6E 64    ce the disk, and
    01C0: 20 74 68 65 6E 20 70 72 65 73 73 20 61 6E 79 20     then press any 
    01D0: 6B 65 79 0D 0A 00 00 00 49 4F 20 20 20 20 20 20    key     IO      
    01E0: 53 59 53 4D 53 44 4F 53 20 20 20 53 59 53 7E 01    SYSMSDOS   SYS~ 
    01F0: 00 57 49 4E 42 4F 4F 54 20 53 59 53 00 00 55 AA     WINBOOT SYS  U*
    

 | 

This is the first sector of a drive formatted with Windows 95. For more information about what this means, get the [FAT32 Specification from Microsoft][65]

Now let's try writing a sector. We'll copy the MBR into sector 3. First, we'll read sector 3 to see what's in it. 

| ----- |
| 
    
    
    LBA=0x0000003F, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Enter LBA (in hex): 3
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Sector Read OK
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
                                                                                    
    0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    (the rest was all zeros)
    

 | 

Now let's read the MBR (sector 0), and write it to sector 3. 

| ----- |
| 
    
    
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit               
    Enter LBA (in hex): 0
    LBA=0x00000000, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Sector Read OK
    LBA=0x00000000, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Enter LBA (in hex): 3
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Warning: this will change data on the drive, are you sure?
    Sector Write OK
    

 | 

That should have written a copy of the MBR onto sector 3. Let's read sector 3F, to make sure the buffer doesn't still have a copy of the data we wrote, and then re-read sector 3 to make sure it does indeed have the MBR data in it. 

| ----- |
| 
    
    
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Enter LBA (in hex): 3F
    LBA=0x0000003F, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Sector Read OK
    LBA=0x0000003F, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Enter LBA (in hex): 3
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    Sector Read OK
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
                                                                                    
    0000: FA 33 C0 8E D0 BC 00 7C 8B F4 50 07 50 1F FB FC    z3@ P< | tP P {|
    0010: BF 00 06 B9 00 01 F2 A5 EA 1D 06 00 00 BE BE 07    ?  9  r%j    >> 
    0020: B3 04 80 3C 80 74 0E 80 3C 00 75 1C 83 C6 10 FE    3  < t  < u  F ~
    0030: CB 75 EF CD 18 8B 14 8B 4C 02 8B EE 83 C6 10 FE    KuoM    L  n F ~
    0040: CB 74 1A 80 3C 00 74 F4 BE 8B 06 AC 3C 00 74 0B    Kt  < tt>  ,< t 
    0050: 56 BB 07 00 B4 0E CD 10 5E EB F0 EB FE BF 05 00    V;  4 M ^kpk~?  
    0060: BB 00 7C B8 01 02 57 CD 13 5F 73 0C 33 C0 CD 13    ; |8  WM _s 3@M 
    0070: 4F 75 ED BE A3 06 EB D3 BE C2 06 BF FE 7D 81 3D    Oum># kS>B ?~} =
    0080: 55 AA 75 C7 8B F5 EA 00 7C 00 00 49 6E 76 61 6C    U*uG uj |  Inval
    0090: 69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 62    id partition tab
    00A0: 6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E 67    le Error loading
    00B0: 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 65     operating syste
    00C0: 6D 00 4D 69 73 73 69 6E 67 20 6F 70 65 72 61 74    m Missing operat
    00D0: 69 6E 67 20 73 79 73 74 65 6D 00 00 81 59 42 17    ing system   YB 
    00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01                    
    01C0: 01 00 0B 1F BF C2 3F 00 00 00 61 BF 15 00 00 00        ?B?   a?    
    01D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                    
    01F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA                  U*
    
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    LBA=0x00000003, (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit
    

 | 

Indeed the MBR data was written into sector 3, which had previously contained all zeros. 

Though there is no on-screen indication, the **D** key was pressed at the end of this last example, to spin down the drive. 

That's about all that this little demo program can do, but it's an easy way to make sure that the connection to your hard drive is working properly before you attempt to use the code within your own program. 

### Pinout Troubleshooting Utility

A simple wiring test utility is provided below. If your IDE interface does not work, this little utility makes testing the wiring much easier. 

The program drives one of the 24 signals high and all the others are driven low. A simple ASCII-art graphic top view of the 40 pin header is show, with the high signal highlighted to make it easy to verify the correct signal using a multimeter. If the problem isn't easy to find, make sure you also measure the other pins using your multimeter to verify that the other 23 pins are all low (the one driven high isn't shorted to another pin). 

| ----- |
| 
    
    
    IDE Pin  7 (D5) is high, all others low.  Driven via PA.5                       
            +-----+
         1  | . . |   2
         3  | . . |   4
         5  | . . |   6
         7  | @ . |   8
         9  | . . |  10
        11  | . . |  12
        13  | . . |  14
        15  | . . |  16
        17  | . . |  18
        19  | .   |  20
        21  | . . |  22
        23  | . . |  24
        25  | . . |  26
        27  | . . |  28
        29  | . . |  30
        31  | . . |  32
        33  | . . |  34
        35  | . . |  36
        37  | . . |  38
        39  | . . |  40
            +-----+
    Press any key for next pin, or ESC to quit
    

 | 

### Download The Code

This code is distributed in the hope that it will be useful, but **without any warranty**; without even the implied warranty of _merchantability_ or _fitness for a particular purpose_. 

* [Assembly Source Code][66]. Tested on rev 5 board. 
* [Old version for rev 2 board][67]. 
* [Pinout Wiring Test Utility][68]. 
* All three in a [ZIP File][69] This code is an _original work_ by Paul Stoffregen, written in December 1999. This code has been placed in the **public domain**. You may use it without any restrictions. You may include it in your own projects, even commercial (for profit) products.  | 
* * *

Paul's 8051 Code Library, Paul Stoffregen   
http://www.pjrc.com/tech/8051/ide/index.html   
Last updated: February 24, 2005   
Status: This page is complete, code updated for rev 5 board, January 2005   
Suggestions, comments, criticisms: <[paul@pjrc.com>][70]

[1]: https://www.pjrc.com/img/1x1.gif
[2]: https://www.pjrc.com/img/logo.gif
[3]: https://www.pjrc.com/cgi-bin/store/step1
[4]: https://www.pjrc.com/img/a.gif
[5]: https://www.pjrc.com/cgi-bin/store/step2
[6]: https://www.pjrc.com/cgi-bin/store/shipcost
[7]: https://www.pjrc.com/cgi-bin/archive/summary
[8]: https://www.pjrc.com/
[9]: https://www.pjrc.com/store/
[10]: https://www.pjrc.com/teensy/
[11]: https://www.pjrc.com/blog/
[12]: https://forum.pjrc.com/
[13]: https://www.pjrc.com/tech/8051/
[14]: https://www.pjrc.com/img/b.gif
[15]: https://www.pjrc.com/tech/8051/serial_io.html
[16]: https://www.pjrc.com/tech/8051/ide/index.html
[17]: https://www.pjrc.com/store/dev_pcb_assem.html
[18]: https://www.pjrc.com/store/dev_display_128x64.html
[19]: https://www.pjrc.com/store/dev_display_16x2.html
[20]: https://www.pjrc.com/store/cable_serial.html
[21]: https://www.pjrc.com/store/pwr_9vdc.html
[22]: https://www.pjrc.com/store/index.html
[23]: https://www.pjrc.com/tech/8051/index.html
[24]: https://www.pjrc.com/img/c.gif
[25]: https://www.pjrc.com/tech/8051/tools/index.html
[26]: https://www.pjrc.com/tech/8051/paulmon2.html
[27]: https://www.pjrc.com/tech/8051/board5/index.html
[28]: https://www.pjrc.com/tech/8051/autobaud.html
[29]: https://www.pjrc.com/tech/8051/uartintr.html
[30]: https://www.pjrc.com/tech/8051/lexer-fixed-string.html
[31]: https://www.pjrc.com/tech/8051/rand.html
[32]: https://www.pjrc.com/tech/8051/serial-eeprom.html
[33]: https://www.pjrc.com/tech/8051/amd-flash-rom.html
[34]: https://www.pjrc.com/tech/8051/xilinx-program.html
[35]: https://www.pjrc.com/tech/8051/ide/fat32.html
[36]: https://www.pjrc.com/tech/8051/ide/wesley.html
[37]: https://www.pjrc.com/tech/8051/contrib/tb51/index.html
[38]: https://www.pjrc.com/tech/8051/aicp-schematic.html
[39]: https://www.pjrc.com/tech/8051/free.html
[40]: https://www.pjrc.com#overview
[41]: https://www.pjrc.com#limits
[42]: https://www.pjrc.com#credit
[43]: https://www.pjrc.com#schematic
[44]: https://www.pjrc.com#lba
[45]: https://www.pjrc.com#routines
[46]: https://www.pjrc.com#setting
[47]: https://www.pjrc.com#usage
[48]: https://www.pjrc.com#troubleshooting
[49]: https://www.pjrc.com#download
[50]: https://www.pjrc.com/tech/8051/index.html#boards
[51]: https://www.pjrc.com/ide_board.jpg
[52]: https://www.pjrc.com/tech/mp3/
[53]: https://www.pjrc.com/tech/mp3/firmware.html
[54]: https://www.pjrc.com/wesley.html
[55]: https://www.pjrc.com/ide8255.zip
[56]: http://www.repairfaq.org/filipg/LINK/F_IDE-tech.html
[57]: http://thef-nym.sci.kun.nl/~pieterh/storage.html
[58]: http://www.mp3projects.com/docs.html
[59]: http://www.angelfire.com/de2/zel/
[60]: http://logicio.com/cgroen/embedded.htm
[61]: https://www.pjrc.com/header.jpg
[62]: https://www.pjrc.com/board2/schematic.html
[63]: https://www.pjrc.com/ide-sch.gif
[64]: https://www.pjrc.com/bottom.jpg
[65]: http://www.microsoft.com/HWDEV/storage/default.htm#Specs
[66]: https://www.pjrc.com/ide.asm
[67]: https://www.pjrc.com/ide_old.asm
[68]: https://www.pjrc.com/ide_pins_test.asm
[69]: https://www.pjrc.com/ide.zip
[70]: mailto:paul%40pjrc.com

