Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!rutgers!cbmvax!jesup From: jesup@cbmvax.commodore.com (Randell Jesup) Newsgroups: comp.sys.amiga.programmer Subject: Re: Direct hardware drive access Message-ID: <20240@cbmvax.commodore.com> Date: 1 Apr 91 23:30:20 GMT References: <2161@pdxgate.UUCP> Reply-To: jesup@cbmvax.commodore.com (Randell Jesup) Organization: Commodore, West Chester, PA Lines: 128 In article 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") ;-)