Hallo allemaal, This document describes my interface and is a concept for my homepage at the same time. Have fun with it. <xxx> is meant to be replaced by a HREF- tag in the future. I also found out that the GIF I have sent some of you was even older version than I thought. The except the invertor I told you of, some of the connections from the 573s towards the 138 are wrong. I hope that the following info helps you to "make" the corrct connections. --------------------------------------------------------------------------- IDE-interface for your Commodore. IDE-interface for the C64/128. Also general description how to adept it to other types. At this moment you can get small IDE-harddisks for peanuts. So I got interested in connecting one to my C64 in one or another way. The result is an interface of just eight common available cheap ICs. There is no specific knowledge of the IDE-bus needed to understand how it works. For those people who are interested in more ins and out you can read <this> document. The IDE-bus is based on the the old MFM-, RLL- and ESDI-harddisks. The idea raised to integrate the controler in the PC with the onboard controler of the harddisk and to attach the result to the harddisk. The only signals needed for the resulting board are the same signals after decoding the complete ISA-bus. These signals together make the IDE-bus. The signals we need for our interface are: - 16 databits, D0..D15 - 3 addresslines, A0..A2 - 2 Registerblock-selectlines, CS0 and CS1 - 2 Read/write lines, IOW and IOR Then there is one line I use but is not needed for the funtioning of the interface: DASP. The function of this line is to blink a LED when the HD is executing a command. There are more lines on the IDE-bus but we don't need them. Most of the time the reason is that the C64 is too slow to have use for them. For example: there is an Interupt-line that becomes active everytime the execution of a command has been finished. This may be very usefull with a Pentium 300 MHz but I already found out that the handling of interupt costs much more time then just waiting for the BUSY-flag to clear. The IDE-HD has two blocks of eight registers each: the "Command Block Registers" and the "Control Block Registers". The first block is choosen by negating CS0, the second by negating CS1. Each register itself is choosen by applying the right value to the addresslines A0..A2. Reading from or writing to a register is done by negating IOR or IOW. The IDE bus is, as said before, 16 bits wide but the registers are 8 bits wide. My first design was based on a design used for the Tandy TRS80-Colour computer. The first problem that I encountered was that the bytes that the C64 read were corrupted. This problem was solved by delaying the positive flank of the IOR-signal and OE-signal of the 74LS373 storing the high-byte. The second problem I encountered was that I was missing bytes when reading a complete sector. The nasty thing was that the number of missing bytes varied as well as the place where they disappeared. After a day of "try and error" the thought occured to me that it could be that the setup time of the addresslines towards the interface could be to short. As you all (should) know, the addresslines of the C64/128 are not valid until after the rising edge of CLK2. Before this moment they reflect an address the VIC (= videochip) is using for its own puposes. The complete decoding of an address is just a matter of nano seconds and some devices need much more for their so called setup time. So I changed the design by generating the needed address- and CSx-lines by means of an 74ALS573. Bingo :-) <The design> The IDE bus is 16 bits wide. The bus of the C64 is only 8 bits wide. So we have to store the extra 8 bits before a write-action and during a read- action in some way. This is where U@ and U3 , both 74ALS573s, come in view. U3 is used to store the high byte for writing, U2 is used to store read high byte. U1, the third 74ALS573, is used to generate the address- and CSx-lines for the IDE bus. Only four bits are used. D0..D2 are used to generate the address lines, D4 for both the CSx-lines. The last is realised by connecting CS0 directly to Q4 and CS1 thru an 74LS14. The first idea was connecting both CS-lines to their own Q-output. But the outputs of a 74ALS573 are undefined after a power-up and my experience is that they are (L) most of the time. And the IDE-docs say it is illegal to negate both CS- lines. I don't know if this illegal situation can damage the hardware but "to prepare is better then to repair". U5, a 74LS245, is used as buffer between the interface and the C64/128. The decoding C64-bussignals can be split up in two parts. The first part takes care of decoding the needed signal to enable the 245. The second part takes care of addressing the 573s and the IOR/IOW-lines of the IDE-bus. The first part is made out of a 74LS260, dual 5-input NOR-gates and two invertors, U7B and U7C. The whole construction can be seen as a 7-input OR- gate decoding the addresslines A2..A7 and IO2. The output is used to enable the 245 and U6, a 74LS138. This 138 is the second part of the decoding and takes care of addressing the 573s and the IOW/IOR-lines. CLK2 is used to enable the G-input of the 138. This is done to minimize the effects of the delaytimes introduced by all the gates used for the decoding. The 138 decodes the last 2 addreslines and separates the write- and read-actions. - Writing to $DE00 enables the output of U3, putting the previous stored high byte on D8..D15 of the IDE-bus. This action also negates IOW telling the HD to read the contents of its databus. The low byte is put on the bus by the C64/128 itself thru U5, the 245. - Reading $DE00 negates IOR, telling the HD to put its data on the bus. The low byte of this data is read by the C64/128 thru U5, the 245. The high byte is clocked into U2 thru an invertor, U4C. To give U2 and the C64/128 some extra time to read the contents of the IDE- databus, the IOR signal is delayed by using 2 74F14-invertors and a RC-network. - Writing to $DE01 latches the wanted values for the address- and CS- lines of the IDE-bus into U1 - Writing to $DE02 latches the byte on the databus of the C64/128 into U3 (thru an invertor, U4D). - Reading $DE02 puts the contents of U2 on the databus of the C64/128. Because I encountered some difficulties reading the contents, I delayed this signal as well using U4E, U4F and a RC-network. Writing to $DE03 does nothing. Reading $DE02 or $DE03 returns an unpredictable value. Unexplained items: The resistors R3..R6 are there because the <IDE-specifications> say to do so. R2 and D1 enable you to see if the HD is performing a command or a datatransfer. Software. No SW has been develloped yet which enables you to work with the drive except some SW to test the interface. For the moment you have to do with the following "how to do it and why". Changing the design from "direct addressing" to "latch addressing" complicated the way to enable a datatransfer. Instead of one read- or writecommand, we need two extra writecommands. But I can assure you right now that this has almost no impact on the time needed to read data from or write data to the HD itself. The IDE-HD has two sets of registers with each the following registers: +-----+-----+-----+---+---+---+----------------+---------------+ | reg | CS0 | CS1 |A2 |A1 |A0 | Read (-IOR) | Write (-IOW) | +-----+-----+-----+---+---+---+----------------+---------------+ | | 0 | 0 | X | X | X | ILLEGAL | ILLEGAL | +-----+-----+-----+---+---+---+----------------+---------------+----------+ | 0 | 0 | 1 | 0 | 0 | 0 | Data Port | Data Port | <--+ | | 1 | 0 | 1 | 0 | 0 | 1 | Error Register | Precomp | | | | 2 | 0 | 1 | 0 | 1 | 0 | Sector Count | Sector Count | Command | | 3 | 0 | 1 | 0 | 1 | 1 | Sector Number | Sector Number | Block | | 4 | 0 | 1 | 1 | 0 | 0 | Cylinder Low | Cylinder Low | Registers| | 5 | 0 | 1 | 1 | 0 | 1 | Cylinder High | Cylinder High | | | | 6 | 0 | 1 | 1 | 1 | 0 | Drive / Head | Drive / Head | | | | 7 | 0 | 1 | 1 | 1 | 1 | Status | Command | <--+ | +-----+-----+-----+---+---+---+----------------+---------------+----------+ | | 1 | 1 | X | X | X | High Impedance | Not Used | | | 0 | 1 | 0 | 0 | 0 | 0 | High Impedance | Not Used | <--+ | | ... | 1 | 0 | ... | High Impedance | Not Used | Control | | 5 | 1 | 0 | 1 | 0 | 1 | High Impedance | Not Used | Block | | 6 | 1 | 0 | 1 | 1 | 0 | Altern Status | Device Control| Registers| | 7 | 1 | 0 | 1 | 1 | 1 | Drive Address | Not Used | <--+ | +-----+-----+-----+---+---+---+----------------+---------------+----------+ 0 r/w data register 1 r error register diagnostic mode errors: bit 7-3 reserved bit 2-1 = 001 no error detected = 010 formatter device error = 011 sector buffer error = 100 ECC circuitry error = 101 controlling microprocessor error operation mode: bit 7 = 1 bad block detected = 0 block OK bit 6 = 1 uncorrectable ECC error = 0 no error bit 5 reserved bit 4 = 1 ID not found = 0 ID found bit 3 reserved bit 2 = 1 command aborted = 0 command completed bit 1 = 1 track 000 not found = 0 track 000 found bit 0 = 1 DAM not found = 0 DAM found (CP-3022 always 0) 1 w WPC/4 (Write Precompensation Cylinder divided by 4) 2 r/w sector count 3 r/w sector number 4 r/w cylinder low 5 r/w cylinder high 6 r/w drive/head bit 7 = 1 bit 6 = 0 bit 5 = 1 bit 4 = 0 drive 0 select = 1 drive 1 select bit 3-0 head select bits 7 r status register bit 7 = 1 controller is executing a command bit 6 = 1 drive is ready bit 5 = 1 write fault bit 4 = 1 seek complete bit 3 = 1 sector buffer requires servicing bit 2 = 1 disk data read successfully corrected bit 1 = 1 index - set to 1 each disk revolution bit 0 = 1 previous command ended in an error 7 w command register commands: 98 E5 check power mode (IDE) 90 execute drive diagnostics 50 format track EC identify drive (IDE) 97 E3 idle (IDE) 95 E1 idle immediatete (IDE) 91 initialize drive parameters 1x recalibrate E4 read buffer (IDE) C8 read DMA with retry (IDE) C9 read DMA without retry (IDE) C4 read multiplec (IDE) 20 read sectors with retry 21 read sectors without retry 22 read long with retry 23 read long without retry 40 read verify sectors with retry 41 read verify sectors without retry 7x seek EF set features (IDE) C6 set multiple mode (IDE) 99 E6 set sleep mode (IDE) 96 E2 standby (IDE) 94 E0 standby immediate (IDE) E8 write buffer (IDE) CA write DMA with retry (IDE) CB write DMA with retry (IDE) C5 write multiple (IDE) E9 write same (IDE) 30 write sectors with retry 31 write sectors without retry 32 write long with retry 33 write long without retry 3C write verify (IDE) 9A vendor unique (IDE) C0-C3 vendor unique (IDE) 8x vendor unique (IDE) F0-F4 EATA standard (IDE) F5-FF vendor unique (IDE) Writing or reading a register. As said before, we need three actions to read from or write to a register. Writing a value in "Cylinder low", register 4 of the Control Block, we first write the value $0C to $DE01. This sets the addresslines and disables CS0. Then we write the wanted value to $DE00. For reading the register we must perform the same first two actions as with writing to the register but the third step is reading $DE00. If we have to perform several actions with the same register, the first two steps don't need to be repeated everytime. To check if the "Cylinder low" register contains the value we just wrote to it, we only have to read $DE00. Reading a sector. To tell the HD which sector we want to read, we have to give it the following commands: <PRE> .ba $8000 ; begin addres .eq DATALO = $DE00 .eq REGIST = $DE01 .eq DATAHI = $DE02 ;** number of sectors (1 in case) lda #$0A sta REGIST lda #$02 sta REGIST lda #$01 sta DATALO ;** which sector (the first one in this case) lda #$0B sta REGIST lda #$03 sta REGIST lda #$01 sta DATALO ;** which track/cylinder (the first one in this case), low byte lda #$0C sta REGIST lda #$04 sta REGIST lda #$00 sta DATALO ;** which track/cylinder (the first one in this case), high byte lda #$0D sta REGIST lda #$05 sta REGIST lda #$00 sta DATALO ;** which head (the first one in this case) lda #$0E sta REGIST lda #$06 sta REGIST lda #$A0 sta DATALO ;** pass the command (read a sector) lda #$0F sta REGIST lda #$07 sta REGIST lda #$21 sta DATALO ;** wait until the HD has accepted the command WAIT lda DATALO bmi WAIT ;** read the sector thru $DE00 lda #$08 sta REGIST lda #$00 sta REGIST ldy #0 LOOP lda DATALO ; read the low byte sta $0400,y ; put it on screen lda DATAHI ; read the stored high byte sta $0518,y ; put it on screen as well iny ; 256 * 2 bytes? bne LOOP ; no, -> rts ; end of program </PRE> I used this program to check visually if I always read the same data by performing it several times in a row. Writing a sector To know if you read the correct data you must know what you are going to read and therefor you firts have to write to a sector. In the following example it will the same sector as above. Therefor I skip a part of the text to make it more easy for you to read it: <PRE> .ba $9000 ; begin addres . . . ;** pass the command (write a sector) lda #$0F sta REGIST lda #$07 sta REGIST lda #$31 sta DATALO ;** wait until the HD has accepted the command WAIT lda DATALO bmi WAIT ;** write to the sector thru $DE00 lda #$08 sta REGIST lda #$00 sta REGIST ldx #$FF ldy #$00 LOOP stx DATAHI ; store highbyte sty DATALO ; write both bytes to HD dex iny ; next byte? bne LOOP ; yes, -> rts ; end of program </PRE> By swapping the above 'stx' and 'sty', NOT 'DATAHI' and 'DATALO', the contents of the screen must change as well after performing a read of the sector. I haven't tried to read multple sectors yet. As far as I understood you can read up to 256 sectors in a row (by writing the value 0 to register 2) without the need to reprogram the registers. 256 sectors are equivalent to 128 KB which simply means that with a little bit of luck ie. unfragmented file, you can fill the RAM of the C64 with one big read cycle :-) Other Commodores: There is, as far as I know, one major difference with the other C=s: the lack of an equivalent of IO2. So in my opinion the only thing you have to do is to supply the equivalent of IO2 to the interface. -------------------------------------------------------------------------- End of doc for the moment. Gentlemen, please think it over. Comments, ideas and whatever (including critics) are welcome. As there is no other interface available, except the one from our Czech friends which is not freeware and reproducable, what we decide here could become a standard for the future. I already posted my ideas about the filesystem and I'm thinking about to email our Czech friends for info about their system. If theirs is good enough for OUR (!) needs, then we could use that instead inventing the wheel again. Still I would be pleased with any comment or idea, how ever small it is like Andre's great idea of using an little jumper. (I hope this compensates my remark of "greedy and complaining people" :-) ) Groetjes, Ruud - This message was sent through the cbm-hackers mailing list. To unsubscribe: echo unsubscribe | mail cbm-hackers-request@dot.tcm.hut.fi.
Archive generated by hypermail 2.1.1.