home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / diskutil / noahdi / hd_low.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-05  |  11.0 KB  |  313 lines

  1. /*
  2.     File: HD_LOW.C       Low Level Harddisk Driver. AHDI Compatible.
  3. */
  4. /*
  5. Copyright (c) 1988 - 1991 by Ted Schipper.
  6.  
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted,
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in
  11. supporting documentation.
  12.  
  13. This software is provided AS IS with no warranties of any kind.  The author
  14. shall have no liability with respect to the infringement of copyrights,
  15. trade secrets or any patents by this file or any part thereof.  In no
  16. event will the author be liable for any lost revenue or profits or
  17. other special, indirect and consequential damages.
  18. */
  19.  
  20. #include "dma.h"
  21. #include "mfp.h"
  22. #include "hddriver.h"
  23. #include "system.h"
  24.  
  25. /***************************************************************************
  26.  
  27.                             LOW-LEVEL Driver
  28.                            ------------------
  29.  HISTORY
  30. ---------
  31.  Oct 1988. THS. Started. Tested read, write and timeout routines.
  32.                 V0.00
  33.  
  34. ***************************************************************************/
  35.  
  36. /***************************************************************************
  37.  *
  38.  * Function name : hwrite. Write to physical sectors on hard disk.
  39.  * Parameters    : long  sector number. 21 bits address.
  40.  *                 short sector count.   8 bits count.
  41.  *                 long  buffer addr    32 bits address.
  42.  *                 short device number.  4 bits: bit 0   = drive # ( 0 or 1)
  43.  *                                               bit 1-3 = controller # (0-7)
  44.  * Returns       : long OK    = write went ok.
  45.  *                      ERROR = timeout.
  46.  * Description   : Write count sectors to ASCI device, starting at given
  47.  *                 sector number, under DMA. Use the data starting at addr.
  48.  * Comments      : Assumes processor is in supervisor mode, and not more
  49.  *                 than 254 sectors written.
  50.  */
  51.  
  52. long hwrite(sect_nr,sect_cnt,buf_addr,dev)
  53.  
  54.  long  sect_nr;
  55.  short sect_cnt;
  56.  long  buf_addr;
  57.  short dev;
  58.  
  59. {
  60.  long  status;
  61.  short dummy = 0;
  62.  
  63.  FLOCK = -1;                            /* disable FDC operations */
  64.  setdma(buf_addr);                      /* setup DMA transfer address */
  65.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  66.  DMA->DATA = (short)((dev >> 1) << 5) | (HD_WRITE); /* cntrl + opcode */
  67.  DMA->MODE = NO_DMA | HDC | A0;         /* A1 high again */
  68.  if (setss(dev,sect_nr,sect_cnt) != OK) /* write bytes 1,2,3,4 to contrlr */
  69.  {
  70.     hdone();                            /* restore DMA device to normal */
  71.     return(ERROR);
  72.  }
  73.  DMA->MODE = NO_DMA | SC_REG;           /* clear FIFO = toggle R/W bit */
  74.  DMA->MODE = DMA_WR | NO_DMA | SC_REG;  /* and select sector count reg */
  75.  DMA->SECT_CNT = sect_cnt;              /* write sector cnt to DMA device */
  76.  DMA->MODE = DMA_WR | NO_DMA | HDC | A0;/* select DMA data register again */
  77.  DMA->DATA = dummy;                     /* write control byte ( = 0 ) */
  78.  DMA->MODE = DMA_WR;                    /* start DMA transfer */
  79.  status = endcmd(DMA_WR | NO_DMA | HDC | A0); /* wait for DMA completion */
  80.  hdone();                               /* restore DMA device to normal */
  81.  return(status);
  82. }
  83.  
  84.  
  85. /***************************************************************************
  86.  *
  87.  * Function name : hread. Read physical sectors from hard disk.
  88.  * Parameters    : long  sector number. 21 bits address.
  89.  *                 short sector count.   8 bits count.
  90.  *                 long  buffer addr    32 bits address.
  91.  *                 short device number.  4 bits: bit 0   = drive # ( 0 or 1)
  92.  *                                               bit 1-3 = controller # (0-7)
  93.  * Returns       : long OK    = read went ok.
  94.  *                      ERROR = timeout.
  95.  * Description   : Read count sectors from ASCI device, starting at given
  96.  *                 sector number, under DMA. Place the data starting at addr.
  97.  *                 
  98.  * Comments      : Assumes processor is in supervisor mode, and not more
  99.  *                 than 254 sectors are read.
  100.  */
  101.  
  102. long hread(sect_nr,sect_cnt,buf_addr,dev)
  103.  
  104.  long  sect_nr;
  105.  short sect_cnt;
  106.  long  buf_addr;
  107.  short dev;
  108.  
  109. {
  110.  long  status;
  111.  short dummy = 0;
  112.  
  113.  FLOCK = -1;                            /* disable FDC operations */
  114.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  115.  DMA->DATA = (short)((dev >> 1) << 5) | (HD_READ);
  116.  setdma(buf_addr);                      /* setup DMA transfer address */
  117.  if (setss(dev,sect_nr,sect_cnt) != OK) /* write bytes 1,2,3,4 to contrlr */
  118.  {
  119.     hdone();                            /* restore DMA device to normal */
  120.     return(ERROR);
  121.  }
  122.  DMA->MODE = DMA_WR | NO_DMA | SC_REG;  /* clear FIFO = toggle R/W bit */
  123.  DMA->MODE = NO_DMA | SC_REG;           /* and select sector count reg */
  124.  DMA->SECT_CNT = sect_cnt;              /* write sector cnt to DMA device */
  125.  DMA->MODE = NO_DMA | HDC | A0;         /* select DMA data register again */
  126.  DMA->DATA = dummy;                     /* write control byte ( = 0 ) */
  127.  DMA->MODE = dummy;                     /* start DMA transfer ( = 0 ) */
  128.  status = endcmd(NO_DMA | HDC | A0);    /* wait for DMA completion */
  129.  hdone();                               /* restore DMA device to normal */
  130.  return(status);
  131. }
  132.  
  133.  
  134. /***************************************************************************
  135.  *
  136.  * Function name : endcmd. Wait for end of ASCI command and get status.
  137.  * Parameters    : short Mode word to write DMA mode register.
  138.  * Returns       : long. ASCI completion status or
  139.  *                       ERROR when timeout occured.
  140.  * Description   : Wait for the end of an ASCI command with a long
  141.  *                 timeout. Write mode word to DMA mode register and
  142.  *                 read the DMA data register. Data register should
  143.  *                 contain the completion status byte.
  144.  * Comments      : Assumes processor is in supervisor mode.
  145.  */
  146.  
  147. long endcmd(mode)
  148.  
  149.  short mode;
  150.  
  151. {
  152.  if (fdone() != OK)                   /* wait for operation done ack */
  153.     return(ERRORL);
  154.  DMA->MODE = mode;                    /* write mode word to mode register */
  155.  return((long)(DMA->DATA & 0x00FF));  /* return completion byte */
  156. }
  157.  
  158.  
  159. /***************************************************************************
  160.  *
  161.  * Function name : setss. Set ACSI drive, sector number and number of sectors
  162.  * Parameters    : short drive number. Disk drive number to use.
  163.  *                 long  sector number. First sector to be transfered.
  164.  *                 short sector count.  Number of sectors to be transfered.
  165.  * Returns       : long. OK    = SCSI bytes ack OK.
  166.  *                       ERROR = SCSI bytes not ack, timed out. 
  167.  * Description   : Send 4 bytes: drv | MSB sector, MidSB sector, LSB sector,
  168.  *                 sector count to controller. Wait after each byte for 
  169.  *                 ACSI acknowledge.
  170.  * Comments      : Assumes processor is in supervisor mode.
  171.  */
  172.  
  173. long setss(drv,sect_nr,sect_cnt)
  174.  
  175.  short drv;
  176.  long  sect_nr;
  177.  short sect_cnt;
  178.  
  179. {
  180.  DMA->MODE = NO_DMA | HDC | A0;          /* A0 line high again */
  181.  if (qdone() != OK)                      /* wait for ack */
  182.     return(ERROR);
  183.  
  184.  DMA->DATA = (short)(((drv & 1) << 5) | (((short)(sect_nr >> 16)) & 0x1F));
  185.  DMA->MODE = NO_DMA | HDC | A0;         /* write drv | MSB sector */
  186.  if (qdone() != OK)                     /* wait for ack */
  187.     return(ERROR);
  188.  
  189.  DMA->DATA = (short)((short)sect_nr >> 8); /* write MidSB sector */
  190.  DMA->MODE = NO_DMA | HDC | A0;
  191.  if (qdone() != OK)
  192.     return(ERROR);
  193.  
  194.  DMA->DATA = (short) sect_nr;           /* write LSB sector */
  195.  DMA->MODE = NO_DMA | HDC | A0;
  196.  if (qdone() != OK)
  197.     return(ERROR);
  198.  
  199.  DMA->DATA = (short) sect_cnt;          /* write sector count */
  200.  DMA->MODE = NO_DMA | HDC | A0;
  201.  if (qdone() != OK)
  202.     return(ERROR);
  203.  
  204.  return(OK);                            /* everything OK, tell the caller */
  205. }
  206.  
  207.  
  208. /***************************************************************************
  209.  *
  210.  * Function name : hdone. Restore DMA device to normal.
  211.  * Parameters    : None.
  212.  * Returns       : long. Status of DMA status register.
  213.  * Description   : Restore the DMA mode register for FDC use and clear
  214.  *                 the FDC lock variable. Return (= read) the DMA status
  215.  *                 register.
  216.  * Comments      : Assumes processor is in supervisor mode.
  217.  */
  218.  
  219. long hdone()
  220. {
  221.  DMA->MODE = NO_DMA;        /* restore DMA mode register */
  222.  FLOCK = 0;                 /* FDC operations may get going again */
  223.  return((long)DMA->STATUS); /* read and return DMA status register */
  224. }
  225.  
  226.  
  227. /***************************************************************************
  228.  *
  229.  * Function name : setdma. Setup DMA base (transfer) address.
  230.  * Parameters    : long address. Address to place in base register.
  231.  * Returns       : None. (void)
  232.  * Description   : setup the DMA base HIGH / MID / LOW registers for
  233.  *                 a DMA operation.
  234.  * Comments      : Assumes processor is in supervisor mode.
  235.  */
  236.  
  237. void setdma(addr)
  238.  
  239.  long addr;
  240.  
  241. {
  242.  DMA->ADDR[LOW]  = (char)(addr);
  243.  DMA->ADDR[MID]  = (char)(addr >> 8);
  244.  DMA->ADDR[HIGH] = (char)(addr >> 16);
  245. }
  246.  
  247.  
  248. /***************************************************************************
  249.  *
  250.  * Function name : qdone. Wait for command byte handshake.
  251.  * Parameters    : none.
  252.  * Returns       : long. OK    = Handshake received.
  253.  *                       ERROR = Handshake not received, timed out.
  254.  * Description   : Wait for a DMA handshake after a command byte has
  255.  *                 been send. Use a short timeout.
  256.  * Comments      : None.
  257.  */
  258.  
  259. long qdone()
  260. {
  261.  return(wait_dma_cmpl(STIMEOUT));
  262. }
  263.  
  264.  
  265. /***************************************************************************
  266.  *
  267.  * Function name : fdone. Wait for operation done handshake.
  268.  * Parameters    : none.
  269.  * Returns       : long. OK    = Handshake received.
  270.  *                       ERROR = Handshake not received, timed out.
  271.  * Description   : Wait for a DMA handshake after an operation has
  272.  *                 been completed. Use a long timeout.
  273.  * Comments      : None.
  274.  */
  275.  
  276. long fdone()
  277. {
  278.  return(wait_dma_cmpl(LTIMEOUT));
  279. }
  280.  
  281.  
  282. /***************************************************************************
  283.  *
  284.  * Function name : wait_dma_cmpl. Wait for DMA interrupt with timeout.
  285.  * Parameters    : unsigned long timerticks to wait before timeout.
  286.  * Returns       : long. OK    = DMA interrupt occured.
  287.  *                       ERROR = No DMA interrupt occured, timed out.
  288.  * Description   : Wait for a DMA interrupt (IRQ line) to occur within
  289.  *                 timerticks * 5 milliseconds.
  290.  * Comments      : Assumes hz_200 timerfield is being updated and 
  291.  *                 processor is in supervisor mode.
  292.  */
  293.  
  294. long wait_dma_cmpl(t_ticks)
  295.  
  296.  unsigned long t_ticks;
  297.  
  298. {
  299.  unsigned long to_count;
  300.  
  301.  to_count = t_ticks + HZ_200;   /* calc value timer must get to */
  302.  
  303.  do
  304.  {
  305.     if ( (MFP->GPIP & IO_DINT) == 0) /* Poll DMA IRQ interrupt */
  306.          return(OK);                 /* got interrupt, then OK */
  307.  }  while (HZ_200 <= to_count);      /* check timer */
  308.  
  309.  return(ERROR);                      /* no interrupt, and timer expired, */
  310.                                      /* return ERROR status.             */
  311. }
  312.  
  313.