home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / useful / dist / other / amicdrom / cdrom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-27  |  5.8 KB  |  224 lines

  1. /* cdrom.c:
  2.  *
  3.  * Basic interaction with the CDROM drive.
  4.  *
  5.  * ----------------------------------------------------------------------
  6.  * This code is (C) Copyright 1993 by Frank Munkert.
  7.  * All rights reserved.
  8.  * This software may be freely distributed and redistributed for
  9.  * non-commercial purposes, provided this notice is included.
  10.  * ----------------------------------------------------------------------
  11.  * History:
  12.  * 
  13.  * 27-Sep-93   fmu   - Added support for multi-LUN devices.
  14.  * 24-Sep-93   fmu   - SCSI buffers may now reside in fast or chip memory.
  15.  *                   - TD_CHANGESTATE instead of CMD_READ in Test_Unit_Ready
  16.  */
  17.  
  18. #include <clib/exec_protos.h>
  19. #include <clib/alib_protos.h>
  20.  
  21. #include <devices/trackdisk.h>
  22.  
  23. #include "cdrom.h"
  24.  
  25. CDROM *Open_CDROM (char *p_device, int p_scsi_id, int p_use_trackdisk,
  26.            int p_use_fast_mem)
  27. {
  28.   CDROM *cd;
  29.   int i;
  30.  
  31.   cd = AllocMem (sizeof (CDROM),
  32.                MEMF_PUBLIC | MEMF_CLEAR |
  33.          (p_use_fast_mem ? MEMF_FAST : MEMF_CHIP));
  34.   if (!cd)
  35.     return NULL;
  36.  
  37.   cd->buffer_data = AllocMem (SCSI_BUFSIZE * SCSI_BUFFERS + 15,
  38.                     MEMF_PUBLIC |
  39.                   (p_use_fast_mem ? MEMF_FAST : MEMF_CHIP));
  40.   if (!cd->buffer_data) {
  41.     FreeMem (cd, sizeof (CDROM));
  42.     return NULL;
  43.   }
  44.  
  45.   /* make the buffer quad-word aligned. This greatly helps 
  46.    * performance on '040-powered systems with DMA SCSI
  47.    * controllers.
  48.    */
  49.  
  50.   cd->buffers[0] = (UBYTE *)(((ULONG)cd->buffer_data + 15) & ~15);
  51.  
  52.   for (i=1; i<SCSI_BUFFERS; i++)
  53.     cd->buffers[i] = cd->buffers[0] + i * SCSI_BUFSIZE;
  54.  
  55.   cd->port = CreateMsgPort ();
  56.   if (!cd->port) {
  57.     FreeMem (cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
  58.     FreeMem (cd, sizeof (CDROM));
  59.     return NULL;
  60.   }
  61.  
  62.   cd->scsireq = CreateIORequest (cd->port, sizeof (struct IOStdReq));
  63.   if (!cd->scsireq) {
  64.     DeletePort (cd->port);
  65.     FreeMem (cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
  66.     FreeMem (cd, sizeof (CDROM));
  67.     return NULL;
  68.   }
  69.  
  70.   if (OpenDevice ((UBYTE *) p_device, p_scsi_id,
  71.                   (struct IORequest *) cd->scsireq, 0)) {
  72.     DeleteIORequest (cd->scsireq);
  73.     DeleteMsgPort (cd->port);
  74.     FreeMem (cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
  75.     FreeMem (cd, sizeof (CDROM));
  76.     return NULL;
  77.   }
  78.  
  79.   for (i=0; i<SCSI_BUFFERS; i++)
  80.     cd->current_sectors[i] = -1;
  81.   
  82.   cd->use_trackdisk = p_use_trackdisk;
  83.  
  84.   /* The LUN is the 2nd digit of the SCSI id number: */
  85.   cd->lun = (p_scsi_id / 10) % 10;
  86.  
  87.   return cd;
  88. }
  89.  
  90. int Do_SCSI_Command (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
  91.              unsigned char *p_command, int p_length)
  92. {
  93.   p_cd->scsireq->io_Length   = sizeof (struct SCSICmd);
  94.   p_cd->scsireq->io_Data     = (APTR) &p_cd->cmd;
  95.   p_cd->scsireq->io_Command  = HD_SCSICMD;
  96.  
  97.   p_cd->cmd.scsi_Data        = (UWORD *) p_buf;
  98.   p_cd->cmd.scsi_Length      = p_buf_length;
  99.   p_cd->cmd.scsi_Flags       = SCSIF_AUTOSENSE | SCSIF_READ;
  100.   p_cd->cmd.scsi_SenseData   = (UBYTE *) p_cd->sense;
  101.   p_cd->cmd.scsi_SenseLength = 18;
  102.   p_cd->cmd.scsi_SenseActual = 0;
  103.   p_cd->cmd.scsi_Command     = (UBYTE *) p_command;
  104.   p_cd->cmd.scsi_CmdLength   = p_length;
  105.  
  106.   p_command[1] |= p_cd->lun << 5;
  107.  
  108.   DoIO ((struct IORequest *) p_cd->scsireq);
  109.   if (p_cd->cmd.scsi_Status) {
  110.     int i;
  111.     for (i=0; i<SCSI_BUFFERS; i++)
  112.       p_cd->current_sectors[i] = -1;
  113.     return 0;
  114.   } else
  115.     return 1;
  116. }
  117.  
  118. int Read_From_Drive (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
  119.              long p_sector, int p_number_of_sectors)
  120. {
  121.   static unsigned char cmd[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  122.  
  123.   if (p_cd->use_trackdisk) {
  124.     p_cd->scsireq->io_Length   = 2048 * p_number_of_sectors;
  125.     p_cd->scsireq->io_Data     = (APTR) p_buf;
  126.     p_cd->scsireq->io_Offset   = (ULONG) p_sector * 2048;
  127.     p_cd->scsireq->io_Command  = CMD_READ;
  128.  
  129.     DoIO ((struct IORequest *) p_cd->scsireq);
  130.     if (p_cd->scsireq->io_Error) {
  131.       int i;
  132.       for (i=0; i<SCSI_BUFFERS; i++)
  133.         p_cd->current_sectors[i] = -1;
  134.       return 0;
  135.     } else
  136.       return 1;
  137.   } else {
  138.     cmd[5] = p_sector & 0xff;
  139.     cmd[4] = (p_sector >> 8) & 0xff;
  140.     cmd[3] = (p_sector >> 16) & 0x1f;
  141.  
  142.     cmd[8] = p_number_of_sectors;
  143.   
  144.     return Do_SCSI_Command (p_cd, p_buf, p_buf_length, cmd, sizeof (cmd));
  145.   }
  146. }
  147.  
  148. int Read_Sector_With_Lookahead (CDROM *p_cd, long p_sector, long p_last_sector)
  149. {
  150.   int status;
  151.   int i;
  152.   static int loc = 0;
  153.  
  154.   for (i=0; i<SCSI_BUFFERS; i++)
  155.     if (p_cd->current_sectors[i] == p_sector) {
  156.       p_cd->buffer = p_cd->buffers[i];
  157.       return 1;
  158.     }
  159.  
  160.   if (p_sector >= p_last_sector) {
  161.  
  162.     loc++;
  163.     if (loc == SCSI_BUFFERS)
  164.       loc=0;
  165.  
  166.     status = Read_From_Drive (p_cd, p_cd->buffers[loc], SCSI_BUFSIZE,
  167.                       p_sector, 1);
  168.     if (status) {
  169.       p_cd->current_sectors[loc] = p_sector;
  170.       p_cd->buffer = p_cd->buffers[loc];
  171.     }
  172.   
  173.   } else {
  174.  
  175.     int len = p_last_sector - p_sector + 1;
  176.     
  177.     if (len > SCSI_BUFFERS)
  178.       len = SCSI_BUFFERS;
  179.  
  180.     status = Read_From_Drive (p_cd, p_cd->buffers[0], SCSI_BUFSIZE * len,
  181.                       p_sector, len);
  182.     if (status) {
  183.       for (i=0; i<len; i++)
  184.         p_cd->current_sectors[i] = p_sector + i;
  185.       p_cd->buffer = p_cd->buffers[0];
  186.     }
  187.  
  188.   }
  189.  
  190.   return status;
  191. }
  192.  
  193. int Read_Sector (CDROM *p_cd, long p_sector)
  194. {
  195.   return Read_Sector_With_Lookahead (p_cd, p_sector, p_sector);
  196. }
  197.  
  198. int Test_Unit_Ready (CDROM *p_cd)
  199. {
  200.   p_cd->current_sectors[0] = -1;
  201.   if (p_cd->use_trackdisk) {
  202.     p_cd->scsireq->io_Command = TD_CHANGESTATE;
  203.  
  204.     if (!DoIO ((struct IORequest *) p_cd->scsireq)) {
  205.       if (!p_cd->scsireq->io_Actual)
  206.         return 1;
  207.     }
  208.     return 0;
  209.   } else {
  210.     static unsigned char cmd[6] = { 0, 0, 0, 0, 0, 0 };
  211.  
  212.     return Do_SCSI_Command (p_cd, p_cd->buffers[0], SCSI_BUFSIZE, cmd, 6);
  213.   }
  214. }
  215.  
  216. void Cleanup_CDROM (CDROM *p_cd)
  217. {
  218.   CloseDevice ((struct IORequest *) p_cd->scsireq);
  219.   DeleteIORequest (p_cd->scsireq);
  220.   DeleteMsgPort (p_cd->port);
  221.   FreeMem (p_cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
  222.   FreeMem (p_cd, sizeof (CDROM));
  223. }
  224.