bairds@eecs.cs.pdx.edu (Shawn L. Baird) (03/30/91)
With the recent flamage/discussion I've revitalized some of my interest in trying my hand at direct disk reading. I've included a small snippet of code and will say that I can't even get the drive light to come on. The code enters with Disable() having been called and all DMA turned off (I'm not using any disk DMA for stepping out to track 0, so this shouldn't be a problem should it?). The goal is to step the disk out to track 0. ; step to the outside of the disk in drive 0 (I wish) and.b #$7f,ciaaprb ; select motor and.b #$f7,ciaaprb ; select drive 0 diskready: btst.b #5,ciaapra ; check DSKRDY beq.s diskready or.b #$02,ciaaprb ; set step direction checktrack0: move.l #3000,d0 jsr wait btst.b #4,ciaapra ; check DSKTRACK0 bne.s disktrack0 and.b #$fe,ciaaprb ; step out or.b #$01,ciaaprb bra.s checktrack0 disktrack0: or.b #$88,ciaaprb ; unselect drive 0 The subroutine wait uses the cia timer to wait d0 microseconds and works as far as I can tell. Didn't someone around here claim to have worked on, or developed entirely, the trackdisk.device for 1.3 and 2.0? If so, help! --- Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD The above message is not licensed by AT&T, or at least, not yet.
mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (03/31/91)
In article <2147@pdxgate.UUCP> bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes: >With the recent flamage/discussion I've revitalized some of my interest >in trying my hand at direct disk reading. I've included a small snippet >of code and will say that I can't even get the drive light to come on. >The code enters with Disable() having been called and all DMA turned >off (I'm not using any disk DMA for stepping out to track 0, so this >shouldn't be a problem should it?). The goal is to step the disk out to >track 0. > > ; step to the outside of the disk in drive 0 (I wish) > and.b #$7f,ciaaprb ; select motor > and.b #$f7,ciaaprb ; select drive 0 >diskready: btst.b #5,ciaapra ; check DSKRDY > beq.s diskready > or.b #$02,ciaaprb ; set step direction >checktrack0: move.l #3000,d0 > jsr wait > btst.b #4,ciaapra ; check DSKTRACK0 > bne.s disktrack0 > and.b #$fe,ciaaprb ; step out > or.b #$01,ciaaprb > bra.s checktrack0 >disktrack0: or.b #$88,ciaaprb ; unselect drive 0 > >The subroutine wait uses the cia timer to wait d0 microseconds and works >as far as I can tell. Didn't someone around here claim to have worked on, >or developed entirely, the trackdisk.device for 1.3 and 2.0? If so, help! > >--- > Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD > The above message is not licensed by AT&T, or at least, not yet. Try the following routines, instead. Notice that 'structured' programming techniques are just as doable in assembler as they are in 'C'. Note that when coding in assembler, your code is pretty optimal. In particular, notice that rather than saying: bsr StepDelay rts You can use bra StepDelay Which saves 34 clock cycles and 2 bytes. tdError dc.l 0 ; result of last operation tdDrive dc.b 0 ; selected drive tdDriveBits dc.b 0 ; bits for CIA for selected drive EVEN SetDrive0 clr.b tdDrive move.b #%00110000,tdDriveBits rts SetDrive1 move.b #1,tdDrive move.b #%00101000,tdDriveBits rts SetDrive2 move.b #2,tdDrive move.b #%00011000,tdDriveBits rts ; Turn Amiga drive motor on: MotorOn clr.l tdError lea CIAB,a0 move.b #%11111111,(a0) move.b #%01111111,(a0) move.b #%01000111,d0 or.b tdDriveBits,d0 move.b d0,(a0) ; wait for disk to come up to speed move.l d4,-(sp) move.w #750/3,d4 .wait bsr StepDelay dbra d4,.wait move.l (sp)+,d4 move.l tdError,d0 rts ; Turn Amiga drive motor off: MotorOff move.l #CIAB,a0 move.b #%11111111,(a0) move.b #%10000111,(a0) move.b #%11111111,(a0) rts ; Use CIA A, Timer A, to delay at least 3Ms. StepDelay move.l d0,-(sp) move.b CRAA,d0 and.b #%11000000,d0 or.b #%00001000,d0 move.b d0,CRAA move.b #%01111111,ICRA move.b #(2148&255),TALOA move.b #(2148>>8),TAHIA .wait btst #0,ICRA beq.s .wait move.l (sp)+,d0 rts ; Step toward track 80: StepRight move.l #CIAB,a0 move.b #%01000111,d0 or.b tdDriveBits,d0 move.b d0,(a0) move.b #%01000100,d0 or.b tdDriveBits,d0 move.b d0,(a0) move.b #%01000101,d0 or.b tdDriveBits,d0 move.b d0,(a0) move.b #%01000111,d0 or.b tdDriveBits,d0 move.b d0,(a0) bra StepDelay ; Step toward track 00 (outermost physical track) StepLeft move.l #CIAB,a0 move.b #%01000111,d0 or.b tdDriveBits,d0 move.b d0,(a0) move.b #%01000110,d0 or.b tdDriveBits,d0 move.b d0,(a0) move.b #%01000111,d0 or.b tdDriveBits,d0 move.b d0,(a0) bra StepDelay -- ******************************************************** * Appendix A of the Amiga Hardware Manual tells you * * everything you need to know to take full advantage * * of the power of the Amiga. And it is only 10 pages! * ********************************************************
jesup@cbmvax.commodore.com (Randell Jesup) (03/31/91)
In article <2147@pdxgate.UUCP> bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes: >With the recent flamage/discussion I've revitalized some of my interest >in trying my hand at direct disk reading. I've included a small snippet >of code and will say that I can't even get the drive light to come on. >The code enters with Disable() having been called and all DMA turned >off (I'm not using any disk DMA for stepping out to track 0, so this >shouldn't be a problem should it?). The goal is to step the disk out to >track 0. I assume you've taken over the machine, or you've called GetUnit() to obtain control of the disk hardware. > ; step to the outside of the disk in drive 0 (I wish) > and.b #$7f,ciaaprb ; select motor I would use #~CIAF_DSKMOTOR, that way you don't have to remember the value of 15 million hardware bits. > and.b #$f7,ciaaprb ; select drive 0 This should be #~(CIAF_DSKMOTOR!CIAF_DSKSEL0) - you're in a timing race to see if dskmotor goes high before the disk notices it has been selected. >diskready: btst.b #5,ciaapra ; check DSKRDY > beq.s diskready > or.b #$02,ciaaprb ; set step direction >checktrack0: move.l #3000,d0 For safety when doing calibrates, we usually use 4ms. > jsr wait > btst.b #4,ciaapra ; check DSKTRACK0 > bne.s disktrack0 > and.b #$fe,ciaaprb ; step out > or.b #$01,ciaaprb > bra.s checktrack0 >disktrack0: or.b #$88,ciaaprb ; unselect drive 0 If track 0 is set when you go into calibration, you must step in until the track-0 indication goes away, delay a settle time (15ms on top of the 4ms step), and then reverse direction and search for track 0). -- Randell Jesup, Keeper of AmigaDos, Commodore Engineering. {uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup Thus spake the Master Ninjei: "To program a million-line operating system is easy, to change a man's temperament is more difficult." (From "The Zen of Programming") ;-)
jesup@cbmvax.commodore.com (Randell Jesup) (03/31/91)
In article <mykes.0840@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: > bsr StepDelay > rts >You can use > bra StepDelay >Which saves 34 clock cycles and 2 bytes. One of the oldest optimizations known to mankind (and compilers with tail-recursion/etc optimizations will do this too - even a simple peephole optimizer can catch this). >; Turn Amiga drive motor on: >MotorOn clr.l tdError > lea CIAB,a0 > move.b #%11111111,(a0) > move.b #%01111111,(a0) > move.b #%01000111,d0 > or.b tdDriveBits,d0 > move.b d0,(a0) > ; wait for disk to come up to speed > move.l d4,-(sp) > move.w #750/3,d4 >.wait bsr StepDelay > dbra d4,.wait First, the persons code you replied to was far better than this. You're waiting .75 seconds (750 ms) on every motor-on. We spec that floppy drives on the Amiga MUST be up to speed in .5 seconds. Also, the disk hardware as a ready signal, to tell you when it's up to speed. Many drives come up to speed far faster than .5 seconds, or may have just been turned off and are still close to speed, etc, or may have been on already, etc. The person who you responded to looped checking dskrdy. The best way to to wait .5 seconds, checking dskrdy every so often (2.0 trackdisk checks it every .1 seconds). > move.l (sp)+,d4 > move.l tdError,d0 > rts > >; Turn Amiga drive motor off: >MotorOff move.l #CIAB,a0 > move.b #%11111111,(a0) > move.b #%10000111,(a0) > move.b #%11111111,(a0) ^^^^^^^^^^^^^^^^^^^^ not needed, doesn't hurt BTW, you could have coded that routine 2 bytes shorter and 12 cycles shorter, if you care so much about space/speed. > rts ... >; Step toward track 80: >StepRight move.l #CIAB,a0 > move.b #%01000111,d0 ^ Interesting, that's DSKSEL3 Ever test this code with 4 drives? ^ Interesting, that's outwards (toward 0) This stuff of CIAB is not needed. (though a different one is) > or.b tdDriveBits,d0 > move.b d0,(a0) > move.b #%01000100,d0 ^ Interesting, that's DSKSEL3 ^ Interesting, that's inwards (toward 80) The hardware manual says DSKDIREC MUST be set correctly BEFORE step is set to 0. You must be lucky not to have hit a drive that actually requires it yet. > or.b tdDriveBits,d0 > move.b d0,(a0) > move.b #%01000101,d0 ^ Interesting, that's DSKSEL3 > or.b tdDriveBits,d0 > move.b d0,(a0) > move.b #%01000111,d0 ^ Interesting, that's DSKSEL3 ^ Interesting, that's outwards again This stuff of CIAB is not needed. > or.b tdDriveBits,d0 > move.b d0,(a0) > bra StepDelay And where is your settle routine? (I suspect you merely didn't include it - you need 15ms settle after finishing seeking (on top of the step delay!) -- Randell Jesup, Keeper of AmigaDos, Commodore Engineering. {uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup Thus spake the Master Ninjei: "To program a million-line operating system is easy, to change a man's temperament is more difficult." (From "The Zen of Programming") ;-)
bairds@eecs.cs.pdx.edu (Shawn L. Baird) (03/31/91)
Well, after examining the CIA specifications in appendix F of the Hardware Reference Manual, I found a small misprint in Chapter 10, "Interface Hardware", of the Hardware Reference Manual. On page 238 it says: Bits labeled "PB" are output bits located in CIAAPRB ($BFD100). ^^^^^^^ This should be CIABPRB, for which the correct address is given. Upon switching to this register and using tips provided by Randell Jesup, I was able to get the motor to come on and the drive to spin (Hey, it's more excitement than I've had in weeks!). Thanks both to Mike Schwartz and Randell Jesup for their help. Note: Even the top of this page says CIAAPRA/CIABPRB. In fact, everything else says CIABPRB. Why I saw only the one little reference to CIAAPRA I don't know, but I guess it seemed to make sense that the registers for controlling and sensing the disk would be on the same CIA chip. --- Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD The above message is not licensed by AT&T, or at least, not yet.
bairds@eecs.cs.pdx.edu (Shawn L. Baird) (04/01/91)
Having finished in my attempts at stepping in and out tracks I have decided to move on to the more difficult prospect of reading and (eventually) writing tracks. With this move I have several questions: 1. The documentation for DSKBYTR states that in read mode data is placed here one byte at a time. I assume this is before DMA is started? For the purposes of syncing or somesuch? 2. DMAON is DSKBYTR does not refer to actual DMA activity, but rather that DMA is enabled? 3. Is there any way to busy loop on the completion of disk DMA? (I realize that an interrupt is more elegant, but this is just a test program.) 4. The hardware manual mentions bugs in both reading and writing data. Now, how am I expected to compensate for these bugs? For reading, I assume I request an extra word? 5. I use DSKSYNC on $4489. Is this correct, or at least for most disks such as AmigaDOS disks? If $4489 isn't found does it keep searching forever? 6. The ADKCON register mentions precomposition. Is there a value for precomposition that I should use with standard MFM data? 7. Does anyone have examples of blitter routines which both encode and decode raw MFM tracks? The hardware manual mentions this as a possibility as have several people on Usenet. I suspect this involves some tricky operation with the line mode, with which I'm just not well enough adjusted to figure it out for myself. If you are looking for a good article on just what MFM encoding itself is, and GCR for that matter, take a look at _Transactor for the Amiga_ Vol. 3, Issue 1, "Amiga Disk Encoding Schemes" by Betty Clay, pp. 70-73. Oh, one last question. Has anybody taken a look at AC Tech? Is it very technical? Are they planning on moving from quarterly to bi-monthly or somesuch? --- Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD The above message is not licensed by AT&T, or at least, not yet.
mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (04/01/91)
In article <20215@cbmvax.commodore.com> jesup@cbmvax.commodore.com (Randell Jesup) writes: >In article <mykes.0840@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: >> bsr StepDelay >> rts >>You can use >> bra StepDelay >>Which saves 34 clock cycles and 2 bytes. > > One of the oldest optimizations known to mankind (and compilers with >tail-recursion/etc optimizations will do this too - even a simple peephole >optimizer can catch this). > Some people who've never seen assembler language don't know about this. They *have* to rely upon their compilers to be good enough to do this for them. I'd be interested to know exactly *what* compilers for the Amiga do this optimization? I'd also point out that sometimes debugging can be easier if you do the bsr followed by RTS. You lose the clock cycles and bytes, but you gain the ability to "step over" the subroutine instead of having to manually put a breakpoint at its RTS. >>; Turn Amiga drive motor on: >>MotorOn clr.l tdError >> lea CIAB,a0 >> move.b #%11111111,(a0) >> move.b #%01111111,(a0) >> move.b #%01000111,d0 >> or.b tdDriveBits,d0 >> move.b d0,(a0) >> ; wait for disk to come up to speed >> move.l d4,-(sp) >> move.w #750/3,d4 >>.wait bsr StepDelay >> dbra d4,.wait > > First, the persons code you replied to was far better than this. >You're waiting .75 seconds (750 ms) on every motor-on. We spec that floppy >drives on the Amiga MUST be up to speed in .5 seconds. Also, the disk hardware >as a ready signal, to tell you when it's up to speed. Many drives come up to >speed far faster than .5 seconds, or may have just been turned off and are >still close to speed, etc, or may have been on already, etc. The person who >you responded to looped checking dskrdy. The best way to to wait .5 seconds, >checking dskrdy every so often (2.0 trackdisk checks it every .1 seconds). > I check DSKRDY before reading/writing to the disk. I waited a little extra time deliberatly to help ensure that drives that are up to 50% out of spec work. Better safe than sorry. And to help other developers who use AmigaMail: The article titled "Low Level Disk Access" by Bryce Nesbitt on page VIII-10/11 shows the following routine: motor_wait btst.b #5,CIAA_PRA ; check READY line bne.s motor_wait ; busy wait until drive is ready rts When I tried this on an A500 at EA, it didn't work at ALL. >> move.l (sp)+,d4 >> move.l tdError,d0 >> rts >> >>; Turn Amiga drive motor off: >>MotorOff move.l #CIAB,a0 >> move.b #%11111111,(a0) >> move.b #%10000111,(a0) >> move.b #%11111111,(a0) > ^^^^^^^^^^^^^^^^^^^^ not needed, doesn't hurt >BTW, you could have coded that routine 2 bytes shorter and 12 cycles shorter, >if you care so much about space/speed. > >> rts >... >>; Step toward track 80: >>StepRight move.l #CIAB,a0 >> move.b #%01000111,d0 > ^ Interesting, that's DSKSEL3 > Ever test this code with 4 drives? My mistake. One of us (you, Bryce, and myself) should have caught this one. You saw these sources before we shipped. I had cut these routines from a set of MS-DOS/Atari ST format drivers someone else had written. > ^ Interesting, that's outwards (toward 0) Difference in terminology here, but Randall's usage is more correct. It should be IN instead of RIGHT, and OUT instead of LEFT. > This stuff of CIAB is not needed. > (though a different one is) >> or.b tdDriveBits,d0 >> move.b d0,(a0) >> move.b #%01000100,d0 > ^ Interesting, that's DSKSEL3 > ^ Interesting, that's inwards (toward 80) >The hardware manual says DSKDIREC MUST be set correctly BEFORE step is set to >0. You must be lucky not to have hit a drive that actually requires it yet. > PEOPLE NOTE THIS! There might not be a drive that requires it yet, but there might be in the future. EA has had ZERO returns or reports of any problems with these routines, but it is always a good idea to do it right. >> or.b tdDriveBits,d0 >> move.b d0,(a0) >> move.b #%01000101,d0 > ^ Interesting, that's DSKSEL3 >> or.b tdDriveBits,d0 >> move.b d0,(a0) >> move.b #%01000111,d0 > ^ Interesting, that's DSKSEL3 > ^ Interesting, that's outwards again > This stuff of CIAB is not needed. Kinda picky about the lower 3 bits... is it WRONG? >> or.b tdDriveBits,d0 >> move.b d0,(a0) >> bra StepDelay > > And where is your settle routine? (I suspect you merely didn't >include it - you need 15ms settle after finishing seeking (on top of the >step delay!) > There is a routine called StepToTrack that calls these routines. When it has stepped to the desired track, it waits 15ms. The original poster asked how to step the heads, not how to read/write to the disk. Another word of advice. Do not use the book "Amiga Disk Drives: Inside and Out" by Abacus. I was told by Commodore when I was writing my routines that the book is full of misinformation and was likely to cause people to have disk driver problems. >-- >Randell Jesup, Keeper of AmigaDos, Commodore Engineering. >{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup >Thus spake the Master Ninjei: "To program a million-line operating system >is easy, to change a man's temperament is more difficult." >(From "The Zen of Programming") ;-) -- ******************************************************** * Appendix A of the Amiga Hardware Manual tells you * * everything you need to know to take full advantage * * of the power of the Amiga. And it is only 10 pages! * ********************************************************
DXB132@psuvm.psu.edu (04/01/91)
In article <mykes.0972@amiga0.SF-Bay.ORG>, mykes@amiga0.SF-Bay.ORG (Mike Schwartz) says: >Another word of advice. Do not use the book "Amiga Disk Drives: Inside >and Out" by Abacus. I was told by Commodore when I was writing my routines >that the book is full of misinformation and was likely to cause people >to have disk driver problems. Correct. Although, I bought it because it DOES contain useful information ...but read the hardware manual first and last! (I really got a chuckle out of the example code that polled disk ready after stepping the head or something. Real smart...) -- Dan Babcock
jesup@cbmvax.commodore.com (Randell Jesup) (04/01/91)
In article <mykes.0972@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: >I check DSKRDY before reading/writing to the disk. I waited a little extra time >deliberatly to help ensure that drives that are up to 50% out of spec work. Better >safe than sorry. And to help other developers who use AmigaMail: The article >titled "Low Level Disk Access" by Bryce Nesbitt on page VIII-10/11 shows the following >routine: > >motor_wait btst.b #5,CIAA_PRA ; check READY line > bne.s motor_wait ; busy wait until drive is ready > rts > >When I tried this on an A500 at EA, it didn't work at ALL. Bug report??? It seems to work ok for us currently (2.0 trackdisk checks ready every .1 seconds up to .5, a compromise). What drives didn't that code work on? Did you tell bryce? >>>; Step toward track 80: >>>StepRight move.l #CIAB,a0 >>> move.b #%01000111,d0 >> ^ Interesting, that's DSKSEL3 >> Ever test this code with 4 drives? > >My mistake. One of us (you, Bryce, and myself) should have caught this >one. You saw these sources before we shipped. I had cut these routines >from a set of MS-DOS/Atari ST format drivers someone else had written. I never saw your routines, and Bryce is a busy person. Things like this are why we discourage the Abacus-style of programming (hard-coded constants, no includes), and prefer and encourage use of symbolic references. I would have written #(DSKSEL3!DSKSIDE!DSKDIREC!DSKSTEP), which makes it obvious that DSKSEL3 has been selected, without having to look up or memorize every bit in the hardware. If he was using hardcoded constants, you should have looked up the register definitions at least so you had some idea what he was doing. >> ^ Interesting, that's outwards (toward 0) > >Difference in terminology here, but Randall's usage is more correct. It should >be IN instead of RIGHT, and OUT instead of LEFT. I've never heard of left/right for disks. It's always in/out. >>> move.b #%01000100,d0 >> ^ Interesting, that's DSKSEL3 >> ^ Interesting, that's inwards (toward 80) >>The hardware manual says DSKDIREC MUST be set correctly BEFORE step is set to >>0. You must be lucky not to have hit a drive that actually requires it yet. >> > >PEOPLE NOTE THIS! There might not be a drive that requires it yet, but there >might be in the future. EA has had ZERO returns or reports of any problems >with these routines, but it is always a good idea to do it right. This sort of thing might not come to the attention of EA unless there were a lot of them out there. And as he says, there is no guarantee that the code above will work with the drives that leave the factory tomorrow or any other day. >>> move.b #%01000111,d0 >> ^ Interesting, that's DSKSEL3 >> ^ Interesting, that's outwards again >> This stuff of CIAB is not needed. > >Kinda picky about the lower 3 bits... is it WRONG? It doesn't hurt anything, but it's spurious. I thought you cared about efficiency... :-) >There is a routine called StepToTrack that calls these routines. When >it has stepped to the desired track, it waits 15ms. > >The original poster asked how to step the heads, not how to read/write >to the disk. Actually he seemed to be recalibrating the heads to track 0. >Another word of advice. Do not use the book "Amiga Disk Drives: Inside >and Out" by Abacus. I was told by Commodore when I was writing my routines >that the book is full of misinformation and was likely to cause people >to have disk driver problems. Absolutely. The code in the book doesn't even work with 1.3 roms, unless they've revised it recently. evil, evil, evil, IMHO. NOTE: this is my personal opinion, not an official opinion or statement of Commodore (of course). -- Randell Jesup, Keeper of AmigaDos, Commodore Engineering. {uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup Thus spake the Master Ninjei: "To program a million-line operating system is easy, to change a man's temperament is more difficult." (From "The Zen of Programming") ;-)
jesup@cbmvax.commodore.com (Randell Jesup) (04/01/91)
In article <2161@pdxgate.UUCP> bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes: > 1. The documentation for DSKBYTR states that in read mode data is placed > here one byte at a time. I assume this is before DMA is started? For > the purposes of syncing or somesuch? DIsk data is available in the register. It's possible to read data directly with the processor using this, but tricky and highly liable to break on different processors/machines if it works at all. > 2. DMAON is DSKBYTR does not refer to actual DMA activity, but rather > that DMA is enabled? Yup. > 3. Is there any way to busy loop on the completion of disk DMA? (I > realize that an interrupt is more elegant, but this is just a test > program.) Sure: just check for a DSKBLK interrupt in INTREQR. A DSKBLK interrupt that merely signals your task is trivial, though. > 4. The hardware manual mentions bugs in both reading and writing data. > Now, how am I expected to compensate for these bugs? For reading, I > assume I request an extra word? Always request 1 more word than you know you need for read (not a problem, make the maximum read 6814 instead of 6812). On write, make sure you have a word of $aaa8 OR $2aa8 (depending on the last bit of the previous word). > 5. I use DSKSYNC on $4489. Is this correct, or at least for most disks > such as AmigaDOS disks? If $4489 isn't found does it keep searching > forever? $4489 is the AmigaDos and MSDOS standard (it's an "illegal" mfm value that is guaranteed by the hardware to be both readable and writable). > 6. The ADKCON register mentions precomposition. Is there a value for > precomposition that I should use with standard MFM data? Look at the public unit structures. Normal amiga disks use no precomp on cylinders 0-39, 01 precomp on cylinders 40-79. The values are available from the public unit structure. > 7. Does anyone have examples of blitter routines which both encode and > decode raw MFM tracks? The hardware manual mentions this as a > possibility as have several people on Usenet. I suspect this > involves some tricky operation with the line mode, with which I'm > just not well enough adjusted to figure it out for myself. It's rather tricky (decode is fairly simple, encode is 4-pass). I advise playing with blitlab a bit. Decode: ((odd bits word & 0x5555) << 1) | (even bits word & 0x5555) This can all be done in one blitter pass. The encoding is done in four separate passes. Two passes encode the odd bits, and two passes encode the even bits. The first pass encodes the data bits and the clock bits. The second pass corrects the clock bits of the first pass by unsetting the clock bit of a zero cell that follows a one cell. In all four passes input C is a mask of $5555. This mask will be used to "cookie cut" the input into clock and data bits. In all cases C refers to data bits and C* to clock bits. Equations are: Pass 1: AC + B*C* (A=odd data bits of the source aligned to the odd data bits of the dest, B=source data bits aligned for the clock bits of the dest. C=clock/data cookie cut mask($5555)). Pass 2: A*BC* + BC (B=result of the previous pass, BC preserves the data from the previous pass. A=data source delayed for two bits - results in off bits aligned over the next cells clock. A*BC* will unset the clock bit of any cell that follows a cell with a data of 1. C=clock/data cookie cut mask($5555)). Pass 3: like pass 1, just for even bits. Pass 4: like pass 2, but A is delayed 1 bit instead of 2, and even bits of course. >If you are looking for a good article on just what MFM encoding itself is, >and GCR for that matter, take a look at _Transactor for the Amiga_ Vol. 3, >Issue 1, "Amiga Disk Encoding Schemes" by Betty Clay, pp. 70-73. -- Randell Jesup, Keeper of AmigaDos, Commodore Engineering. {uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup Thus spake the Master Ninjei: "To program a million-line operating system is easy, to change a man's temperament is more difficult." (From "The Zen of Programming") ;-)
mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (04/01/91)
In article <2161@pdxgate.UUCP> bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes: >Having finished in my attempts at stepping in and out tracks I have decided >to move on to the more difficult prospect of reading and (eventually) >writing tracks. With this move I have several questions: I don't want to give away all my source code, but this should help. > 3. Is there any way to busy loop on the completion of disk DMA? (I > realize that an interrupt is more elegant, but this is just a test > program.) You don't have to use interrupts for ANYTHING on the Amiga if you don't want to :) ; Wait until DMA write is finished. We poll IRQ bits to find out. move.w #2,INTREQW(a6) ; clear DMA done bit ... >>> set up and start your DMA <<< moveq #2,d1 ; to make Randall happy! l1 move.w INTREQR(a6),d0 and.w d1,d0 beq.s l1 ; 0, not finished. Make sure you do the following, too. ; Our work is done. 'dsklen'=$4000 prevents accidental writes, ; leave IRQ bits and disk DMA off. move.w #$10,DMACONW(a6) ; disable disk dma. move.w #$4000,DSKLENW(a6) ; prevent accidental writes move.w #$1002,INTREQW(a6) ; DSKSYN+DSKBLCK (to make Randall Happy!) > > 4. The hardware manual mentions bugs in both reading and writing data. > Now, how am I expected to compensate for these bugs? For reading, I > assume I request an extra word? > ; After a disk write DMA has finished, a delay of POSTWRITE_TIME ; miliseconds is required before any other operations (drive select, ; step, head change, etc). The type of disk drives used have a gap ; between the erase head and the read-write head. The disk drive keeps ; the erase head enabled after the end of write gate to compensate for ; the gap. Failure to wait out the delay may result in writing over ; innocent data on other tracks or sides. > 5. I use DSKSYNC on $4489. Is this correct, or at least for most disks > such as AmigaDOS disks? If $4489 isn't found does it keep searching > forever? > Here is a fragment of code that will read your track. Remember, before this routine has been called, the motor is up to speed, the heads have been stepped to the correct track, and 12ms of settle time has elapsed. The first thing that is done is DSKRDY is tested to make sure that the disk hasn't been ejected. ReadTrack btst #DSKRDY,CIAA beq.s TrackReader ; there is a disk in the drive move.l #ERROR_NoDisk,tdError move.l tdError,d0 rts TrackReader clr.l tdError move.w #$4000,DSKLENW(a6) ; turn off DMA (to be safe) move.w #$8400,ADKCONW(a6) ; turn on precomp (280ns) move.w #$4489,DSKSYNW(a6) ; sync pattern for start of header move.l #trackBuffer,DSKPTRW(a6) ; set DMA transfer address ; clear pending interrupt requests. move.w #$1002,INTREQW(a6) move.w #$8210,DMACONW(a6) ; enable disk dma move.w #$8000+READSIZE,d0 ; a number here would be more informative... Randall can tell you what READSIZE should be. move.w d0,DSKLENW(a6) ; set length (WORDS) move.w d0,DSKLENW(a6) ; again! This starts DMA ; If the disk has not been formatted, the DSKSYN won't happen. You have ; to use the timer to timeout in this case. ; Wait until DMA write is finished. We poll IRQ bits to find out. .retry move.w #200,d1 ; about 600 ms ; This is similar to StepDelay, except it breaks out ; of the busy wait loop (for DMA finished) even ; if the 3ms time hasn't elapsed. .waitsync move.b CRAA,d0 and.b #%11000000,d0 or.b #%00001000,d0 move.b d0,CRAA move.b #%01111111,ICRA move.b #(2148&255),TALOA move.b #(2148>>8),TAHIA .wait move.w INTREQR(a6),d0 btst #1,d0 ; DMA done? bne.s .done btst #0,ICRA beq.s .wait dbra d1,.waitsync ; sync never happened, move.w #$4000,DSKLENW(a6) ; stop DMA move.w #$10,DMACONW(a6) ; stop DMA move.l #ERROR_NoSync,tdError ; No Sync move.l tdError,d0 rts ; The read is complete. .done move.w #$4000,DSKLENW(a6) move.w #$10,DMACONW(a6) ; stop DMA bra DecodeTrack ; use the blitter! > 7. Does anyone have examples of blitter routines which both encode and > decode raw MFM tracks? The hardware manual mentions this as a > possibility as have several people on Usenet. I suspect this > involves some tricky operation with the line mode, with which I'm > just not well enough adjusted to figure it out for myself. > Maybe there should be a routine provided by trackdisk.device to do this. The blitter code isn't as tricky as you'd think. Here is how the CPU does it: DecodeLongWord move.l (a0)+,d0 move.l (a0)+,d1 andi.l #$55555555,d0 andi.l #$55555555,d1 lsl.l #1,d0 or.l d1,d0 rts >--- > Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD > The above message is not licensed by AT&T, or at least, not yet. -- ******************************************************** * Appendix A of the Amiga Hardware Manual tells you * * everything you need to know to take full advantage * * of the power of the Amiga. And it is only 10 pages! * ********************************************************
bairds@eecs.cs.pdx.edu (Shawn L. Baird) (04/01/91)
jesup@cbmvax.commodore.com (Randell Jesup) writes: >In article <mykes.0972@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: >>motor_wait btst.b #5,CIAA_PRA ; check READY line >> bne.s motor_wait ; busy wait until drive is ready >> rts >> >>When I tried this on an A500 at EA, it didn't work at ALL. > Bug report??? It seems to work ok for us currently (2.0 trackdisk >checks ready every .1 seconds up to .5, a compromise). What drives didn't >that code work on? Did you tell bryce? This code works perfectly fine on my A500. In fact, it's what I'm using now. Of course, when taking over the machine it may not matter that this is a busy loop. Checking every .1 seconds seems like a good compromise. But you say it checks up to .5 seconds. Does it return an error if the drive is not up to speed within .5 seconds? I modified most of my routines to use constants as you mention. Like you say, it's a good idea. I have my own include file that I have been adding to since starting my assembler projects. I never quite figured out where the common constants are listed so I just pick a suitable name and use it from there on out. It is, of course, much easier than trying to memorize bit numbers. > I've never heard of left/right for disks. It's always in/out. Left/right just doesn't seem to make any sense. On one side of the spindle it's left and on the other it's right. In/out however, make perfect sense. >>PEOPLE NOTE THIS! There might not be a drive that requires it yet, but there >>might be in the future. EA has had ZERO returns or reports of any problems >>with these routines, but it is always a good idea to do it right. > This sort of thing might not come to the attention of EA unless there >were a lot of them out there. And as he says, there is no guarantee that >the code above will work with the drives that leave the factory tomorrow or >any other day. The Chinon timing diagrams in the Hardware Reference Manual explicitly show that the direction should be set prior to stepping the drive. However, they don't show how long, so I'm assuming just doing it in two different instructions is the main thing. That is, using two different instructions would still work on a 68030 machine? >>The original poster asked how to step the heads, not how to read/write >>to the disk. > Actually he seemed to be recalibrating the heads to track 0. You are both correct in essence. I was trying to figure out how to step the heads of the disk to get to track 0. It seems to be the only way to know exactly what track you are on. I assume from then on that you keep the value of the track and modify it every time you step in or out. >>Another word of advice. Do not use the book "Amiga Disk Drives: Inside >>and Out" by Abacus. I was told by Commodore when I was writing my routines >>that the book is full of misinformation and was likely to cause people >>to have disk driver problems. Okay, what book should you use when accessing the drives at such a low level? The Hardware Reference Manual is a good reference, but is somewhat lacking in detail when it comes to such a low level of drive operation. Oh, by the way Mr. Jesup, could you possibly send me some email with the address to C.A.T.S. or somesuch? One final thing. A third party manufacturer is producing a high density 3.5" drive for the Amiga. Does anyone know what ID string it uses? Was this ID string assigned by Commodore? Also, will the high density 3.5" drives in the 3000UX be compatible with this third party drive? Is Commodore going to set a standard for high density 3.5" drives? --- Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD The above message is not licensed by AT&T, or at least, not yet.
dillon@overload.Berkeley.CA.US (Matthew Dillon) (04/02/91)
In article <mykes.0840@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: >Try the following routines, instead. Notice that 'structured' programming >techniques are just as doable in assembler as they are in 'C'. Note that >when coding in assembler, your code is pretty optimal. In particular, notice >that rather than saying: > bsr StepDelay > rts >You can use > bra StepDelay >Which saves 34 clock cycles and 2 bytes. A good example of an optimization that will never make a bit of difference to the overall performance, because the step delay loop does a busy wait. 2 bytes verses how many for the routine? Now, of course, such a *simple* optimization I would probably do myself, but when all is said and done it seems to me that a BETTER optimization would be do something useful while you were waiting on the step... 3ms = 3000uS = many, many cycles. >******************************************************** >* Appendix A of the Amiga Hardware Manual tells you * >* everything you need to know to take full advantage * >* of the power of the Amiga. And it is only 10 pages! * >******************************************************** -Matt -- Matthew Dillon dillon@Overload.Berkeley.CA.US 891 Regal Rd. uunet.uu.net!overload!dillon Berkeley, Ca. 94708 USA
jesup@cbmvax.commodore.com (Randell Jesup) (04/02/91)
In article <2171@pdxgate.UUCP> bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes: >jesup@cbmvax.commodore.com (Randell Jesup) writes: >>In article <mykes.0972@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: >>>motor_wait btst.b #5,CIAA_PRA ; check READY line >>> bne.s motor_wait ; busy wait until drive is ready >>> rts >This code works perfectly fine on my A500. In fact, it's what I'm using >now. Of course, when taking over the machine it may not matter that this >is a busy loop. Checking every .1 seconds seems like a good compromise. >But you say it checks up to .5 seconds. Does it return an error if the >drive is not up to speed within .5 seconds? We specify that drives must be up to speed in .5 seconds. The .5 second max has two reasons: paranoia, since we hadn't been actively using the signal in 1.3, and also performance, since dskrdy may not be active for as much as .7 seconds after motor-on, even though the motor is up to speed (it has to wait for the magnet to come by the sensor). >I modified most of my routines to use constants as you mention. Like you >say, it's a good idea. I have my own include file that I have been adding >to since starting my assembler projects. I never quite figured out where >the common constants are listed so I just pick a suitable name and use it >from there on out. It is, of course, much easier than trying to memorize >bit numbers. They aren't in an include file. They're in the timing diagrams in the 1.3 HW manual and in the text of the low-level disk access article I wrote for AmigaMail a couple of years ago. >The Chinon timing diagrams in the Hardware Reference Manual explicitly show >that the direction should be set prior to stepping the drive. However, they >don't show how long, so I'm assuming just doing it in two different >instructions is the main thing. That is, using two different instructions >would still work on a 68030 machine? The 1.3 HW manual says explicitly that they must be set by two separate writes. 68030 has no affect on this. >Okay, what book should you use when accessing the drives at such a low >level? The Hardware Reference Manual is a good reference, but is somewhat >lacking in detail when it comes to such a low level of drive operation. I'm afraid the HW manual is about it. If you're really careful, know what you're doing and what is legal and illegal by inspection, the abacus book can be used a bit as a reference. It requires a LOT of separating the wheat from the chaff. >One final thing. A third party manufacturer is producing a high density >3.5" drive for the Amiga. Does anyone know what ID string it uses? Was >this ID string assigned by Commodore? Also, will the high density 3.5" >drives in the 3000UX be compatible with this third party drive? Is >Commodore going to set a standard for high density 3.5" drives? I assign ID strings. I assume you're talking about applied engineering. Normally there's no need for you to know other people's id numbers, the same way we keep HW manufacturer numbers private. If there is some reason, let me know. Since their interface to the HD modes is funny, the ID number won't help you. The new HD drives for the tower/UX are just 150 rpm versions of the current drives. They change ID depending on the disk in them, and 2.0 trackdisk reads the id on each disk insertion. Other than that, you merely read or write twice as much data. If you have need for more detailed info, contact CATS. -- Randell Jesup, Keeper of AmigaDos, Commodore Engineering. {uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup Thus spake the Master Ninjei: "To program a million-line operating system is easy, to change a man's temperament is more difficult." (From "The Zen of Programming") ;-)
jesup@cbmvax.commodore.com (Randell Jesup) (04/02/91)
In article <mykes.1046@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes: >> 5. I use DSKSYNC on $4489. Is this correct, or at least for most disks >> such as AmigaDOS disks? If $4489 isn't found does it keep searching >> forever? > >Here is a fragment of code that will read your track. Remember, before this >routine has been called, the motor is up to speed, the heads have been stepped >to the correct track, and 12ms of settle time has elapsed. The first thing that >is done is DSKRDY is tested to make sure that the disk hasn't been ejected. NAK! You say wait 12ms (I assume you already waited the 3ms of step time). That's wrong. You must wait a total of 18ms (3ms + 15ms) for the heads to properly settle. See the 1.3 HW manual timing diagrams, they show the required 18ms total delay. >ReadTrack btst #DSKRDY,CIAA > beq.s TrackReader ; there is a disk in the drive > move.l #ERROR_NoDisk,tdError > move.l tdError,d0 > rts Wrong, the proper bit to check is DSKCHANGE. It goes low immediately if a disk is removed, as the hardware manual states on page 238. DSKRDY only tells you that the motor is up to speed, not whether there's a disk in the drive. It can rotate even with no disk in the drive. >TrackReader clr.l tdError > move.w #$4000,DSKLENW(a6) ; turn off DMA (to be safe) > move.w #$8400,ADKCONW(a6) ; turn on precomp (280ns) > move.w #$4489,DSKSYNW(a6) ; sync pattern for start of header > move.l #trackBuffer,DSKPTRW(a6) ; set DMA transfer address > > ; clear pending interrupt requests. > move.w #$1002,INTREQW(a6) > move.w #$8210,DMACONW(a6) ; enable disk dma > move.w #$8000+READSIZE,d0 ; a number here would be more informative... > >Randall can tell you what READSIZE should be. It should be (6812+2)*2 bytes (6814 words) at least (a bit extra doesn't hurt). If you're not using DSKSYNC/WORDSYNC, you should add a full raw sector to that to ensure getting all sectors. The AmigaMail article goes into all this, and how the numbers are arrived at (it was also posted to BIX in amiga.dev at the time (quite a while ago)). >; If the disk has not been formatted, the DSKSYN won't happen. You have >; to use the timer to timeout in this case. Yup. Since we don't care about performance here, we use a 300000 microsecond wait, started AFTER dma, and you always check for dma completion first if the timer goes off. (A nominal rotation is 200000us, but we're transferring more than a nominal track, and we want a safety margin.) >Maybe there should be a routine provided by trackdisk.device to do this. > >The blitter code isn't as tricky as you'd think. Here is how the CPU >does it: > >DecodeLongWord move.l (a0)+,d0 > move.l (a0)+,d1 > andi.l #$55555555,d0 > andi.l #$55555555,d1 > lsl.l #1,d0 > or.l d1,d0 > rts (BTW, that can be shorter and faster). ;-) Note that applies only to the header/checksum words. Data words (and the 16 bytes of header info) are split, all the odd and even bits together (odd bits first). Also, when doing this you may want to accumulate the checksum value as well (if doing the data area). 2.0 does it like that. Here's a table showing how the bits are split up: * |<- 16 bits->| |<------ 16 bits ------>| * data addr buffer addr * ----- /------------\ ----- /-----------------------\ * +0 | word 0 | +0 | odd bits of word 0 | * |------------| |-----------------------| * +1 | word 1 | +1 | odd bits of word 1 | * |------------| |-----------------------| * | * | | * | * | * | | * | * | * | | * | * |------------| |-----------------------| * +n -2 | word n -2 | +n -2 | odd bits of word n-2 | * |------------| |-----------------------| * +n -1 | word n -1 | +n -1 | odd bits of word n-1 | * \------------/ |-----------------------| * +n +n | even bits of word 0 | * |-----------------------| * +n +1 | even bits of word 1 | * |-----------------------| * | * | * | * | * | * | * |-----------------------| * +2n -2 | even bits of word n-2 | * |-----------------------| * +2n -1 | even bits of word n-1 | * \-----------------------/ * +2n * Here's a piece of a routine to decode data set up like that, and keep a checksum value in a register: (it makes assumptions about certain things, like d4 being $55555555, odd/even sources in a0/a2, destination in a1, count in d1, and 0 in d0) SumBufLoop: ; first we grab the odd bits MOVE.L (A0)+,D2 MOVE.L (A2)+,D3 ; then the even bits EOR.L D2,D0 EOR.L D3,D0 ; add into checksum AND.L D4,D2 AND.L D4,D3 ; mask off clock bits ASL.L #1,D2 ; allign & OR.L D3,D2 ; combine them MOVE.L D2,(A1)+ ; and store in dest DBRA D1,SumBufLoop -- Randell Jesup, Keeper of AmigaDos, Commodore Engineering. {uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com BIX: rjesup Thus spake the Master Ninjei: "To program a million-line operating system is easy, to change a man's temperament is more difficult." (From "The Zen of Programming") ;-)