[comp.os.minix] Minix ST harddisk driver - problem fixed

leo@marco.UUCP (Matthias Pfaller) (03/07/90)

  Now (after twice trashing my minix-partition) I know, how to have minix run
with my ST (with hypercache) and my ICD-harddisk. I compared the original AHDI
program with the minix-ST harddisk driver. I found no difference, and this
almost drived me crazy, because TOS worked wonderfully with my harddrive.
It absolutely didn't care about the fact that TOS doesn't use IRQs and minix
does. The problem *IS* that the TOS driver writes data and control register
with *ONE* longword access, whereas minix does this with *TWO* 16bit transfers.
I now (after finding this out by myself) found a paragraph in 'Das Atari ST
Profibuch', where it states that atari had stated (somewhere you'll never find
it) that *THIS* is the correct way to access the DMA-controller: use one
long-word transfer to write data and control (if you send command bytes to
the ACSI-device)! The following patch to the 1.5.0 stwini.c and stdma.c
cured the problem. From time to time I read that other people had similar
problems with their STs even without an hypercache installed. Perhaps this
patch can help in such a case too.

	leo@marco.UUCP (Matthias Pfaller)

PS: If you use the diskclocks, you possible have to do some changes in this
    code too. I haven't touched this because I do not use it.

----------------------------------- cut --------------------------------------
*** stwini.c	Wed Mar  7 09:39:31 1990
--- new/stwini.c	Wed Mar  7 09:27:36 1990
***************
*** 73,79 ****
  #endif /* CLOCKS */
  /* Parameters for the disk drive. */
  #define SECTOR_SIZE	512	/* physical sector size in bytes */
! #define NR_DRIVES	1	/* maximum number of drives */
  #define	MAX_MINOR	(NR_DRIVES<<3)
  #define MAX_ERRORS	10	/* how often to try rd/wt before quitting */
  /* dis/enable interrupts */
--- 73,79 ----
  #endif /* CLOCKS */
  /* Parameters for the disk drive. */
  #define SECTOR_SIZE	512	/* physical sector size in bytes */
! #define NR_DRIVES	4	/* maximum number of drives */
  #define	MAX_MINOR	(NR_DRIVES<<3)
  #define MAX_ERRORS	10	/* how often to try rd/wt before quitting */
  /* dis/enable interrupts */
***************
*** 263,270 ****
  	IENABLE();
  #endif
  	dmacomm(wrbit | FDC | SCREG, count, HDC_DELAY);
! 	dmawdat(wrbit | FDC | HDC | A0, 0, HDC_DELAY);
! 	DMA->dma_mode = wrbit;		/* needed? */
  	receive(HARDWARE, &mess);	/* Wait for interrupt. */
  #ifdef SUPRA
  	IDISABLE();
--- 263,270 ----
  	IENABLE();
  #endif
  	dmacomm(wrbit | FDC | SCREG, count, HDC_DELAY);
! 	DMA->dma_mode = wrbit | FDC | HDC | A0;
! 	dmawcmd(0, wrbit);
  	receive(HARDWARE, &mess);	/* Wait for interrupt. */
  #ifdef SUPRA
  	IDISABLE();
***************
*** 297,304 ****
  int cmd;
  {
    DMA->dma_mode = FDC | HDC;
!   DMA->dma_data = (short)(((drive>>1)<<5) | (cmd&0x1F));
!   DMA->dma_mode = FDC | HDC | A0;
  }
  
  PRIVATE int cmdtail(drive, sector, count)
--- 297,303 ----
  int cmd;
  {
    DMA->dma_mode = FDC | HDC;
!   dmawcmd((short)(((drive>>1)<<5) | (cmd&0x1F)), FDC | HDC | A0);
  }
  
  PRIVATE int cmdtail(drive, sector, count)
***************
*** 310,329 ****
    DMA->dma_mode = FDC | HDC | A0;
    if (poll() != OK)
  	return(ERROR);
!   DMA->dma_data = (short) (((drive&1)<<5) | (((int)(sector>>16))&0x1F));
!   DMA->dma_mode = FDC | HDC | A0;
    if (poll() != OK)
  	return(ERROR);
!   DMA->dma_data = (short) ((int)sector >> 8);
!   DMA->dma_mode = FDC | HDC | A0;
    if (poll() != OK)
  	return(ERROR);
!   DMA->dma_data = (short) sector;
!   DMA->dma_mode = FDC | HDC | A0;
    if (poll() != OK)
  	return(ERROR);
!   DMA->dma_data = (short) count;
!   DMA->dma_mode = FDC | HDC | A0;
    if (poll() != OK)
  	return(ERROR);
    return(OK);
--- 309,324 ----
    DMA->dma_mode = FDC | HDC | A0;
    if (poll() != OK)
  	return(ERROR);
!   dmawcmd((short) (((drive&1)<<5) | (((int)(sector>>16))&0x1F)), FDC | HDC | A0);
    if (poll() != OK)
  	return(ERROR);
!   dmawcmd((short) ((int)sector >> 8), FDC | HDC | A0);
    if (poll() != OK)
  	return(ERROR);
!   dmawcmd((short) sector, FDC | HDC | A0);
    if (poll() != OK)
  	return(ERROR);
!   dmawcmd((short) count, FDC | HDC | A0);
    if (poll() != OK)
  	return(ERROR);
    return(OK);
***************
*** 353,359 ****
  }
  
  #ifdef CLOCKS
! #include <minix/sgtty.h>
  #define XFERSIZE 13
  /*===========================================================================*
   *				do_ioctl				     *
--- 348,354 ----
  }
  
  #ifdef CLOCKS
! #include <sgtty.h>
  #define XFERSIZE 13
  /*===========================================================================*
   *				do_ioctl				     *
*** stdma.c	Wed Mar  7 09:39:45 1990
--- new/stdma.c	Wed Mar  7 09:27:15 1990
***************
*** 68,74 ****
  {
    message	m;
  
!   xxxint = 0;			/* no more DMA interrupts */
    ASSERT(qhead == p);
    qhead = QNEXT(p);
    QNEXT(p) = 0;
--- 68,74 ----
  {
    message	m;
  
!   xxxint = (int(*)())0;		/* no more DMA interrupts */
    ASSERT(qhead == p);
    qhead = QNEXT(p);
    QNEXT(p) = 0;
***************
*** 120,132 ****
    DMA->dma_data = data;
  }
  
  PUBLIC void dmacomm(mode, data, delay)
  int mode;
  int data;
  int delay;
  {
-   DMA->dma_mode = mode;
    DMA->dma_mode = mode ^ WRBIT;
    DMA->dma_mode = mode;
    while (--delay >= 0);
    DMA->dma_data = data;
--- 120,140 ----
    DMA->dma_data = data;
  }
  
+ PUBLIC void dmawcmd(dm)
+ union { long l; struct { short data; short mode; } dm; } dm;
+ {
+ 	register long l;
+ 	l = dm.l;
+ 	*((long*)&DMA->dma_data) = l;
+ }
+ 
  PUBLIC void dmacomm(mode, data, delay)
  int mode;
  int data;
  int delay;
  {
    DMA->dma_mode = mode ^ WRBIT;
+   while (--delay >= 0);
    DMA->dma_mode = mode;
    while (--delay >= 0);
    DMA->dma_data = data;
----------------------------------- cut --------------------------------------