-
Notifications
You must be signed in to change notification settings - Fork 4
/
8255-ide.txt
2323 lines (2163 loc) · 113 KB
/
8255-ide.txt
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
> Please send me the IDE interface document. I would be happy to put the
> document on my web page so you can refer everyone to there instead of
> having numerous requests for the document.
>
> Thanks.
>
> Keith Welker
> Ohio University student
> Electrical Engineering Department
> http://www.ent.ohiou.edu/~welker/index.cgi
I think putting it on your web page would be a good idea. Ever
since I posted the announcing message I've been bombed with
requests. I never expected this much response.
Well here comes the document:
How to connect an IDE disk to a microcontroller using an 8255
=============================================================
Introduction
============
Some time ago I have dropped that I had connected an IDE harddisk
to one of my microcontrollers. This has provoced a response that
I had not forseen. Since that day I have received some one to two
e-mails a day requesting more details about what I had done. At
first I have mailed a more or less cryptic decription of my
interface to some of the requesters. That only resulted in more
e-mail asking for more details. As it seems some people out there
are really interested in how my contraption is made. In this
description I will attempt to satify the information-hunger of
all you out there who's appetite I seem to have awakened.
This interface first came to my mind when I re-read some old, old
computer magazines. In one of them, the German magazine called
C't there was a short description of how and IDE interface is put
together. This is in the November issue of 1990. The article
describes an IDE interface for both the PC-XT(!) and the PC-AT.
The circuit diagrams of the article indcate that the hardware of
an IDE interface is in fact very simple. It is essentially a data
bus extension from the PC-AT bus to an IDE device. For a PC the
hardware comes down to some bus buffers and some decoding. When a
disk is connected as an IDE device the PC-AT still 'sees' the
old-type control registers of the ancient MFM disk controller. In
the article the entire interface is implemented using simple TTL
chips. The main problem in a PC seems to be how to keep the
harddisk interface and the floppy interface from colliding on
some register addresses. If the IDE interface is implemented
based on some controller system this is of course no problem.
From a controller point of view an IDE interface could be
described as a set of I/O ports. The IDE interface has a 8/16
bits I/O bus, two /CS lines, a /WR and /RD line, three address
bits and one interrupt. In this description I assume the most
traditional IDE interface. In later IDE interfaces a series of
nice so-called PIO modes where added. These PIO modes add things
like a ready line, DMA facilities and higher speed data
transfers. As you read on you will understand that I only use the
so-called PIO mode 0. This is the slowest communication modus on
an IDE bus. It is also the easiest one to implement. The data bus
on an IDE interface is used mostly for 8-bits transfers. Only the
real disk data reads and writes use the 16-bits bus in full
width. You COULD even implement an IDE interface with an 8-bits
only data bus. That would mean that you use only half the disk
capacity (the lower bytes of the 16-bits-wide bus) but that
should work.
When scanning the net I did find an implementation of an IDE
interface for 8-bit controllers. This interface was for a (hope I
have this correct..) COCO bus. It was implemented in TTL, just
like the magazine's interface. The main idea was that whenever a
(16-bits) word was read from the IDE bus the upper 8 bits where
stored in a latch. The controller could retrieve them from the
latch later. Writing to the IDE bus was implemented in the same
manner. The IDE bus read/write cycles where in fact simple bus
read and write cycles. At first I was about to copy this design.
When thinking about it I thought that this TTL design was too
complex for what I wanted to do. You need quite some TTL to
implement a 16-bits read/write I/O port in TTL on an 8-bits
controller.
Hardware description
====================
When implementing a 16-bits I/O port all you need is a
bidirectional I/O port and some control bits to generate the /RD,
/WR etc... That is when the 8255 came in view. An 8255 has 3
8-bits I/O ports. It can be switched from output to input and
back under software control. I used 2 of the 8-bits I/O ports for
the data path and use port to generate the IDE control signals.
The 74HC04 came into the design later. Once I had the controller
and the 8255 strapped together with the IDE connector and a disk
I found out that the 8255 has a nasty trait. Whenever you switch
the I/O modus of the chip it resets ALL its memory bits. That
includes ALL output signals too. For the data bus that is not so
much of a problem. The control signals get a real shake when this
happens. In particular: The /RESET line of the interface is
activated. That makes all control of a disk on this interface
impossible (the disk gets a reset at all kinds of odd
moments...). I have solved this by simply inverting all the
control signals from the 8255 to the IDE bus. When the modus of
the 8255 is switched all outputs of the chip go to '0'. That
means that all the (low-active) control signals are made inactive
by the inversion. That is -in fact- the state where I have them
already when I'm about to change the 8255's modus.
At this point I would like to present a nice circuit diagram to
show what the contraption I have made looks like. Unfortunately I
know of no easy way to do that. This beautiful net is a marvel
when it comes down to transporting text, graphics is another
matter. A GIF picture would do the work; I do not have any means
to produce one. Some schematics drawing package could give a good
picture; I have no schematics package and I am not sure what
package would be universal enough to be usable by everyone. So I
am restricted to a more or less cryptic ASCII description of the
hardware. Please, the cryptology is out of need, not out of my
liking. Well here it comes:
1) The IDE bus pin connections themselves:
---------------------------------------
The IDE connector itself is a 40-pins two-row connector:
1 39 odd-numbered pins
....................
....................
2 40 even-numbered pins
In an IDE bus this connector is used as follows:
pin no: name: function:
--------- ------- ---------
1 /RESET Al low signal level on this pin will reset
all connected devices
2,19,22 GND ground, interconnect them all and tie to
24,26,30 controller's ground signal
40
3,5,7,9,11 D7..D0 low data bus, 3=D7 .. 17=D0. This part of
13,15,17 the bus is used for the command and
parameter transfer. It is also used for
the low byte in 16-bits data transfers.
4,6,8,10 D8..D15 high data bus, 4=D8 .. 18=D15. This part
12,14,16,18 of the bus is used only for the 16-bits
data transfer.
20 - This pin is usually missing. It is used to
prevent mis-connecting the IDE cable.
21 and /IOREADY I do not use or connect to this pin. It is
27 there to slow down a controller when it is
going too fast for the bus. I do not have
that problem...
23 /WR Write strobe of the bus.
25 /RD Read strobe of the bus.
28 ALE Some relic from the XT time. I do not use
it, and I'm not the only one...
31 IRQ Interrupt output from the IDE devices. At
this moment I do not use it. This pin
could be connected to a controller to
generate interrupts when a command is
finished. I have an inverter ready for
this signal (I need a /IRQ for my
controller, an IRQ is of no use to me..)
32 IO16 Used in an AT interface to enable the
upper data bus drivers. I do not use this
signal. It is redundant anyway, the ATA-3
definition has scrapped it.
34 /PDIAG Master/slave interface on the IDE bus
itself. Leave it alone or suffer
master/slave communications problems. Not
used (or connected to ANYTHING) by me.
35 A0 Addresses of the IDE bus. With these
33 A1 you can select which register of the IDE
36 A2 devices you want to communicate.
37 /CS0 The two /CS signals of the IDE bus. Used
38 /CS1 in combination with the A0 .. A2 to select
the register on the IDE device to
communicate with.
39 /ACT A low level on this pin indicates that the
IDE device is busy. I have connected a LED
on this pin. The real busy signal for the
controller I get from the IDE status
register.
Input/Output status of these signals:
-------------------------------------
The signals:
A0, A1, A2, /CS0, /CS1, /WR, /RD and /RESET are always outputs
from the controller to the IDE bus.
The signals:
IRQ and /ACT are always outputs from the IDE bus to the
controller (IRQ can be tri-stated by the IDE device when two
devices are connected to the IDE bus.) /ACT can drive a LED (with
resistor of course).
The signals:
D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14,
D15 are bi-directional. They are output from the controller to
the IDE bus when writing, output from the IDE device to the
controller when reading information.
2) The 8255 <-> controller
-----------------------
The 8255 is connected to the controller by means of its 8-bit
data bus, the A0 and A1 lines and the /CS, /WR and /RD lines. I
can not give that much info about this. If in doubt: consult the
8255 data sheet. This part depends as much on the controller you
use as anything else. I have the 8255 connected to my controller
(HD63B03R1CP, a Hitachi 6803-derivate..) as an I/O port. Perhaps
some of you have seen my previous e-mails asking for the pinout
of the HD63B03R1CP (52-pins PLCC) chip, well I did find it (Some
department of my work had an old Hitachi databook, voila the
pinout was there). My address decoding puts the 8255 on address
0500H to 0503H in the controller's memory map. That may help if
you decide to try to make sense of my software listing. On this
point you are on your own as to the how to connect a 8255 to your
controller.
3) 8255 <-> IDE connector
----------------------
I have used the 8255's port A to generate the IDE bus control
signals. Some of these control signals pass through an inverter
before I connected them to the IDE connector itself. All of these
signals are always used as output from the 8255 to the IDE bus.
When a control signal is inverted the 8255 pin is connected to
one of the inputs of the 74HC04 and the (corresponding) output of
the 74HC04 is connected to the IDE bus connector.
The ports B and C are used as the 16-bits data bus. There are no
special things in this, it's just a simple interconnection of the
8255 I/O pins to the D0..D15 pins of the IDE connector.
I have connected this as follows:
---------------------------------
PA.7 --> inverter --> IDE bus /RESET
PA.6 --> inverter --> IDE bus /RD
PA.5 --> inverter --> IDE bus /WR
PA.4 --> inverter --> IDE bus /CS1
PA.3 --> inverter --> IDE bus /CS0
PA.2 --> IDE bus A2
PA.1 --> IDE bus A1
PA.0 --> IDE bus A0
PB.7 <--> IDE bus D7
PB.6 <--> IDE bus D6
PB.5 <--> IDE bus D5
PB.4 <--> IDE bus D4
PB.3 <--> IDE bus D3
PB.2 <--> IDE bus D2
PB.1 <--> IDE bus D1
PB.0 <--> IDE bus D0
PC.7 <--> IDE bus D15
PC.6 <--> IDE bus D14
PC.5 <--> IDE bus D13
PC.4 <--> IDE bus D12
PC.3 <--> IDE bus D11
PC.2 <--> IDE bus D10
PC.1 <--> IDE bus D9
PC.0 <--> IDE bus D8
I have put a 10 KOhm pull-down resistor from the IDE bus IRQ to
ground. The IDE IRQ signal is also connected to the input of the
(one-remaining) inverter. The output of the inverter is connected
to the controller's /IRQ input. As you can see, I do have the
hardware for interrupts here, I do not use it. I tried to use it,
but got unexplained errors (I probably did something wrong, I
have not yet found what)..
|\
IDE IRQ o-----+----+ >o--------o CPU's /IRQ
| |/
+++
| |
| | 10 KOhm
+++
|
|
-+- GND
///
The IDE /ACT signal is connected to a 330 Ohm resistor, the other
end of the resistor is connected to a LED, the other end of the
LED is connected to the +5 Volts. This gives a nice LED
indication of when I'm using the disk. This is -as far as I know-
the same hardware a PC uses to produce the disk busy LED you may
find on the front of a PC box.
330 Ohm
+-------+ LED
IDE /ACT o-----+ +------|<-----o +5 Volts
+-------+
So much about the hardware of the IDE interface. I hope that is
all clear now. If I have been less than clear, please ask. If I
have made mistakes, please complain (I said complain, NOT FLAME!!!).
IDE read/write and register description
=======================================
The IDE device appears to the IDE bus as a set of regsiters. The
register selection is done with the /CS0, CS1 and A0, A1, A2
lines. Reading/writing is done with the /RD and /WR signals. I
have used the 8255 port A signals to make read/write cycles on
the IDE bus. What I do is the following:
read cycle:
-----------
1) put the port B and C of the 8255 in input modus.
2) set an address and /CS0 and /CS1 signal on the port A of the
8255.
3) activate the /RD of the IDE bus by setting the equivalent bit
in the port A of the 8255.
4) read the data from port B (and C) of the 8255.
5) deactivate the /RD signal on the IDE bus by resetting the
equivalent bit of port A of the 8255.
write cycle:
-----------
1) put the port B and C of the 8255 in output modus.
2) set an address and /CS0 and /CS1 signal on the port A of the
8255.
3) set a data word (or byte) on port B (and C) of the 8255.
4) activate the /WR of the IDE bus by setting the equivalent bit
in the port A of the 8255.
5) deactivate the /WR signal on the IDE bus by resetting the
equivalent bit of port A of the 8255.
The only difference between 8 bits and 16 bits transfers is the
following:
- In an 8-bit transfer I use only the port B of the 8255 for data
transfer. When writing I put data only on the lower byte of the
IDE bus; the upper byte is ignored anyway by the IDE device.
When reading I read only port B of the 8255; I never even
bother to look at the upper byte.
- In an 16-bit transfer I read/write to both the upper and the
lower byte of the IDE bus; thus using both port B and port C.
The IDE device appears as the following registers:
--------------------------------------------------
/CS0=0, /CS1=1, A2=A1=A0=0: data I/O register (16-bits)
This is the data I/O register. This is in fact the only 16-bits
wide register of the entire IDE interface. It is used for all data
block transfers from and to the IDE device.
/CS0=0, /CS1=1, A2..A0=001B: This is the error information
register when read; the write precompensation register when
written. I have never bothered with the write precompensation at
all, I only read this register when an error is indicated in the
IDE status register (see below for the IDE status register).
/CS0=0, /CS1=1, A2..A0=010B: Sector counter register. This
register could be used to make multi-sector transfers. You'd have
to write the number of sectors to transfer in this register. I
use one-sector only transfers; So I'll only write 01H into this
register. I do use this register to pass the parameter the
timeout for idle modus command via this register.
/CS0=0, /CS1=1, A2..A0=011B: Start sector register. This register
holds the start sector of the current track to start reading/
writing to. For each transfer I write the start sector in this
register. For some fancy reason the sector count starts at 1 and
runs up to 256, so writing 00H results in sector number 256. Why
that is done is a mystery to me, all other counting in the IDE
interface starts at 0.....
/CS0=0, /CS1=1, A2..A0=100B: Low byte of the cylinder number.
This register holds low byte of the cylinder number for a disk
transfer.
/CS0=0, /CS1=1, A2..A0=101B: High two bits of the cylinder
number. The traditional IDE interface allows only cylinder
numbers in the range 0..1023. This register gets the two upper
bits of this number. I write the cylinder number's upper two bits
into this register before each transfer.
/CS0=0, /CS1=1, A2..A0=110B: Head and device select register. The
bits 3..0 of this register hold the head number (0..15) for a
transfer. The bit 4 is to be written 0 for access to the IDE
master device, 1 for access to the IDE slave device. The bits
7..5 are fixed at 101B in the traditional interface.
/CS0=0, /CS1=1, A2..A0=111B: command/status register. When
written the IDE device regards the data you write to this
register as a command. When read you get the status of the IDE
device. Reading his register also clears any interrupts from the
IDE device to the controller.
/CS0=1, /CS1=0, A2..A0=110B: 2nd status register/interrupt and
reset register. When read this register gives you the same status
byte as the primary (/CS0=0, /CS1=1, A2..A0=111B) status
register. The only difference is that reading this register does
not clear the interrupt from the IDE device when read. When
written you can enable/disable the interrupts the IDE device
generates; Also you can give a software reset to the IDE device.
/CS0=1, /CS1=0, A2..A0=111B: active status of the IDE device. In
this register (read-only) you can find out if the IDE master or
slave is currently active and find the currently selected head
number. In a PC environment you can also find out if the floppy
is currently in the drive. I have not used this register yet.
Some of these registers have bitwise meanings. I'll elaborate on
that here:
head and device register:
-------------------------
A write register that sets the master/slave selection and the
head number.
bits 3..0: head number [0..15]
bit 4 : master/slave select: 0=master,1=slave
bits 7..5: fixed at 101B. This is in fact the bytes/sector
coding. In old (MFM) controllers you could specify if
you wanted 128,256,512 or 1024 bytes/sector. In the
IDE world only 512 bytes/sector is supported. This bit
pattern is a relic from the MFM controllers age. The
bit 6 of this pattern could in fact be used to access
a disk in LBA modus.
Status register:
----------------
Both the primary and secondary status register use the same bit
coding. The register is a read register.
bit 0 : error bit. If this bit is set then an error has
occurred while executing the latest command. The error
status itself is to be found in the error register.
bit 1 : index pulse. Each revolution of the disk this bit is
pulsed to '1' once. I have never looked at this bit, I
do not even know if that really happens.
bit 2 : ECC bit. if this bit is set then an ECC correction on
the data was executed. I ignore this bit.
bit 3 : DRQ bit. If this bit is set then the disk either wants
data (disk write) or has data for you (disk read).
bit 4 : SKC bit. Indicates that a seek has been executed with
success. I ignore this bit.
bit 5 : WFT bit. indicates a write error has happened. I do
not know what to do with this bit here and now. I've
never seen it go active.
bit 6 : RDY bit. indicates that the disk has finished its
power-up. Wait for this bit to be active before doing
anything (execpt reset) with the disk. I once ignored
this bit and was rewarded with a completely unusable
disk.
bit 7 : BSY bit. This bit is set when the disk is doing
something for you. You have to wait for this bit to
clear before you can start giving orders to the disk.
interrupt and reset register:
-----------------------------
This register has only two bits that do something (that I know
of). It is a write register.
bit 1 : IRQ enable. If this bit is '0' the disk will give and
IRQ when it has finished executing a command. When it
is '1' the disk will not generate interrupts.
bit 2 : RESET bit. If you pulse this bit to '1' the disk will
execute a software reset. The bit is normally '0'. I
do not use it because I have full software control of
the hardware /RESET line.
Active status register:
-----------------------
This is a read register. I have -up till now- ignored this
register. I have only one IDE device (a disk) on my contraption.
bit 0 : master active. If this bit is set then the master IDE
device is active.
bit 1 : slave active. If this bit is set then the slave IDE
device is active.
bits 5..2: complement of the currently active disk head.
bit 6 : write bit. This bit is set when the device is writing.
bit 7 : in a PC environment this bit indicates if a floppy is
present in the floppy drive. Here it has no meaning.
error register:
---------------
The error register indicates what went wrong when a command
execution results in an error. The fact that an error has
occurred is indicated in the status register, the explanation is
given in the error register. This is a read register.
bit 0 : AMNF bit. Indicates that an address mark was not
found. What this means I not sure of. I have never
seen this happen.
bit 1 : TK0NF bit. When this bit is set the drive was not able
to find track 0 of the device. I think you will have
to throw away the disk if this happens.
bit 2 : ABRT bit. This bit is set when you have given an
indecent command to the disk. Mostly wrong parameters
(wrong head number etc..) cause the disk to respond
with error flag in the status bit set and the ABRT bit
set. I have gotten this error a lot when I tried to
run the disk with interrupts. Something MUST have been
wrong with my interface program. I have not (yet)
found what.
bit 3 : MCR bit. indicated that a media change was requested.
What that means I do not know. I've ignored this bit
till now.
bit 4 : IDNF bit. Means that a sector ID was not found. I have
never seen this happen, I guess it means that you've
requested a sector that is not there.
bit 5 : MC bit. Indicates that the media has been changed. I
ignore this bit.
bit 6 : UNC bit. Indicates that an uncorrectable data error
happened. Some read or write errors could provoce
this. I have never seen it happen.
bit 7 : reserved.
Note: I have these registers descriptions from two sources:
1) The C't magazine I mentioned before. It's in German, not very
complete (the error register description is missing) and very
old. It does have a hardware description of and IDE interface
however....
2) The document X3T10/2008D: Information Technology-
AT Attachment-3 Interface (ATA-3), Working draft.
This latter document gives an exhaustive overview of the IDE
interface. It states more details of the IDE interface than I
can ever hope to include in this short description. It does
however have one disadvantage: it's BIG. I found the document
on the net (on the Western Digital homepage) in the form of an
.exe file. When you run this file on a PC you are rewarded
with a bigger-than-1 Mbytes .DOC file. That is a Word
document. When you print (Wondows-95 has a Word viewer/printer
application) it you get a nearly-200-pages paper. If you want
to get into the IDE interface seriously I recommend you print
this thing.
I hope the description I have given here will allow those that do
not have a laser printer and a fast internet link available to
get to grips with the IDE bus.
Intermezzo: Disk size limitations on the IDE bus and LBA modus
-----------
In the PC world there has been (and still is) a lot of discussion
about 'limits' in the disk interface.
At first (MSDOS versions till 3.3) the disk interface was not
able to access more than 32MB on one volume. That was a
limitation of the MSDOS file system rather than of the disk
interface. The same DOS version that was unable to access bigger
partitions than 32MB *WAS* able to access 650MB CDROMs. The limit
came from the fact that each disk sector (512 bytes) was
registered in the FAT in a 16-bits word. The total partition size
was limited by the fact that only 65536 sectors could be
addressed. The partition size was thus limited to 65536 x 512
bytes = 32 MBytes.
Later -as the disks became larger- the disk interface itself ran
into its limits. The interface I describe here has room for 16
heads, 256 sectors per track and only 1024 cylinders. With the
standard sector size of 512 bytes that leaves you a maximum disk
size of 16 x 256 x 1024 x 512 = 2048 MBytes. That is a real
limitation of the IDE interface as I decribe it here. It can not
access more than some 2 GBytes of disk space.
This was overcome by introducing the so-called LBA modus. In LBA
modus the sectors are simply numbered from 0 to -big-. The lowest
byte of the LBA sector number is written into the sector number
register, the middle 16 bits of the LBA sector number are written
in the cylinder number registers (low and high, all 16 bits are
used). The highest 4 bits of the LBA sector number are written in
the head and device register. That gives you 28 bits of LBA
sector number. The sector size was again fixed at 512bytes, so in
LBA modus you have access to: 2^28 x 512 = 1.37 E 11 (some 137.4
gigabytes) of disk space. This LBA modus has been made mandatory
for all new disks (in the ATA-3 spec.) That should keep the disk
makers busy for some while to come... If you want to connect a
disk larger than 2 GBytes to this IDE interface you too will have
to use the LBA modus. How to do that: the bit 6 of the head and
device register is set to indicate that LBA modus is used (the
fixed pattern of 101B in the bits 7..5 of the head and device
register is to be changed into 111B). All other manipulation of
the IDE interface is the same for Sector/Head/Cylinder modus and
LBA modus.
All other limits in te MSDOS/Windows-whatever disk interface must
be due to the BIOS implementation or the file system used. I can
find no reason in the IDE definition for 512 MB limits or 8 GB
limits at all.
End of intermezzo
-----------------
IDE registers usage
===================
Ok, now you know what registers the IDE system uses. Next
question: How to use them? I do not pretend I have tried every
possibility with these registers. As I stated before I have
restricted myself to reading/writing data blocks to/from the
disk. What to do for that is in fact fairly simple:
1) Before doing anything with a device you have to wait till it
indicates that it is ready (RDY bit in the status register)
2) Next you load the parameters of a command into the appropriate
registers. For read/write commands that comes down to writing
the cylinder/head/sector numbers into the registers.
3) You issue a read or write command.
4) You wait till the device signals that it is ready for data
transfer (DRQ in the status register).
5) Feed the device data (for write) or get the data from the
device (for read). In case of a write you could wait for the
operation to complete and read the status register to find out
what has become of your data.
6) Finish!! That's all folks! The IDE interface is a surprisingly
simple thing to get to work. If only I had an IDE disk and this
kind of information when I was still programming my
MSX-computer I'd have had a harddisk connected to it in no
time.
IDE commands
============
What has been missing in this description till now is the command
set. I do not think I can describe the complete command set here.
The ATA-3 document is a better source for that than I can give
here (All I would be doing is re-entering the ATA-3 document; I
have neither the time nor any liking for that). The most usable
commands I do intend to describe. Mind: When giving a command you
first have to wait for device ready, next put the command
parameters in the registers and only then can you give a command
(by writing a command byte to the command register). The disk
will start executing the command right after you've written the
command into the command register.
IDE command: Description:
------------ ------------
1XH recalibrate the disk. NB: 1XH means that the lower
nibble of the command byte is a don't care. All
commands 10H..1FH will result in a recalibrate
disk command being executed. This command has no
parameters. You simply write the command code to
the command register and wait for ready status to
become active again.
20H Read sector with retry. NB: 21H = read sector
without retry. For this command you have to load
the complete circus of cylinder/head/sector
first. When the command completes (DRQ goes
active) you can read 256 words (16-bits) from the
disk's data register.
30H Write sector (with retry; 31H = without retry).
Here too you have to load cylinder/head/sector.
Then wait for DRQ to become active. Feed the disk
256 words of data in the data register. Next the
disk starts writing. When BSY goes not active you
can read the status from the status register.
7XH Seek. This normally does nothing on modern IDE
drives. Modern drives do not position the head if
you do not command a read or write.
ECH Identify drive. This command prepares a buffer
(256 words) with information about the drive. If
you want the details either look closely at the
interface program I will add at the end of this
description or get the ATA-3 document. To use it:
simply give the command, wait for DRQ and read
the 256 words from the drive. I have found that
the modern drives I used give nice information
about number of heads,sectors,cylinders etc...
One of the disks I tried (a Miniscribe 8051A)
gave wrong answers in this buffer. The disk is
actually a 4 heads/28 sectors disk. It should be
used in a translated modus with 5 heads/17
sectors. In the ident drive response it reported
as 4 heads/28 sectors and it will NOT work in
that modus. Two other disks (a Quantum 127 MB
disk and a Western Digital 212 MB disk) report
nicely. If not for the Miniscribe I would use the
parameters reported to auto-config the interface
to match the disk configuration.
E0H Spins down the drive at once. No parameters. My
Miniscribe 8051A does not respond to this
command, the other disks do execute this command.
E1H Spins up the drive again. Same remarks as E0H
command.
E2H and E3H Auto-power-down the disk. Write in the sector
count register the time (5 seconds units) of
non-activity after which the disk will spin-down.
Write the command to the command register and the
disk is set in an auto-power-save modus. The disk
will automatically spin-up again when you issue
read/write commands. E2H will spin-down, E3H will
keep the disk spinning after the command has been
given. Example: write 10H in the sector count
register, give command E2H and the disk will
spin-down after 80 seconds of non-activity. BTW:
You can use this command easily on a PC disk too.
The harddisk of the computer I am working on now
gets this exact command at boot. That saves a lot
of noise when I'm typeing long stories like this
one.
F2H and F3H The same as E2H and E3H, only the unit in the
sector count register is interpreted as 0.1 sec
units. I have not tried this command. Ithink it
will work (the E0H/E1H/E2H/E3H commands work, why
should this one not work?)
Two-devices considerations
==========================
The IDE bus is intended for two devices. A master and a slave
device. I have not tried anything myself, but the descriptions
indicate that it is in fact very simple to connect two devices to
the IDE bus. All you have to do is:
1) Configure the master/slave jumpers of the devices.
2) Select a device before you start giving commands to the
devices.
The head and device register has the bit you need to switch from
one device to another. You have to write the bit to either 0 for
master or 1 for slave and start controlling the other device.
Mind: BOTH devices will get their registers WRITTEN. Any data or
register READ will come from the selected device. ONLY the
selected device will execute commands.
Conclusions and ravings
=======================
ravings:
--------
This description should be about what you need to connect an IDE
disk to any controller. The only thing I have left out are my
unsuccessfull experiments with the interrupt. What happened there
is that I enabled the interrupt, made an interrupt handler that
simply read the status register (to get the interrupt to
disappear) and re-scheduled the disk interface task. I was
rewarded with occasional errors. Some of the read requests got an
ABRT error. I do not yet know what I did wrong. I can not have
been far off the mark, because most of the commands where
executed without comment from the disk. I do intend to try the
interrupt modus again later. I theory the interrupt modus should
give me a slightly bigger data rate. I have found data rates in
the order of 32 KBytes per seccond when I was using interrupts.
About interrupts: When you want to use the interrupt mechanism
all you have to do is enable the interrupt modus of the interface
by clearing the interrupt disable bit in the reset and interrupt
register. The disk will generate an interrupts as soon as it
has completed a command. That means that it will generate an
interrupt when it has read a sector from disk (as soon as DRQ
gets active) or when it has finished writing a sector to disk. I
am not sure about the other commands, but the description says
that the disk will generate an interrupt upon the completion of
each command.
About the data rate. This IDE interface will never win any award
for its speed. It is in one word slow. I get data transfer rates
in the order of 25 KBytes per seccond. I spend most of the time
reading/writing data words from/to the disk on a word-by-word
basis under software control. On the other hand, my controller
has a total (RAM) memory of 24 KBytes. With the current interface
I can dump the complete memory to disk in less than one seccond.
That in itself makes me think that for this application the low
speed is not so much of an issue.
About the future. I think I will give interrupt modus another
try. Not because it gives me a fantastic data rate, I just can't
stand it that it does not want to work good.
I am thinking about a proper file system to put on the disk. That
will enable me to access the disk in a more normal way that the
current 'sea of sectors' approach I use now. A FAT filesystem
looks like an absolute horror when combined with a controller, so
I'll have to either find something that looks good to me or strap
something together myself.
I think I will give the ATAPI command set a try. I have just
found and printed the 'SFF committee specification of ATA Packet
Interface for CDROMs' (SFF-8020i) document. That document gives a
description of how to control an ATAPI CDROM via the IDE bus. On
the other hand: I would really not know what to begin with a
CDROM connected to a microcontroller. But what the heck, I have
no really good idea what to do with a microcontroller with a 40MB
harddisk connected..... I have seen occasional questions in this
mailing list about how to control a CDROM via its backside
connector: I think this IDE interface with an ATAPI piggy-back
software could just do the work.
Till now I've been concentrating on only one side of the
interface. The IDE interface is in fact no more than a
ready-decoded, buffered interface of a (mostly-PC) hardware
system. I could in fact connect god-knows-what at the other end.
I have an interrupt, DMA and I/O available, what else could you
ask for? A disk or CDROM is only one of the less inspired devices
you can connect to an IDE interface. Given the fact that modern
PC-motherboards have two IDE interfaces aboard I can think of
some nice things I'd like to connect to them. How about some 8
parallel input/output ports, how about a data aquisition system?
Lately I have been able to get a C-mos version of the 8255. My
controller system is quite low-power (10 mA for the entire
thing). I did not feel good about the IDE extension with a 8255
that used some 80 mA all by itself. The controller system with
the D71055C (a C-mos NEC version of the 8255) has gone down to
its normal -about 10 mA- power usage. the change from N-mos 8255
to C-mos D71055C has had no other noticable effects than a lower
power usage.
Even when I have no disk connected to this contraption it
delivers me three 8-bits I/O ports. I am thinking about what
other things I could connect to that.
conclusions:
------------
As you can see it is far from difficult to connect an IDE disk to
some computer. My implementation with a 8255 and an inverter chip
may not be the fastest thing on earth, it works, it's simple and
may be usable for many applications where a controller with a
large backup store could save the day.
I'll wrap this up with a case-study: The software I use on my
63B03 controller to control the IDE bus. I hope it can clarify
any points I have not covered in this description. I know this
software to work, I hope it can give someone inspiration to do
something similar on some controller system somewhere.
If I have been less than clear, or wrong, or you have some
questions left, remarks to make, improvements to suggest, please
drop me a line:
paper mail:
Peter Faasse
Hakfort 337
1102 LA Amsterdam
Netherlands
e-mail:
Appendix:
=========
The software I use to control a single IDE harddisk using a 63B03
controller system and a 8255/74HC04 IDE interface.
Notes:
------
The interface program has been made on a 63B03 controller in
assembly code. The 63B03 code is nearly 6800 code. If in doubt,
consult some source of 6800 or 6803 or 63B03 instructions.
The source of the interface program is of course the most
complete description of how to program this interface, but
certainly not the most un-cryptic description. I try to program
without any 'dirty tricks' but who knows....
This interface program makes sporadic use of the underlying 63B03
real-time scheduler. If you see a 'jsr Sys' somewhere that is
where I called the scheduler to do something for me. As far as I
can see I only use Sys to produce a 10-ms delay. I have left the
code of the scheduler itself out. Not beacuse it is anything but
public domain, but beacuse it is another 150 KBytes of source
file. This description is long enough as it stands here. The
scheduler is not really needed, so I left it out. If you are
interested in the scheduler as such, drop me a line (the address
is a little up in the text).
The IDE interface software as such I hereby donate to the public
domain. Use it as pleases you. Change it when you think it is
wrong, suffer the consequences if you make mistakes. I do not
take responsibility if you blow up harddisks, interface hardware
or if anything goes wrong when you use it. I have found it to
work on my system and, so sorry, that is all the guarantee I can
give you about it.
>>>>>>>>>>>>>>>>>>>>>>>> 63B03 assembly listing <<<<<<<<<<<<<<<<<<<
0000 |Begin----------------------------------------------------------
0000 |
0000 | Disk interface task for the 63B03 system
0000 |
0000 | Update history:
0000 | ---------------
0000 | 02-02-1998 : Started with the thing. The hardware has been
0000 | finished today. All seems to work. Now I need
0000 | software to get some life into it.
0000 |
0000 | 05-02-1998 : Hit a bloody trick of the 8255: When you change
0000 | the modus byte ALL outputs are set to 0. I now
0000 | know why nobody wants to use this bugger. The
0000 | solution for this shit is easy: I plan to put an
0000 | inverter in all the control lines. The following
0000 | lines will be inverted:
0000 | /CS0, /CS1, /IORD, /IOW, /RES, IRQ (the latter
0000 | for the 63B03, it has a /IRQ input)..
0000 | This is the software change needed to make things
0000 | work again...
0000 |
0000 | 06-02-1998 : Hardware change done, disk reset works
0000 | Started testing the disk interface functions.
0000 | The recalibrate command works too, the stop
0000 | disk/start disk functions seem to be not
0000 | present in this 40 MB disk. I also made a LBA
0000 | routine, I can now access the disk as a set of
0000 | sequential blocks, without counting heads etc..
0000 | It seems the PC hardware starts counting sectors
0000 | starting at 1 (WHY???), all other numbers start
0000 | at 0...
0000 |
0000 | My disk (about 40 MB) tells me it has
0000 | 980 cyls, 5 heads, 17 secs/track. In fact it does
0000 | tell me different numbers, only the label
0000 | indicates that it has been translated...
0000 |
0000 | At this moment I only support disk block read
0000 | and disk block write. I want to make some file-
0000 | system too. Besides, this thing works code-bound.
0000 | I want to start using interrupts too...
0000 |
0000 | 08-02-1998 : /IRQ hardware made ok. The disk can now generate
0000 | interrupts. These will come into the system via
0000 | the CPU's /IRQ signal. I even crashed the system
0000 | by giving /IRQ's with no handler in place...
0000 | Start making the disk software /IRQ-driven.
0000 |
0000 | 10-02-1998 : Changed the interrupt generation/detection
0000 | software Found one nasty bug in the interrupt
0000 | usage as I did it: I first gave a disk reset on
0000 | the IDE bus, then started giving commends right
0000 | away. On this ONE occasion I do NOT have the
0000 | disk's interrupt facility available, the disk is
0000 | still executing its internal reset. I have to
0000 | wait for ready there, THEN start issuing
0000 | commands... Also set the bus control signals to
0000 | output BEFORE I start using the bus at all... Now
0000 | the interrupt mechanism works like the beauty it
0000 | is...
0000 |
0000 | 11-02-1998 : Cleaned up the data transfer code. The disk I/O
0000 | was very slow due to very systematic code.
0000 | ReadWord/WriteWord code substituted in the
0000 | ReadBlock/WriteBlock code. Routines ReadWord/
0000 | WriteWord removed from the code. There was an
0000 | error in the writeword routine, I've removed it.
0000 |
0000 | 15-02-1998 : I have given up about the interrupt-driven disk