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

  1. /*
  2.     File: HD_EXTRA.C     Extra Low Level Harddisk Routines.
  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.                         Some EXTRA LOW-LEVEL Stuff
  28.                        ----------------------------
  29.  HISTORY
  30. ---------
  31.  Nov 1988. THS. Started. Tested send_cmd routine. Added req_sense.
  32.  Dec 1988. THS. Tested req_sense routine. Not sure it works OK. HAC bug.
  33.  Jan 1989. THS. Added, tested wd_msel and wd_format. Also tested some
  34.                 drive errors. Controller always reports no errors.
  35.                 V0.00
  36.  
  37. ***************************************************************************/
  38.  
  39. /***************************************************************************
  40.  *
  41.  * Function name : wd_format. Format hard disk
  42.  * Parameters    : short  device number. 4 bits: bit 0   = drive # ( 0 or 1)
  43.  *                                               bit 1-3 = controller # (0-7)
  44.  *                 short  pattern_flag.  2 bits: bit 1-3 = Data pattern Flag
  45.  *                 short  pattern.       8 bits: bit 0-7 = Data pattern
  46.  *                 short  ileave_high.   8 bits: bit 0-7 = Interleave High
  47.  *                 short  ileave_low.    8 bits: bit 0-7 = Interleave Low
  48.  * Returns       : long. dma completion byte or time-out (-1)
  49.  * Description   : Format a harddisk with given pattern and interleave.
  50.  * Comments      : Assumes processor is in supervisor mode, and drive
  51.  *                 specifications has been set with the wd_msel command.
  52.  */
  53.  
  54. long wd_format(dev,pattern_flag,pattern,ileave_high,ileave_low)
  55.  
  56.  short dev;
  57.  short pattern_flag;
  58.  short pattern;
  59.  short ileave_high;
  60.  short ileave_low;
  61.  
  62. {
  63.  long status;
  64.  short dummy = 0;
  65.  
  66.  FLOCK = -1;                            /* disable FDC operations */
  67.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  68.  DMA->DATA = (short)((dev >> 1) << 5) | (HD_FD); /* contrl# + command */
  69.  DMA->MODE = NO_DMA | HDC | A0;
  70.  if (qdone() != OK)                     /* wait for ack */
  71.  {
  72.     hdone();                            /* restore DMA device to normal */
  73.     return(ERROR);
  74.  }
  75.  DMA->DATA =  (short)((dev & 1) << 5) | (pattern_flag & 6); /* drv# + pat flag */
  76.  DMA->MODE = NO_DMA | HDC | A0;
  77.  if (qdone() != OK)                     /* wait for ack */
  78.  {
  79.     hdone();                            /* restore DMA device to normal */
  80.     return(ERROR);
  81.  }
  82.  DMA->DATA = pattern;
  83.  DMA->MODE = NO_DMA | HDC | A0;
  84.  if (qdone() != OK)                     /* wait for ack */
  85.  {
  86.     hdone();                            /* restore DMA device to normal */
  87.     return(ERROR);
  88.  }
  89.  DMA->DATA = ileave_high;
  90.  DMA->MODE = NO_DMA | HDC | A0;
  91.  if (qdone() != OK)                     /* wait for ack */
  92.  {
  93.     hdone();                            /* restore DMA device to normal */
  94.     return(ERROR);
  95.  }
  96.  DMA->DATA = ileave_low;
  97.  DMA->MODE = NO_DMA | HDC | A0;
  98.  if (qdone() != OK)                     /* wait for ack */
  99.  {
  100.     hdone();                            /* restore DMA device to normal */
  101.     return(ERROR);
  102.  }
  103.  DMA->DATA = dummy;
  104.  DMA->MODE = NO_DMA | HDC | A0;
  105.  
  106.  while ((MFP->GPIP & IO_DINT) == IO_DINT) ; /* wait (forever) for completion */
  107.  status = (long)(DMA->DATA & 0x00FF);   /* get the status */
  108.  hdone();                               /* restore DMA device to normal */
  109.  return(status);                        /* return completion status */
  110. }
  111.  
  112.  
  113. /***************************************************************************
  114.  *
  115.  * Function name : wd_msel. Mode select. Specify drive format parameters.
  116.  * Parameters    : short device number. 4 bits: bit 0   = drive # ( 0 or 1 )
  117.  *                                              bit 1-3 = controller # (0-7)
  118.  *                 short count.         size of parameter block.
  119.  *                 char * parameterblock. pointer to parameter block.
  120.  * Returns       : long. ASCI completion byte or time-out.
  121.  * Description   : Send a mode select command to a controller and drive
  122.  *                 followed by the parameter block which is send under DMA.
  123.  * Comments      : Assumes processor is in supervisor mode, and parameter
  124.  *                 block is not bigger than 1 sector (512 bytes).
  125.  */
  126.  
  127. long wd_msel(dev,cnt,param)
  128.  
  129.  short dev;
  130.  short cnt;
  131.  char * param;
  132.  
  133. {
  134.  long status;
  135.  short dummy = 0;
  136.  
  137.  FLOCK = -1;                            /* disable FDC operations */
  138.  setdma(param);                         /* setup DMA transfer address */
  139.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  140.  DMA->DATA = (short)((dev >> 1) << 5) | (HD_MSEL); /* contrl# + command */
  141.  DMA->MODE = NO_DMA | HDC | A0;
  142.  if (qdone() != OK)                     /* wait for ack */
  143.  {
  144.     hdone();                            /* restore DMA device to normal */
  145.     return(ERROR);
  146.  }
  147.  DMA->DATA =  (short)((dev & 1) << 5);  /* drv# */
  148.  DMA->MODE = NO_DMA | HDC | A0;
  149.  if (qdone() != OK)                     /* wait for ack */
  150.  {
  151.     hdone();                            /* restore DMA device to normal */
  152.     return(ERROR);
  153.  }
  154.  DMA->DATA = dummy;
  155.  DMA->MODE = NO_DMA | HDC | A0;
  156.  if (qdone() != OK)                     /* wait for ack */
  157.  {
  158.     hdone();                            /* restore DMA device to normal */
  159.     return(ERROR);
  160.  }
  161.  DMA->DATA = dummy;
  162.  DMA->MODE = NO_DMA | HDC | A0;
  163.  if (qdone() != OK)                     /* wait for ack */
  164.  {
  165.     hdone();                            /* restore DMA device to normal */
  166.     return(ERROR);
  167.  }
  168.  DMA->DATA = cnt;
  169.  DMA->MODE = NO_DMA | HDC | A0;
  170.  if (qdone() != OK)                     /* wait for ack */
  171.  {
  172.     hdone();                            /* restore DMA device to normal */
  173.     return(ERROR);
  174.  }
  175.  DMA->MODE = NO_DMA | SC_REG;           /* clear FIFO and */
  176.  DMA->MODE = DMA_WR | NO_DMA | SC_REG;  /* select sector count register */
  177.  DMA->SECT_CNT = 1;                     /* sector count */
  178.  DMA->MODE = DMA_WR | NO_DMA | HDC | A0; /* select DMA register again */
  179.  DMA->DATA = dummy;                     /* write last byte */
  180.  DMA->MODE = DMA_WR;                    /* start DMA transfer */
  181.  if (fdone() != OK)                     /* wait for DMA completion */
  182.  {
  183.      hdone();                           /* restore DMA device to normal */
  184.      return(ERROR);
  185.  }
  186.  DMA->MODE = DMA_WR | NO_DMA | HDC | A0; /* set DMA register to normal */
  187.  status = (long)(DMA->DATA & 0x00FF);   /* get ASCI completion byte */
  188.  hdone();                               /* restore DMA device to normal */
  189.  return(status);                        /* return ASCI completion byte */
  190. }
  191.  
  192.  
  193. /***************************************************************************
  194.  *
  195.  * Function name : dosahdxc. Send an ASCI command with timeout.
  196.  * Parameters    : short device number. 4 bits: bit 0   = drive # ( 0 or 1 )
  197.  *                                              bit 1-3 = controller # (0-7)
  198.  *               : short * cdb. Pointer to the Command Descriptor Block.
  199.  * Returns       : long OK    = command block send OK.
  200.  *                      ERROR = timeout.
  201.  * Description   : Send 6 bytes from the Command Descriptor Block to an
  202.  *                 ASCI device.  
  203.  * Comments      : Assumes processor is in supervisor mode. 
  204.  */
  205.  
  206. long dodahdxc(dev,cdb)
  207.  
  208.  short dev;
  209.  short cdb[6];
  210.  
  211. {
  212.  short i;
  213.  long status;
  214.  
  215.  cdb[0] |= ((dev >> 1) << 5);           /* put controller# in first byte */
  216.  cdb[1] |= ((dev & 1) << 5);            /* put drive# in second byte */
  217.  FLOCK = -1;                            /* disable FDC operations */
  218.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  219.  for (i=0; i<6; i++)                    /* write 6 bytes to ASCI device */
  220.  {
  221.     DMA->DATA = cdb[i];                 /* next 5 bytes with A1 high */
  222.     DMA->MODE = NO_DMA | HDC | A0; 
  223.     if (i<5)                            /* not the last byte ? */
  224.     {                                   /* use short time-out */
  225.        if (qdone() != OK)               /* wait for ack */
  226.        {
  227.           hdone();                      /* restore DMA device to normal */
  228.           return(ERROR);
  229.        }
  230.     }
  231.     else                                /* last byte, use long time-out */
  232.     {
  233.        if (fdone() != OK)               /* wait for ack */
  234.        {
  235.           hdone();                      /* restore DMA device to normal */
  236.           return(ERROR);
  237.        }
  238.     }
  239.  }
  240.  DMA->MODE = NO_DMA | HDC | A0;         /* get ASCI completion byte */
  241.  status = (long)(DMA->DATA & 0x00FF);
  242.  hdone();                               /* restore DMA device to normal */
  243.  return(status);                        /* return with completion byte */
  244. }
  245.  
  246.  
  247. /***************************************************************************
  248.  *
  249.  * Function name : send_cmd. Send an ASCI command with timeout.
  250.  * Parameters    : short * cdb. Pointer to the Command Descriptor Block.
  251.  * Returns       : long OK      = command block send OK.
  252.  *                      ERROR   = timeout.
  253.  * Description   : Send 6 bytes from the Command Descriptor Block to an
  254.  *                 ASCI device.  
  255.  * Comments      : Assumes processor is in supervisor mode. 
  256.  */
  257.  
  258. long send_cmd(cdb)
  259.  
  260.  short cdb[6];
  261.  
  262. {
  263.  short i;
  264.  long status;
  265.  
  266.  FLOCK = -1;                            /* disable FDC operations */
  267.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  268.  for (i=0; i<6; i++)                    /* write 6 bytes to ASCI device */
  269.  {
  270.     DMA->DATA = cdb[i];                 /* next 5 bytes with A1 high */
  271.     DMA->MODE = NO_DMA | HDC | A0; 
  272.     if (i<5)                            /* not the last byte ? */
  273.     {                                   /* use short time-out */
  274.        if (qdone() != OK)               /* wait for ack */
  275.        {
  276.           hdone();                      /* restore DMA device to normal */
  277.           return(ERROR);
  278.        }
  279.     }
  280.     else                                /* last byte, use long time-out */
  281.     {
  282.        if (fdone() != OK)               /* wait for ack */
  283.        {
  284.           hdone();                      /* restore DMA device to normal */
  285.           return(ERROR);
  286.        }
  287.     }
  288.  }
  289.  DMA->MODE = NO_DMA | HDC | A0;         /* get ASCI completion byte */
  290.  status = (long)(DMA->DATA & 0x00FF);
  291.  hdone();                               /* restore DMA device to normal */
  292.  return(status);                        /* return with completion byte */
  293. }
  294.  
  295.  
  296. /***************************************************************************
  297.  *
  298.  * Function name : req_sense. Request sense. Return Status Error Code 
  299.  * Parameters    : short  device number. 4 bits: bit 0   = drive # ( 0 or 1)
  300.  *                                               bit 1-3 = controller # (0-7)
  301.  * Returns       : long. 1st byte of Error Status Codes
  302.  * Description   : Send a request sense command to a controller and drive,
  303.  *                 then read the ASCI completion byte and the 4 Error Status
  304.  *                 codes.
  305.  * Comments      : Assumes processor is in supervisor mode.
  306.  */
  307.  
  308. long req_sense(dev)
  309.  
  310.  short dev;
  311.  
  312. {
  313.  short status[5], i;
  314.  short dummy = 0;
  315.  
  316.  for (i=0; i<5; i++)
  317.     status[i] = 0x0080;
  318.  
  319.  FLOCK = -1;                            /* disable FDC operations */
  320.  DMA->MODE = NO_DMA | HDC;              /* write 1st byte (0) with A1 low */
  321.  DMA->DATA = (short)((dev >> 1) << 5) | (HD_RS); /* contrl# + command */
  322.  DMA->MODE = NO_DMA | HDC | A0; 
  323.  if (qdone() != OK)                     /* wait for ack */
  324.  {
  325.     hdone();                            /* restore DMA device to normal */
  326.     return(1);
  327.  }
  328.  DMA->DATA = (short)((dev & 1) << 5);   /* drv# */
  329.  DMA->MODE = NO_DMA | HDC | A0;
  330.  if (qdone() != OK)                     /* wait for ack */
  331.  {
  332.     hdone();                            /* restore DMA device to normal */
  333.     return(2);
  334.  }
  335.  DMA->DATA = dummy;
  336.  DMA->MODE = NO_DMA | HDC | A0;
  337.  if (qdone() != OK)                    /* wait for ack */
  338.  {
  339.     hdone();                           /* restore DMA device to normal */
  340.     return(3);
  341.  }
  342.  DMA->DATA = dummy;
  343.  DMA->MODE = NO_DMA | HDC | A0;
  344.  if (qdone() != OK)                    /* wait for ack */
  345.  {
  346.     hdone();                           /* restore DMA device to normal */
  347.     return(4);
  348.  }
  349.  DMA->DATA = 4;
  350.  DMA->MODE = NO_DMA | HDC | A0;
  351.  if (qdone() != OK)                    /* wait for ack */
  352.  {
  353.     hdone();                           /* restore DMA device to normal */
  354.     return(5);
  355.  }
  356.  DMA->DATA = dummy;
  357.  DMA->MODE = NO_DMA | HDC | A0;
  358.  qdone();                              /* wait 100 msec */
  359.  status[0] = (DMA->DATA & 0x00FF);     /* get completion status byte */
  360.  qdone();                              /* wait 100 msec */
  361.  status[1] = (DMA->DATA & 0x00FF);     /* get the four request sense bytes */
  362.  qdone();                              /* etc. */
  363.  status[2] = (DMA->DATA & 0x00FF);
  364.  qdone();
  365.  status[3] = (DMA->DATA & 0x00FF);
  366.  qdone();
  367.  status[4] = (DMA->DATA & 0x00FF);
  368. /*
  369.  printf("sense : %02x %02x %02x %02x %02x\n",
  370.         status[0],status[1],status[2],status[3],status[4]);
  371. */
  372.  hdone();                               /* restore DMA device to normal */
  373.  return((long)status[1]);               /* return 1st Status Error Code */
  374.                                         /* that makes sense */
  375. }
  376.  
  377.