/********************************************************/ /* */ /* SUPRA CORPORATION */ /* Hard Disk drivers for the Atari 520 ST */ /* */ /* 1 July 1986 */ /* */ /* This file contains the necessary routines to access */ /* a DMA bus device on the Atari 520ST. These */ /* examples are intended ONLY to be used as examples */ /* on how to read and write to the DMA bus. */ /* They were written in MEGAMAX C. */ /* NOTE: */ /* The 'asm' command in the 'FIFO_RD()' procedure */ /* may be required if your compiler uses a 'CLR' */ /* to zero a memory location. The two lines must */ /* store a LONG 0 into 'FIFO'. A 'CLR' (what */ /* Megamax compiles the commented out line to) */ /* will NOT WORK. */ /* */ /* This file contains two parts: */ /* PART 1 -> Example routines to call part 2 */ /* PART 2 -> Low level routines to actually */ /* access the hard disk drive */ /* */ /* Supra Corporation assumes no responsibility or */ /* liability for the use of these routines. This */ /* information is correct for the current version */ /* (11/20/1985) of TOS in ROM, and is compatible */ /* with Atari's hard disk drive. */ /* If you have questions or comments please use either */ /* Compuserve or call the Supra Support BBS. We */ /* are not able to answer questions over the phone */ /* about this information. We do hope that this */ /* information will help answer the questions on */ /* the use of the powerful and fast Atari 520ST */ /* DMA bus. */ /* */ /* Tech Support Department */ /* CIS 76004,565 */ /* SUPRA CORPORATION */ /* 1133 Commercial Way */ /* Albany, OR 97321 */ /* (503) 967-9075 */ /* Supra Support BBS (503) 926-1980 */ /* */ /********************************************************/ /********************************************************/ /* PART 1 */ /* Example calling routines to access the */ /* hard disk drive */ /* */ /********************************************************/ /****************************************************/ /* Routine to see if hard disk is ready to operate */ /* need only be called after powerup */ /* -pass in dma device number in 'dma' */ /* -return is set on done -- '0' -> OK */ /* '2' -> ERROR */ /* '-1'-> TIMED OUT */ WORD hd_ready(dma) WORD dma; { WORD ret; /* 'zero' is drive ready */ ret = sc_ready(dma); return( ret ); } /* Routine to reset hard disk head to track '0' */ /* not necessary except maybe after 'sc_ready' */ /* -pass in dma device number in 'dma' */ /* -return is set on done -- '0' -> OK */ /* '2' -> ERROR */ /* '-1'-> TIMED OUT */ WORD hd_zero(dma) WORD dma; { WORD ret; /* 'zero' is head at track '0' */ ret = sc_zero(dma); return( ret ); } /* Routine to get and show error status of hard disk */ /* -pass in dma device number in 'dma' */ /* -return is set on done -- '0' -> OK */ /* '2' -> ERROR */ /* '-1'-> TIMED OUT */ WORD hd_error(dma) WORD dma; { WORD ret; /* 'zero' is ok read */ BYTE errs[8], /* array to hold status */ cd_str[4], /* string to hold error code */ cl_str[4], /* string to hold error class */ addr_str[8]; /* string to hold sector address */ ret = hd_sense(gl_dma,&errs[0],4); /* read errors from drive */ if( ret == 0 ) { itoa( (errs[0] & 0x0f),cd_str ); /* get error code */ itoa( (errs[0] & 0x30) >> 4,cl_str ); /* get error class */ if( errs[0] & 0x80 ) { /* Is addr valid ? */ temp = errs[1] & 0x1f << 16; /* figure error sector */ temp |= errs[2] << 8; temp |= errs[3]; ltoa(temp,addr_str); } else addr_str[0] = '\0'; } /* display error stuff on screen here */ return( ret ); } /* Routine to read a section of the hard disk */ /* -pass in dma device number in 'dma' */ /* -return is set on done -- '0' -> OK */ /* '2' -> ERROR */ /* '-1'-> TIMED OUT */ WORD read(sector,count,buf,dma) LONG sector; /* sector number to start at */ WORD count; /* number of sectors to read ( 0 -> 0xfd ) */ LONG buf; /* address of buffer to read data into */ WORD dma; /* dma device to use */ { WORD ret; /* 'zero' is ok read */ ret = hd_read(sector,count,buf,dma) return( ret ); } /* Routine to write a section of the hard disk */ /* -pass in dma device number in 'dma' */ /* -return is set on done -- '0' -> OK */ /* '2' -> ERROR */ /* '-1'-> TIMED OUT */ WORD write(sector,count,buf,dma) LONG sector; /* sector number to start at */ WORD count; /* number of sectors to write ( 0 -> 0xfd ) */ LONG buf; /* address of buffer to write data into */ WORD dma; /* dma device to use */ { WORD ret; /* 'zero' is ok write */ ret = hd_write(sector,count,buf,dma) return( ret ); } /********************************************************/ /* PART 2 */ /* */ /* Actual low level routines to access a dma */ /* device. These routines are also compatible */ /* with the Atari hard disk drives */ /* */ /********************************************************/ WORD *flock = 0x43eL; BYTE *gpip = 0xfffa01L; WORD *diskctl_w = 0xff8604L; LONG *diskctl_l = 0xff8604L; WORD *fifo = 0xff8606L; BYTE *dmahigh = 0xff8609L; BYTE *dmamid = 0xff860bL; BYTE *dmalow = 0xff860dL; LONG save_ssp; #define READY 0x0008aL #define ZERO 0x1008aL #define SENSE 0x3008aL #define READ 0x8008aL #define WRITE 0xa008aL #define LONG_DELAY 690000 #define SHORT_DELAY 23000L #define V_SHORT_DLY 500L #define FLOCK_ON -1 #define FLOCK_OFF 0 VOID sup_on() { save_ssp = Super(0L); } VOID sup_off() { Super(save_ssp); } WORD wait(time) LONG time; { while(time--) { if( (*gpip & 0x20) == 0) return(0); } return(-1); } VOID fifo_rd(count) WORD count; { *fifo = 0x90; *fifo = 0x190; *fifo = 0x90; *diskctl_w = count; *fifo = 0x8a; /* *diskctl_l = 0x0L; DONT use this -- compiler does it WRONG */ asm{ move.l #0x00ff8604,A0 move.l #0x00000000,(A0) } } VOID fifo_wrt(count) WORD count; { *fifo = 0x90; *fifo = 0x190; *diskctl_w = count; *fifo = 0x18a; *diskctl_l = 0x100L; } WORD hd_read(sectno,count,buf,dma) LONG sectno; WORD count; LONG buf; WORD dma; { WORD err; sup_on(); err = select_sector(READ,sectno,count,buf,dma); if( err == 0 ) { fifo_rd(count); err = get_status(0x8a); } end_hd(); sup_off(); return(err); } WORD hd_write(sectno,count,buf,dma) LONG sectno; WORD count; LONG buf; WORD dma; { WORD err; sup_on(); err = select_sector(WRITE,sectno,count,buf,dma); if( err == 0 ) { fifo_wrt(count); err = get_status(0x18a); } end_hd(); sup_off(); return(err); } WORD get_status(mode) WORD mode; { WORD err; err = wait(LONG_DELAY); if( !err ) { *fifo = mode; err = *diskctl_w & 0xff; } return(err); } VOID end_hd() { WORD dummy; *fifo = 0x80; dummy = *diskctl_w; *flock = FLOCK_OFF; } VOID set_dma(buf) LONG buf; { *dmalow = (BYTE) (buf & 0xff); *dmamid = (BYTE) ((buf >> 8) & 0xff); *dmahigh = (BYTE) ((buf >> 16) & 0xff); } WORD select_sector(command,sectno,count,buf,dma) LONG command,sectno; WORD count; LONG buf; WORD dma; { WORD err; *flock = FLOCK_ON; if ( buf ) set_dma(buf); *fifo = 0x88; *diskctl_l = ( (LONG) dma << 21) | command; err = wait(SHORT_DELAY); if( !err ) { *diskctl_l = ( (LONG) dma << 21) | (sectno & 0x1f0000) | 0x8a; err = wait(SHORT_DELAY); if( !err ) { *diskctl_l = (sectno & 0xff00) << 8 | 0x8a; err = wait(SHORT_DELAY); if( !err ) { *diskctl_l = (sectno & 0xff) << 16 | 0x8a; err = wait(SHORT_DELAY); if( !err ) { *diskctl_l = (LONG) (count & 0xff) << 16 | 0x8a; err = wait(SHORT_DELAY); } } } } return(err); } WORD send_dcb(count,dma,command,forever) WORD count,dma,forever; LONG command; { WORD err; sup_on(); err = select_sector(command,0L,count,0L,dma); if ( !err ) { *diskctl_l = 0x8aL; do { err = wait(SHORT_DELAY); } while( err && forever ); err = get_status(0x8a); } end_hd(); sup_off(); return(err); } WORD sc_zero(dma) WORD dma; { return( send_dcb(0,dma,ZERO,0) ) ; } WORD sc_ready(dma) WORD dma; { return( send_dcb(0,dma,READY,0) ) ; } WORD byte_rd(buf,len) BYTE *buf; WORD len; { WORD i; *diskctl_l = 0x8aL; wait(SHORT_DELAY); i=0; while( len ) { if( wait(V_SHORT_DLY) == -1 ) { buf[i++] = (BYTE) (*diskctl_w & 0xff); len--; } else break; } wait(SHORT_DELAY); return(i); } WORD hd_sense(dma,buf,len) WORD dma,len; BYTE *buf; { WORD err; sup_on(); err = select_sector(SENSE,0L,len,0L,dma); if( err == 0 ) { byte_rd(buf,len); err = get_status(0x8a); } end_hd(); sup_off(); return(err); }