This file is a more specialised look at hardware disc access. Requests for a specialised DOC file covering this material have been fairly numerous now, so I'm going to add this to the DOC file list. As per usual, this file will con- tain material culled from the Amiga Hardware Reference Manual plus extra add- itions of my own where deemed necessary (given that the Amiga manual writers are all devotees of the terse school of writing, the additions are deemed to be necessary on a regular basis!). Contents: Hardware Disc Access:Introduction Hardware Disc Access:Hardware Organisation Hardware Disc Access:CIA Timers For Delays Hardware Disc Access:MFM And GCR Encoding Hardware Disc Access:Basic I/O Hardware Disc Access:Track Selection Hardware Disc Access:Hardware Bugs Hardware Disc Access:File Updates Hardware Disc Access:Introduction There have been a number of requests (particularly among ACC members) for a DOC file on the subject of hardware disc access. Well, here it is. This is partly a reworking of the Hardware Reference Manual (considered a strong contender in some circles for the Plain English Society's gobbledegook award) and various snippets of information that have come my way. As usual, I'll try to make this file as simple to understand as possible given the subject mat- ter. Why hardware disc access? Well, games writers form one group of pro- grammers who immediately come to mind when one thinks of people who require this sort of information, as they are ALWAYS looking for sneaky tricks with which they can bypass the OS and do their own thing. Whether it's custom boot code or finding an alternative low-level disc data organisation to cram more sound samples or graphics data into their creations, games programmers always 'hit the hardware' first and foremost. Further down the list come system rpogrammers, who need hardware info in order to provide those operating system routines that allow the remainder of the programming community to write applications without having to reinvent the wheel many times over to perform tasks such as loading and saving files. Then there's the purely curious. ACC members usually fall into this category, whether or not they fall into the previous two categories. This DOC file should please this latter group too. Programmers who have previously been satisfied with the DOS library should take note of the following caveats: 1) ANY direct access to the hardware is GUARANTEED to destroy Exec's multitasking integrity. If you want to access hardware without compromising multitasking, use the resources (disk.resource and misc.resource etc, accessed in a like manner to devices); 2) Direct access to the disc hardware is complicated by the use of two chip sets (the CIAs and the custom chips); 3) Direct access to the disc hardware also requires a knowledge of hardware-level disc formats (more on this later). If you are not sure what MFM and GCR formats are, then I suggest seeking out suitable reference material before using the information in this DOC file. These warnings given, it is now time to move on. But before I do, note also that this information applies to floppy disc controllers ONLY. Since I do not have a hard disc, and certainly do not have a spare hard disc to experiment with, I cannot give information on hard disc controllers (and in any case, it is highly unlikely that anyone reading this DOC file is then going to go away and write system software unless they're already employed by Commodore-Amiga, and in that case they'll have far more information to hand than here!). Hardware Disc Access:Hardware Organisation Having stated that the disc hardware uses two different chip sets, I shall now outline the disc hardware organisation. The CIA chips (component number 8520) are used for drive selection & disc sensing. The custom chips (specifically, Paula) are used for drive con- trol (read/write mode), and to link areas of memory reserved by the program- mer for disc access to the disc system. Note before I continue that as is the case for ALL memory intended to be used in conjunction with the custom chips, disc read/write buffers MUST be in CHIP RAM. This normally lies at the add- resses given below: $00000-$7FFFF : A500/A1000/A2000 with original chip set $00000-$FFFFF : A500/A1000/A2000/A1500 with Fatter Agnus chip and the new A500P $00000-$1FFFFF : A3000 with Super Fat Agnus Chip (for rich programmers only!) However, this may NOT be true in the future! Commodore has already made four changes to the chip set (the latest being the Enhanced Chip Set specifica- tion as found on latest A3000s) and future changes may see future Amigas with relocatable CHIP RAM pages, so you have been warned! For a method of reser- ving CHIP RAM that works on ALL machines, use the Exec AllocMem() call via exec.library (this HAS to work or else Commodore will face lawsuits!). Having dealt with CHIP RAM, now to the registers of the disc hardware system. First, the CIA registers. These lie at addresses $BFD000-$BFEFFF, but not all of these addresses are used. Below is a table outlining the CIA regi- ster set used by the disc hardware, including addresses, register names, and functions. NOTE:many signals accepted by the CIA registers are ACTIVE LOW, in other words, to turn the function ON requires a ZERO to be written into the approriate register or register bit (as opposed to the normal signal logic, called ACTIVE HIGH). In the table below, (L) denotes ACTIVE LOW, and (H) de- notes ACTIVE HIGH. Register Bit Function -------- --- -------- CIAAPRA 5 DSKRDY signal (L). ($BFE001) Drive will pull this signal low (clear the bit) when the drive motor is known to be rotating at full speed (see Note 1 below). 4 DSKTRACK0 signal (L). Drive will pull this signal low (clear the bit) when the disc drive read/write heads are positioned over track zero (see Note 2 below). When this signal is active, software MUST NOT ATTEMPT TO STEP THE HEADS OUTWARDS! Modern add-on drives ignore the signal in these circumstances, but older drives may try to step out, resulting in a _35 repair bill for a dead drive! YOU HAVE BEEN WARNED! 3 DSKPROT signal (L). Disc write protected signal: 0 = Disc write protected 1 = Disc writeable 2 DSKCHANGE (L). Disc changed signal. This bit becomes zero when a disc is removed from the drive (signalling a disc change). The signal only becomes 1 again if a disc is inserted AND a step pulse is re- ceived (built-in safety feature, which makes sure that a real disc is being accessed, and not thin air). CIABPRB 7 DSKMOTOR (L). ($BFD000) Disc motor control signal. Implemented in a non-standard fashion. Drives LATCH the signal (i.e., keep their own private copy of it) when selected. So, to force a drive motor to be in a given state, set or clear this bit, THEN send a signal along one of the drive select lines. The drive will "remember" the state of its motor once the select signal is turned off. 0 = Motor ON 1 = Motor OFF CAUTION:after turning the motor ON, software MUST wait for either 1/2 sec (500 ms) or DSKRDY to go low. Other- wise, the motor will NOT be at full speed, and a write operation will trash the disc! 6 DSKSEL3 (L). Select drive 3 (DF3: if available on the user's system). 0 = Select drive for operation 1 = Drive ignores other signals 5 DSKSEL2 (L). Select drive 2 (DF2: if available on the user's system). 0 = Select drive for operation 1 = Drive ignores other signals 4 DSKSEL1 (L). Select drive 1 (DF1: if available on the user's system). 0 = Select drive for operation 1 = Drive ignores other signals 3 DSKSEL0 (L). Select drive 0 (DF0:), THE internal drive on A500s (some A1000/2000 have two inter- nal drives), and the one used for booting WorkBench under KickStart 1.2/1.3. 0 = Select drive for operation 1 = Drive ignores other signals 2 DSKSIDE Specify which disc read/write head to use. All Amiga drives are double sided. Hence there are two read-write heads. Use: 0 = Select UPPER surface disc head 1 = Select LOWER surface disc head This value MUST be stable for at least 100 microseconds before writing, and at least 1.3 MILLIseconds must elapse before switching DSKSIDE. 1 DSKDIREC Specify direction to seek the heads. 0 = Seek TOWARD CENTRE SPINDLE 1 = Seek TOWARD OUTER EDGE This signal MUST be set up BEFORE issuing a disc step signal. DO NOT use a single write to the register to perform both tasks! Use (for example): MOVE.B #$0A,CIABPRB ... short delay, e.g. NOP MOVE.B #$09,CIABPRB to step the heads outward on DF0:. 0 DSKSTEP (L). Step the heads of the disc a distance of one track. So, to step 5 tracks, this signal needs to be sent 5 times. The signal MUST be sent as: Write 1 into bit Write 0 into bit Very short delay, e.g. a NOP Write 1 into bit As in: MOVE.B #$08,CIABPRB MOVE.B #$09,CIABPRB NOP MOVE.B #$08,CIABPRB for EACH INDIVIDUAL step operation. See notes 3,4. CIABICR 4 DSKINDEX (L). ($BFDD00) Disc index pulse. Can be used to gen- erate a level 6 interrupt. Notes on Above Table 1) DSKRDY valid ONLY when drive motor is ON. At other times, configuration information may obscure the meaning of this input. 2) Track zero is the OUTERMOST track of a disc. The usual largest track is track 79, located nearest the centre of the disc. Some drives (BUT NOT ALL!) are capable of reading and writing up to track 83. DO NOT ASSUME that software attempting such access will work on all machines! 3) Amiga drives are guaranteed to step to the next track within 3 milliseconds (3 ms). Some drives will perform much faster than this, but NOT ALL. Using software delay loops (decre- menting a counter) is NOT ACCEPTABLE (and not portable to machines using 68020/68030 processors with higher clock speeds). A better method is to use the CIA timers to pro- vide the delay. See later. 4) When reversing directions, a MINIMUM delay of 18 ms is required from the last step pulse. Settle time for Amiga drives is specified at 15 ms. That covers the CIA portion of the disc hardware. Now I present a table of registers, bits and functions, this time for the various custom chip regis- ters used by the disc hardware system (located at $DFF000 onwards). Note: many registers exist as pairs, one for reading, one for writing. Write-only register are denoted by (W), read-only registers by (R). Register Bits Function -------- ---- -------- $DFF020 3-0 DSKPTH (W) $DFF022 15-0 DSKPTL (W) Disc data pointer registers Contains a pointer to the area of CHIP RAM used for data transfer. Store the address in these two registers. A single MOVE.L can be used for this. $DFF024 DSKLEN (W) Disc data length & access register 15 DMAEN Secondary disc DMA enable. Disc access using a DMA channel CANNOT take place if this bit is zero! 14 WRITE 0 = Read access 1 = Write access 13-0 LENGTH These bits contain the number of WORDS to transfer. $DFF01A DSKBYTR (R) Disc data byte & status read 15 DSKBYT Set to 1 by disc system when bits 0-7 of this register contain a valid byte of data. When this register is read by the 68000 or DMA, this bit is cleared for the next data byte status. 14 DMAON Indicates when DMA is ACTUALLY ON. Is only set to 1 when ALL DMA enable bits pertinent to the disc system are set! 13 DISKWRITE Reflects the state of the WRITE bit in DSKLEN above. 12 WORDEQUAL Indicates that the DSKSYNC register equals the disc input stream. This bit is only true while the input stream matches the sync register, which can be for as little as 2 microseconds! See below for DSKSYNC. 11-8 Currently unused. DO NOT RELY ON READ VALUE. 7-0 DATA Value of disc data byte that has been read. $DFF07E DSKSYNC (W) Disc synchronisation value register 15-0 Disc synchronisation value. Normally set to the magic MFM sync mark value of $4489 by AmigaDOS. Hardware pro- grammers can experiment with other values (CAUTION!). $DFF010 ADKCONR (R) $DFF09E ADKCON (W) Audio and Disc Control Register Use in the following manner: MOVE.W ADKCONR,D0 for READING MOVE.W D0,ADKCON for WRITING 15 SET/CLR Best illustrated by an example. If the word $8001 is written to a regi- ster with a SET/CLR bit, then bit 0 will be SET, and all other bits left untouched. If the word $0001 is writ- ten, then bit 0 will be CLEARED, and all other bits left untouched. This allows the programmer to affect ONLY those bits required for the given operation. Also, see typed_hardware.doc for more info. 14 PRECOMP1 13 PRECOMP0 Precompensation value. Values are: 00 : No precompensation 01 : 140 ns precompensation 10 : 280 ns precompensation 11 : 560 ns precompensation 12 MFMPREC 0 = GCR precompensation (allows Amiga drives to read Apple Macintosh discs with certain programming tricks) 1 = MFM (Normal AmigaDOS setting, also allows Atari ST/IBM PC discs to be read) 10 WORDSYNC Set to 1 to allow synchronising and starting of DMA on disc read of a word. DSKSYCN contains the synchronisation word. VERY USEFUL. 9 MSBSYNC Set to 1 to enable synchronisation on most significant bit of input (used for GCR setting) 8 FAST Value of 1 selects 2 microseconds per bit cell (MFM). Data must be valid raw MFM data. Value of 0 selects 4 micro- seconds per bit cell (GCR). This covers the register organisation of the disc hardware. Before covering how to use the registers for disc access, it is time to cover MFM encoding & related topics. Hardware Disc Access:CIA Timers For Delays The CIA chips contain on-board timer hardware, that allows the programmer to implement precisely timed delay loops that can migrate happily across differ- ent versions of the Amiga. This facility will be vital in managing the disc hardware, so I shall now describe the usage of the CIA timers to generate a fixed-period delay loop. Now, the CIA timers are often chosen to implement delay loops that are relatively independent of the remaining Amiga hardware. However, accord- ing to the Concise Hardware Reference Manual, the timing signals for NTSC and PAL Amigas differs slightly. The timing signals are: NTSC : 715.909 KHz PAL : 715.379 KHz However, these timing signals remain constant across different Amiga specifi- cations, from base A500 all the way to A3000 with 68040 accelerator board. As a means of creating processor-independent delay loops, the CIAs are the prime choice. The best timer to use under most circumstances is the CIA-B Timer B, and this timer can be found at $BFD600/$BFD700. It is a 16-bit timer, and to use it requires setting control bits in the CIA control registers. But first let's see the sequence of events in action: MOVE.W #TIMEVAL,D0 ;Timer value MOVE.B D0,CIABTBLO ;set low byte LSL.W #8,D0 MOVE.B D0,CIABTBHI ;set high byte This sequence sets the CIA-B Timer B write only latches. These are registers that hold the timing value until the control register forces this value to be loaded into the actual timer counters and counting to begin. Having set the timer latches, it is time to start the timer. An instruction that can be used is: MOVE.B #%00011001,CIABCRB If one refers to the Concise Hardware Reference Manual, and examines the bit allocations of CIABCRB, the effect of the above instruction is: 1) Alarm bit (bit 7):don't care about it, so set it to 0. 2) Inmode bits (Bits 6,5):Want timer to count the incoming clock signal pulses, so set these bits to 00. 3) Load bit (bit 4):Force timer to load the latch values into the timer, and then count down to zero, so set this bit to 1. 4) Runmode bit (bit 3):Set to 1 for one-shot mode (since we only want a single delay). 5) Outmode bit (bit 2):Set to 0 to receive a pulse on the line being sensed. 6) PBON bit (bit 1):Set to 0 (leave PB7 line alone as it's needed elsewhere!). 7) Start bit (bit 0):Set to 1 to start the timer counting down. OK, now we've set off our timer. Now we need to be able to sense when it has reaced the timeout condition (i.e., time is up). Well, the best way is to set up the interrupt control register (CIABICR) to allow the CIA to generate an interrupt upon a timeout. To allow Timer B to generate an interrupt within the CIA itself, use: MOVE.B #%10000010,CIABICR or similar. This writes the control bits into the CIA's interrupt latch, and allows Timer B to create an interrupt within the CIA. Now, reading the same register address will read the CIA-B interrupt input bits, and if Bit 1 is set, then the timer has timed out. Of course, as CIA-B will generate a level 6 interrupt (IPL6 on the 68000), it is possible to write a level 6 interrupt handler to check for this, but it is also poss- ible to read the register directly (especially if the level 6 interrupt vec- tor is disabled or redirected by the programmer for other reasons). Timer A on the CIA-B can also be used (as it is not in use for any operating system purposes) but if the operating system has been killed off by the programmer, ALL of the timers are free. The above code applies mainly if at least some facets of the operating system are being kept alive (for true friendliness within the multitasking environment, use the CIA Resource, and the Exec OpenResource() call). Also, the programmer can choose to test the bits of the CIA interrupt register directly or write an interrupt handler to do it (INT2 if using the CIA-A timers, INT6 if using CIA-B). Don't forget to enable the required in- terrupt in the 4703 interrupt controller (custom chip-write to INTENA, at ad- dress $DFF09A to control the required interrupts), and to change the value of the 68000 status register if required by your code. This requires access to supervisor mode, which can be done in two ways. First, there is an Exec call that will run a piece of code in supervisor mode: MOVE.L ExecBase,A6 JSR Superstate(A6) MOVE.L D0,Old_SSTk ;keep this value! and allow recovery of user mode via: MOVE.L Old_SSTk,D0 MOVE.L ExecBase,A6 JSR UserState(A6) or alternatively, if you're killing off the operating system, try this rather naughty piece of code: LEA MyTrap0(PC),A0 MOVE.L A0,$80 ;addr of TRAP #0 vector TRAP #0 ... ;from here on, MOVE SR is ;allowed as you are in ;supervisor mode! ... MyTrap0 MOVE.W (SP)+,D0 ;get status reg BSET #13,D0 ;set supervisor mode MOVE.W D0,-(SP) ;put back RTE ;return in supervisor mode! This is a very naughty piece of code (which destroys multitasking integrity) of the sort that a games coder might like to use when returning to the oper- ating system is not called for. Now that we can implement CIA timer delay loops (needed later on), it is time to look at MFM and GCR data encoding. Hardware Disc Access:MFM And GCR Encoding Those who haven't encountered direct writing to disc before may be surprised to find that the actual bit patterns written to the disc differ from the bit patterns of the data that the programmer writes to disc when using AmigaDOS routines. Well, all is to be revealed. The fundamental problem of writing data to a disc is detecting the difference between a zero bit and a one bit. The next problem is detecting the difference between individual bits, be they ones or zeros. Since the disc read/write head uses magnetic fields for its operations, there are only two possibilities:magnetic field on and magnetic field off. Allocating each of these signals to a zero and one bit respectively would render detection of an individual bit impossible. To solve this problem, a scheme called frequency modulation was de- vised, whereby CHANGES in the magnetic field value written to the disc were used to signal the start of a bit, and the TYPE of change encountered used to determine which type of bit was written during the original write opera- tion. This scheme works for low-volume data storage, but when the density of the data exceeds a certain value, the frequency of read/write errors builds up to an unacceptable value. For the technically minded, the problem is that high-speed flux changes take time to generate the respective electronic sig- nal change, a time known as the half zero bit length, and the minimum value of this is the main determinant of the maximum density of data storable on a disc. Also, there is a delay during initiation of read/write operations, this value being the precompensation value (although Amiga disc drives are capable of handling read/write operations with zero precompensation). Generally, the faster the read/write operation, the more precompensation needed. Overcoming the problem of large precompensation values for densely packed data on a disc led to the formation of Modified Frequency Modulated encoding (MFM). This encoding scheme expands the actual data to twice its original size, but in doing so generates raw data to write to the disc that is efficient enough to allow 880K of user data to be stored on a 3.5 inch disc. So, what is MFM? The exact relationship is: User Data Bit MFM Bits ------------- -------- 1 01 0 10 if following a 0 data bit 0 00 if following a 1 data bit Now according to the Amiga Hardware Reference Manual, it is possible to use the blitter to encode and decode the MFM data. Well, for the record, I have not tried this, so those willing to experiment might like to disassemble the trackdisk.device and see if Commodore have written blitter MFM routines (and if they haven't, why mention this?). Really clever programmers reading this can write their own. GCR encoding is an entirely different matter. Sad to say, Commodore- Amiga do NOT give any in-depth information on this subject, other than to say that a translation table (called a nibbliser table) is used to prevent too many consecutive 1 or 0 bits occuring in the data stream. Users who want this information should obtain a comprehensive reference work covering hardware- level disc formats and floppy disc hardware in general. Anyone familiar with Apple II (there's nostalgia for you!) disc drives and their hardware-level format, or the Apple Macintosh disc format, please get in touch so that I can provide information on GCR encoding for Amiga users! As I was perusing the subject, a piece of code that performed MFM en- coding and decoding without the need for the trackdisk device appeared on ACC disc 18, so I decided to have a further look. The code turned out to be quite interesting (as it had no comments explaining it-thanks Mark Flemans for an example of the minimalist approach to documentation!), but apparently works. Hardware Disc Access:Basic I/O Now is the time to start using the registers and performing some actual disc operations. The following code is all my own, to be considered freeware and rippable/editable to the reader's preferences/sexual leanings etc. First, disc access via the DMA channels. This is the usual method, & has the advantage of allowing the 68000 to get on with other processing while a disc is being read. Now users with one disc drive will not normally need to consider the drive select signals, but I shall include the drive select code so that the code can be used by users with more than one drive. The sequence of operations looks like this in assembler: MOVE.B #$78,CIABPRB ;switch ON motor, no drive select MOVE.B #$F0,CIABPRB ;select drive 0 bwait1 BTST #5,CIAAPRA ;drive ready? (Busy wait-sigh) BNE.S bwait1 ;wait until so LEA $DFF000,A5 ;point to custom chips MOVE.L #BUFFER,DSKPTH(A5) ;point to our buffer * The two statement sets below are commented out. Remove the comment * characters for the operation wanted. * MOVE.W #$4000,DSKLEN(A5) ;turn off secondary disc DMA * MOVE.W #$8000,D0 ;secondary DMA on, READ DISC * ADD.W #DATASIZE,D0 ;no of WORDS to READ * MOVE.W D0,DSKLEN(A5) ;need to write TWICE to * MOVE.W D0,DSKLEN(A5) ;start the operation! * MOVE.W #$4000,DSKLEN(A5) ;turn off secondary disc DMA * MOVE.W #$C000,D0 ;secondary DMA on, WRITE DISC * ADD.W #DATASIZE,D0 ;no of WORDS to WRITE * MOVE.W D0,DSKLEN(A5) ;need to write TWICE to * MOVE.W D0,DSKLEN(A5) ;start the operation! ... here wait for DMA to complete MOVE.W #$4000,DSKLEN(A5) ;turn off disc DMA again MOVE.B #$F8,CIABPRB ;turn motor OFF MOVE.B #$F0,CIABPRB ;select drive 0 Ok, some notes about the above code. First, the motor is switched on, with no drive select signals sent. Because the signals are ACTIVE LOW, the bits to turn OFF a function are SET. The same applies to the drive select signal immediately following. Now anyone who has read my previous DOC files will know that I HATE busy waits, such as the one that I've sadly included here. Well, this code is intended to be simple to understand, so I'll break the golden rule and use a busy wait to wait for the drive to be ready. This just waits for the DSKRDY bit to go low. Of course, an alternative is to use the disk index pulse bit to trigger a level 6 interrupt, and then read DSKRDY within the interrupt, while your code does something more useful than twiddle its thumbs. Now, point A5 at the custom chips, to make life easier (especially if you use the hardware.i ACC include file), then point the DSKPTH/L registers at the buffer of your choice. Here, we decide whether to read or write to disc. Both code sections are included above. Just remove the comment markers from the one required, & delete the other. Note that in order to set off a DMA disc operation, the DSKLEN regi- ster must be written to TWICE. This is intended to prevent accidental writes to a disc (which are of course always to be avoided!), and ensure that when a disc operation is requested, the hardware receives a genuine request. The above code does this. Of course, it is possible to read or write the 'hard' way, using the 68000 to keep track of things, but the above is more efficient (barring the busy wait). Now, some restrictions. First, the above should be used to read or write an entire track at a time. It is possible to modify it to read in one sector at a time, but the above is not intended to be an advanced routine. Sector-level disc I/O requires using the DSKBYTR and DSKSYNC registers, and also probably requires handling via interrupts not only for maximum effic- iency, but for maximum data integrity too. When using the above code for a track read or write, the size of the buffer should be: (512 * 11) * 2 + 2 = 11266 bytes Size of 1 track MFM Overhead The reason for the size given is 1) a single sector is 512 bytes of user data on a standard AmigaDOS disc; 2) there are 11 sectors per track; 3) all data in MFM format is expanded to twice the uncoded size; 4) an extra word is to be reserved to take account of a hardware bug (see below) that Commodore just happen to have mentioned in the Amiga Hardware Reference Manual. Now, there remains another task to be performed before reading data from a disc. That is to make sure that the data coming off the disc is syn- chronised to the actual data layout. The programmer wants to be sure that a data stream coming in actually STARTS at the first word of the first sector of the track being read. How is this done? Well, for an AmigaDOS disc, load DSKSYNC with the magic value $4489. This is a value called a 'sync mark'. This value is chosen so that there is no way possible that any data on the disc encodes to this value. There are a number of such values, but AmigaDOS uses $4489. Normal user data will never encode to this number using MFM encoding as given above, and so the disc sys- tem can use this value to mark the start of the track. Having loaded DSKSYNC with the sync mark value, enable the WORDSYNC bit in ADKCON prior to reading or writing. Then, data transfer will NOT be performed until the sync mark is found, at which point the following word of data on the disc will be the start point for data transfer. Use: MOVE.W #$4489,DSKSYNC(A5) where A5 points to the start of the custom chip registers ($DFF000). Then set WORDSYNC in ADKCON: MOVE.W #$9500,ADKCON(A5) which sets the WORDSYNC, MFMPREC and FAST bits. Do this BEFORE the main code for reading or writing discs above. Hardware Disc Access:Track Selection This is the final basic function to be performed. Track selection is a mite complicated, because the drives do not signal directly (except for track 0) when the heads are aligned over a given track. So, to perform this function, the programmer MUST first seek to track 0 (at which point the DSKTRACK0 bit of CIAAPRA will become zero. This requires first that the drive be selected, then the motor turned on, then DSKDIREC set to 1 to force a seek to the outer edge of the disc (where track 0 lies). Then, send a step pulse to DSKSTEP as outlined above until DSKTRACK0 goes low. Then, SAVE this track number in a variable set up within the program for this purpose. From this point on, to find a given track requires a seek in the given direction, incrementing the variable each time a step inwards is performed, and decrementing the varia- ble when a step outwards is performed. Locating a specified track then requ- ires a compare with the desired track number. For example, after selecting a drive and turning on the motor, code such as the following may be used: FindTRK0 btst #4,CIAAPRA ;hit track 0? beq.s FoundTRK0 ;skip if so move.b #%11110010,CIABPRB ;seek to outer, DF0: ... ;here set up a delay using a CIA timer ... ;for 18 milliseconds move.b #%11110001,CIABPRB ;set DSKSTEP high move.b #%11110000,CIABPRB ;then low move.b #%11110001,CIABPRB ;then high again ... ;here set up 3 ms delay using ... ;a CIA timer bra.s FindTRK0 ;and check if hit track 0 FoundTRK0 clr.w TrackNumber ;absolute variable (sigh) ... ;from here, can seek anywhere! Having used this, code to seek in a given direction can use a second varia- ble (call it TrackWanted). A CMP between the two will establish the seek di- rection. Alternatively, use: move.w TrackNumber,d0 move.w TrackWanted,d1 sub.w d0,d1 ;check seek direction beq.s Done ;already there! bpl.s Seek_Inward neg.w d1 move.b #%11110110,CIABPRB ;set DSKDIREC outwards ... ;here CIA timer delay, 18 ms Seek_Out move.b #%11110001,CIABPRB ;set DSKSTEP high move.b #%11110000,CIABPRB ;then low move.b #%11110001,CIABPRB ;then high again subq.w #1,TrackNumber ;update track count cmp.w TrackWanted,TrackNumber ;found req'd track? beq.s Seek_Done ;got it! subq.w #1,d1 bne.s Seek_out ... Seek_Inward move.b #%11110100,CIABPRB ;set DSKDIREC inwards ... ;here CIA timer delay, 18 ms Seek_In move.b #%11110001,CIABPRB ;set DSKSTEP high move.b #%11110000,CIABPRB ;then low move.b #%11110001,CIABPRB ;then high again addq.w #1,TrackNumber ;update track count cmp.w TrackWanted,TrackNumber ;found req'd track? beq.s Seek_Done ;got it! subq.w #1,d1 bne.s Seek_In Seek_Done ... This should cover most needs for hardware disc programmers. Those requiring a routine to perform sector-level access, be warned that the facilities provi- ded for sector-level access are limited. First, the DSKBYTR register must be polled on a regular basis while the track is being scanned. Second, since the disc system does NOT maintain sector counters in hardware, the programmer has to provide variables for this purpose within the program. Unless there is a shortage of available memory, and sector-level access is the ONLY option open to the programmer, then reading an entire track in one go is a far superior option. Hardware Disc Access:Hardware Bugs Now the bad news. The Amiga Hardware Reference Manual contains a short para- graph (tucked away where it can't be seen too easily so as not to alarm the first-time hardware programmer!) which mentions a disc hardware bug. Well, it is really two bugs, one occurring during a read operation, and one occurring during a write operation. Firstly, during a read operation, the last word requested may not be read. This doesn't always happen, but just in case it does, the buffer for a hardware disc read should be one word longer than necessary. Also, for write operations, the extra last word should match the first word of the buffer. I forgot to reserve space for sync marks in the buffer information above (sorry about that!), so make the first word the sync mark, then a track full of data and finally a copy of the sync mark. Hardware Disc Access:File Updates For updated versions of this file, or any of the other files in this series of DOC files, the contact addresses are: Dave Edwards Mark Meany 232 Hale Road 12 Hinkler Road WIDNES Thornhill Cheshire SOUTHAMPTON WA8 8QA Hants The first of these is mine. Sending a blank formatted disc to me at the above address, with a stamped, self-addressed jiffy bag for return postage (stand- ard 1st class stamp sufficient) will get you the files of your choice, writ- ten to your disc in uncompressed ASCII format. Sending a disc to Mark at the above address (plus jiffy bag, stamp etc.) will get you one of the ACC club discs which contain these files spread over a period (they were intended for the ACC club readership initially, and are now Public Domain DOCs distributed as part of the ACC club material by Mark). All DOC files appearing on the ACC Club discs are in compressed format, and you'll need the packer/depacker that is supplied with the ACC discs to be able to edit them, if this is your wish. Should anyone out there have information to add to the files, please contact either Mark or myself at the addresses above, sending your info as an uncompressed ASCII file. I shall add the info to the relevant file when time allows, and send off the latest version upon request. All contributors will be acknowledged gratefully. **** VERY IMPORTANT **** Since the DOC files have now grown alarmingly in number (and size-they occupy nearly 3MB when decompressed!) from 1/10/91 onwards, ALL reques .