[comp.sys.atari.st] programming the dma port

cyliax@pur-ee.UUCP (01/14/87)

Has anyone had any experience programming the dma port ? I have build
an interface to use on the port, but I have some problems accessing
it in software. I used the following code segment to access the port:
	{
	short rv;
	short *flock = (short *)0x43e;	   /* flag to disable flpvbl routine */
	short *hdcreg = (short *)0xff8604; /* the fdc/sector count register */
	short *dmareg = (short *)0xff8606; /* dma mode/status register */

		while(!*flock)		/* wait for flock */
			;
		*flock++ ;		/* and set it */

		*dmareg = 0x08;		/* select hdc register with A1 = 0 */
		*hdcreg = 0x00;		/* now write to it */
		rv = *hdcreg;		/* now read from it */

		*flock = 0;		/* enable flpvbl routine */
		return(rv);
	}
When this was run in supervisory mode, there was no activity on the dma port
control signals ( CS R/W* d0-d7 .. ) at all. Although the returned value
did reflect the state on the data lines, for example pulling one low would
reset the coreesponding bit in the returned value.  I have also tried putting
some delays between the reads and writes. Any hints or pointers would be
greatly apreciated.

				Ingo Cyliax
				cyliax@ee.ecn.purdue.edu
				cyliax@ihnp4!pur-ee

espen@well.UUCP (Peter Espen) (01/19/87)

In article <5252@pur-ee.UUCP>, cyliax@pur-ee.UUCP writes:
> Has anyone had any experience programming the dma port ? I have build
> an interface to use on the port, but I have some problems accessing
> it in software. I used the following code segment to access the port:
> 	{
> 	short rv;
> 	short *flock = (short *)0x43e;	   /* flag to disable flpvbl routine */
> 	short *hdcreg = (short *)0xff8604; /* the fdc/sector count register */
> 	short *dmareg = (short *)0xff8606; /* dma mode/status register */
> 
> 		while(!*flock)		/* wait for flock */
> 			;
> 		*flock++ ;		/* and set it */
> 
> 		*dmareg = 0x08;		/* select hdc register with A1 = 0 */
> 		*hdcreg = 0x00;		/* now write to it */
> 		rv = *hdcreg;		/* now read from it */
> 
> 		*flock = 0;		/* enable flpvbl routine */
> 		return(rv);
> 	}
> When this was run in supervisory mode, there was no activity on the dma port
> control signals ( CS R/W* d0-d7 .. ) at all. Although the returned value
> did reflect the state on the data lines, for example pulling one low would
> reset the coreesponding bit in the returned value.  I have also tried putting
> some delays between the reads and writes. Any hints or pointers would be
> greatly apreciated.
> 
> 				Ingo Cyliax
> 				cyliax@ee.ecn.purdue.edu
> 				cyliax@ihnp4!pur-ee

----------------------------------------------------------------------------
	Here is something I pulled off one of the nets awhile ago. It might
not be exactly what you are looking for, however it might help somebody.


The following code was distributed by Supra Corp. of Albany OR
(who make one of the third party ST hard disk drives) on Compuserve
as an example of how to use the ST DMA port to talk to a hard disk.

/***************************************************************************/
/*   */
/* SUPRA CORP. Hard Disk Format drivers for the Atari 520 ST           */
/*   */
/* 15 April 1986   */
/*   */
/*This file containes the routines that are necessary 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.   */
/*   */
/*Supra Corp. 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   */
/*   */
/***************************************************************************/

/***************************************************************************/

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;

LONGsave_ssp;

#defineLONG_DELAY690000
#define SHORT_DELAY23000
#defineFLOCK_ON-1
#defineFLOCK_OFF0

/***************************************************************************/

VOID
sup_on()
{
save_ssp = Super(0L);
}

VOID
sup_off()
{
Super(save_ssp);
}

WORD
wait(time)
LONGtime;
{

while(time--) {
if( (*gpip & 0x20) == 0)
return(0);
}
return(-1);
}

VOID
fifo_rd(count)
WORDcount;
{

*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)
WORDcount;
{

*fifo = 0x90;
*fifo = 0x190;
*diskctl_w = count;
*fifo = 0x18a;
*diskctl_l = 0x100L;
}

WORD
get_status(mode)
WORDmode;
{
WORDerr;

err = wait(LONG_DELAY);
if( !err ) {
*fifo = mode;
err = *diskctl_w & 0xff;
}
return(err);
}

VOID
end_hd()
{
WORDdummy;

*fifo = 0x80;
dummy = *diskctl_w;
*flock= FLOCK_OFF;
}

VOID
set_dma(buf)
LONGbuf;
{

*dmalow = (BYTE) (buf & 0xff);
*dmamid = (BYTE) ((buf >> 8) & 0xff);
*dmahigh = (BYTE) ((buf >> 16) & 0xff);
}

WORD
select_sector(command,sectno,count,buf,dma)
LONGcommand,sectno;
WORDcount;
LONGbuf;
WORDdma;
{
WORDerr;

*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
hd_read(sectno,count,buf,dma)
LONGsectno;
WORDcount;
LONGbuf;
WORDdma;
{
WORDerr;

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)
LONGsectno;
WORDcount;
LONGbuf;
WORDdma;
{
WORDerr;

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);
}

---------------------------------------------------------------------------
Have Fun!
Peter Espen
(espen@well)

pa@lri.UUCP (Patrick Amar) (01/20/87)

Hello,
when you say: *flock++ to set the lock flag, the C compiler
understands something like:
		(flock++, *(flock-1))
This means that you do the ++ on the pointer and not on the
thing pointed to by flock. To set the flag you can say:
		(*flock)++;

Patrick Amar
e mail: ...!seismo!mcvax!inria!lri!orion1!pa