home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
hard_ref
/
dma_docs
/
supexmp.c
< prev
Wrap
Text File
|
1985-11-18
|
9KB
|
435 lines
/********************************************************/
/* */
/* 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);
}