home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bbs / may94 / disk / cdrom / amicdrom.lha / AmiCDROM / cdrom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-17  |  15.3 KB  |  601 lines

  1. /* cdrom.c:
  2.  *
  3.  * Basic interaction with the CDROM drive.
  4.  *
  5.  * ----------------------------------------------------------------------
  6.  * This code is (C) Copyright 1993,1994 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.  * 17-Feb-94   fmu   Added support for Toshiba 4101.
  14.  * 06-Feb-94   dmb   - Fixed bug in Test_Unit_Ready() trackdisk support.
  15.  *                   - Fixed bug in Open_CDROM (size of request)
  16.  *                   - Added function Clear_Sector_Buffers().
  17.  * 01-Jan-94   fmu   Added function Data_Tracks() for multisession support.
  18.  * 11-Dec-93   fmu   - Memory type can now be chosen by the user.
  19.  *                   - Addional parameter p_direction for Do_SCSI_Command().
  20.  *                   - Start_Play_Audio() now plays all tracks.
  21.  *                   - Mode_Select() instead of Select_XA_Mode().
  22.  *                   - Support for CDROM drives with 512, 1024 or 2048 bytes
  23.  *                     per block.
  24.  * 06-Dec-93   fmu   New drive type DRIVE_SCSI_2.
  25.  * 09-Nov-93   fmu   Added Select_XA_Mode.
  26.  * 23-Oct-93   fmu   Open_CDROM now returns an error code that tell what
  27.  *                   went wrong.
  28.  * 09-Oct-93   fmu   SAS/C support added.
  29.  * 03-Oct-93   fmu   New buffering algorithm.
  30.  * 27-Sep-93   fmu   Added support for multi-LUN devices.
  31.  * 24-Sep-93   fmu   - SCSI buffers may now reside in fast or chip memory.
  32.  *                   - TD_CHANGESTATE instead of CMD_READ in Test_Unit_Ready
  33.  */
  34.  
  35. #include <string.h>
  36.  
  37. #include <clib/exec_protos.h>
  38. #include <clib/alib_protos.h>
  39.  
  40. #ifdef AZTEC_C
  41. #include <pragmas/exec_lib.h>
  42. #endif
  43. #ifdef LATTICE
  44. #include <pragmas/exec_pragmas.h>
  45. #endif
  46. #if defined (_DCC) && defined (REGISTERED)
  47. #include <pragmas/exec_pragmas.h>
  48. extern struct Library *SysBase;
  49. #endif
  50.  
  51. #include <devices/trackdisk.h>
  52.  
  53. #include <limits.h>
  54.  
  55. #include "cdrom.h"
  56.  
  57. int g_cdrom_errno;
  58. int g_ignore_blocklength = FALSE;
  59.  
  60. void Determine_Drive_Type (CDROM *p_cd)
  61. {
  62.   t_inquiry_data data;
  63.   char buf[33];
  64.   
  65.   p_cd->drive_type = DRIVE_ANY;
  66.  
  67.   if (!Inquire (p_cd, &data))
  68.     return;
  69.  
  70.   if ((data.version & 0x7) >= 2)
  71.     p_cd->drive_type = DRIVE_SCSI_2;
  72.  
  73.   if (strncmp (data.vendor, "TOSHIBA", 7) == 0) {
  74.     memcpy (buf, data.product, 32);
  75.     buf[32] = 0;
  76.     if (strstr (buf, "3401") || strstr (buf, "4101"))
  77.       p_cd->drive_type = DRIVE_TOSHIBA_3401;
  78.   }
  79. }
  80.  
  81. CDROM *Open_CDROM (char *p_device, int p_scsi_id, int p_use_trackdisk,
  82.            unsigned long p_memory_type,
  83.            int p_std_buffers, int p_file_buffers)
  84. {
  85.   CDROM *cd;
  86.   int i;
  87.   int bufs = p_std_buffers + p_file_buffers + 1;
  88.   
  89.   g_cdrom_errno = CDROMERR_NO_MEMORY;
  90.  
  91.   cd = AllocMem (sizeof (CDROM),
  92.                MEMF_PUBLIC | MEMF_CLEAR | p_memory_type);
  93.   if (!cd)
  94.     return NULL;
  95.  
  96.   cd->std_buffers = p_std_buffers;
  97.   cd->file_buffers = p_file_buffers;
  98.  
  99.   cd->buffer_data = AllocMem (SCSI_BUFSIZE * bufs + 15,
  100.                     MEMF_PUBLIC | p_memory_type);
  101.   if (!cd->buffer_data) {
  102.     Cleanup_CDROM (cd);
  103.     return NULL;
  104.   }
  105.  
  106.   cd->buffers = AllocMem (sizeof (unsigned char *) * bufs, MEMF_PUBLIC);
  107.   if (!cd->buffers) {
  108.     Cleanup_CDROM (cd);
  109.     return NULL;
  110.   }
  111.   
  112.   cd->current_sectors = AllocMem (sizeof (long) * bufs, MEMF_PUBLIC);
  113.   if (!cd->current_sectors) {
  114.     Cleanup_CDROM (cd);
  115.     return NULL;
  116.   }
  117.  
  118.   cd->last_used = AllocMem (sizeof (unsigned long) * p_std_buffers,
  119.                   MEMF_PUBLIC | MEMF_CLEAR);
  120.   if (!cd->last_used) {
  121.     Cleanup_CDROM (cd);
  122.     return NULL;
  123.   }
  124.   
  125.   /* make the buffer quad-word aligned. This greatly helps 
  126.    * performance on '040-powered systems with DMA SCSI
  127.    * controllers.
  128.    */
  129.  
  130.   cd->buffers[0] = (UBYTE *)(((ULONG)cd->buffer_data + 15) & ~15);
  131.  
  132.   for (i=1; i<bufs; i++)
  133.     cd->buffers[i] = cd->buffers[0] + i * SCSI_BUFSIZE;
  134.  
  135.   cd->port = CreateMsgPort ();
  136.   if (!cd->port) {
  137.     g_cdrom_errno = CDROMERR_MSGPORT;
  138.     Cleanup_CDROM (cd);
  139.     return NULL;
  140.   }
  141.  
  142.   cd->scsireq = CreateIORequest (cd->port, sizeof (struct IOExtTD));
  143.   if (!cd->scsireq) {
  144.     g_cdrom_errno = CDROMERR_IOREQ;
  145.     Cleanup_CDROM (cd);
  146.     return NULL;
  147.   }
  148.  
  149.   if (OpenDevice ((UBYTE *) p_device, p_scsi_id,
  150.                   (struct IORequest *) cd->scsireq, 0)) {
  151.     g_cdrom_errno = CDROMERR_DEVICE;
  152.     Cleanup_CDROM (cd);
  153.     return NULL;
  154.   }
  155.  
  156.   cd->device_open = TRUE;
  157.  
  158.   for (i=0; i<bufs; i++)
  159.     cd->current_sectors[i] = -1;
  160.  
  161.   cd->use_trackdisk = p_use_trackdisk;
  162.   cd->t_changeint = -1;
  163.   cd->t_changeint2 = -2;
  164.  
  165.   /* The LUN is the 2nd digit of the SCSI id number: */
  166.   cd->lun = (p_scsi_id / 10) % 10;
  167.  
  168.   /* 'tick' is incremented every time a sector is accessed. */
  169.   cd->tick = 0;
  170.  
  171.   g_cdrom_errno = 0;
  172.  
  173.   Determine_Drive_Type (cd);
  174.  
  175.   if (g_ignore_blocklength) {
  176.     cd->block_length = 0;
  177.     cd->blocking_factor = 0;
  178.   } else {
  179.     cd->block_length = Block_Length (cd);
  180.     switch (cd->block_length) {
  181.     case 2048:
  182.       cd->blocking_factor = 0;
  183.       break;
  184.     case 1024:
  185.       cd->blocking_factor = 1;
  186.       break;
  187.     case 512:
  188.       cd->blocking_factor = 2;
  189.       break;
  190.     case 0:
  191.       cd->blocking_factor = 0;
  192.       break;
  193.     default:
  194.       g_cdrom_errno = CDROMERR_BLOCKSIZE;
  195.       Cleanup_CDROM (cd);
  196.       return NULL;
  197.     }
  198.   }
  199.  
  200.   return cd;
  201. }
  202.  
  203. int Do_SCSI_Command (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
  204.              unsigned char *p_command, int p_length, int p_direction)
  205. {
  206.   int bufs = p_cd->std_buffers + p_cd->file_buffers + 1;
  207.  
  208.   p_cd->scsireq->io_Length   = sizeof (struct SCSICmd);
  209.   p_cd->scsireq->io_Data     = (APTR) &p_cd->cmd;
  210.   p_cd->scsireq->io_Command  = HD_SCSICMD;
  211.  
  212.   p_cd->cmd.scsi_Data        = (UWORD *) p_buf;
  213.   p_cd->cmd.scsi_Length      = p_buf_length;
  214.   p_cd->cmd.scsi_Flags       = SCSIF_AUTOSENSE | p_direction;
  215.   p_cd->cmd.scsi_SenseData   = (UBYTE *) p_cd->sense;
  216.   p_cd->cmd.scsi_SenseLength = 18;
  217.   p_cd->cmd.scsi_SenseActual = 0;
  218.   p_cd->cmd.scsi_Command     = (UBYTE *) p_command;
  219.   p_cd->cmd.scsi_CmdLength   = p_length;
  220.  
  221.   p_command[1] |= p_cd->lun << 5;
  222.  
  223.   DoIO ((struct IORequest *) p_cd->scsireq);
  224.   if (p_cd->cmd.scsi_Status) {
  225.     int i;
  226.     for (i=0; i<bufs; i++)
  227.       p_cd->current_sectors[i] = -1;
  228.     return 0;
  229.   } else
  230.     return 1;
  231. }
  232.  
  233. int Read_From_Drive (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
  234.              long p_sector, int p_number_of_sectors)
  235. {
  236.   static unsigned char cmd[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  237.   int bufs = p_cd->std_buffers + p_cd->file_buffers + 1;
  238.  
  239. #ifdef DEBUG_SECTORS
  240.   extern void *dbprintf (char *, ...);
  241.  
  242.   if (p_number_of_sectors == 1)
  243.     dbprintf ("[%ld]", p_sector);
  244.   else
  245.     dbprintf ("[%ld-%ld]", p_sector, p_sector + p_number_of_sectors - 1);
  246. #endif
  247.  
  248.   if (p_cd->use_trackdisk) {
  249.     p_cd->scsireq->io_Length   = 2048 * p_number_of_sectors;
  250.     p_cd->scsireq->io_Data     = (APTR) p_buf;
  251.     p_cd->scsireq->io_Offset   = (ULONG) p_sector * 2048;
  252.     p_cd->scsireq->io_Command  = CMD_READ;
  253.  
  254.     DoIO ((struct IORequest *) p_cd->scsireq);
  255.     if (p_cd->scsireq->io_Error) {
  256.       int i;
  257.       for (i=0; i<bufs; i++)
  258.         p_cd->current_sectors[i] = -1;
  259.       return 0;
  260.     } else
  261.       return 1;
  262.   } else {
  263.     long sector = p_sector << p_cd->blocking_factor;
  264.     cmd[5] = sector & 0xff;
  265.     cmd[4] = (sector >> 8) & 0xff;
  266.     cmd[3] = (sector >> 16) & 0x1f;
  267.  
  268.     cmd[8] = p_number_of_sectors << p_cd->blocking_factor;
  269.  
  270.     return Do_SCSI_Command (p_cd, p_buf, p_buf_length, cmd, sizeof (cmd),
  271.                     SCSIF_READ);
  272.   }
  273. }
  274.  
  275. /* Read one sector from the CDROM drive.
  276.  */
  277.  
  278. int Read_Sector (CDROM *p_cd, long p_sector)
  279. {
  280.   int status;
  281.   int i;
  282.   int maxbuf = p_cd->std_buffers;
  283.   int loc;
  284.  
  285.   p_cd->tick++;
  286.  
  287.   for (i=0; i<maxbuf; i++)
  288.     if (p_cd->current_sectors[i] == p_sector) {
  289.       p_cd->buffer = p_cd->buffers[i];
  290.       p_cd->last_used[i] = p_cd->tick;
  291.       return 1;
  292.     }
  293.  
  294.   /* find an empty buffer position: */
  295.   for (loc=0; loc<maxbuf; loc++)
  296.     if (p_cd->current_sectors[loc] == -1)
  297.       break;
  298.  
  299.   if (loc==maxbuf) {
  300.     /* no free buffer position; remove the buffer that is unused
  301.        for the longest time: */
  302.     unsigned long oldest_tick = ULONG_MAX;
  303.     unsigned long tick;
  304.  
  305.     for (loc=0, i=0; i<maxbuf; i++) {
  306.       tick = p_cd->last_used[i];
  307.       if (tick < oldest_tick)
  308.         loc = i, oldest_tick = tick;
  309.     }
  310.   }
  311.  
  312.   status = Read_From_Drive (p_cd, p_cd->buffers[loc], SCSI_BUFSIZE,
  313.                   p_sector, 1);
  314.   if (status) {
  315.     p_cd->current_sectors[loc] = p_sector;
  316.     p_cd->buffer = p_cd->buffers[loc];
  317.     p_cd->last_used[loc] = p_cd->tick;
  318.   }
  319.  
  320.   return status;
  321. }
  322.  
  323. /* Read_Contiguous_Sectors uses the 'file buffers' instead of the
  324.  * 'standard buffers'. Additionaly, more than one sector may be read
  325.  * with a single SCSI command. This may cause a substantial increase
  326.  * in speed when reading large files.
  327.  */
  328.  
  329. int Read_Contiguous_Sectors (CDROM *p_cd, long p_sector, long p_last_sector)
  330. {
  331.   int status;
  332.   int i;
  333.   int maxbuf = p_cd->std_buffers + p_cd->file_buffers;
  334.   int len;
  335.  
  336.   for (i=p_cd->std_buffers; i<maxbuf; i++)
  337.     if (p_cd->current_sectors[i] == p_sector) {
  338.       p_cd->buffer = p_cd->buffers[i];
  339.       return 1;
  340.     }
  341.  
  342.   if (p_last_sector <= p_sector)
  343.     len = 1;
  344.   else {
  345.     len = p_last_sector - p_sector + 1;
  346.     if (len > p_cd->file_buffers)
  347.       len = p_cd->file_buffers;
  348.     if (len > 255)
  349.       len = 255;
  350.   }
  351.  
  352.   status = Read_From_Drive (p_cd, p_cd->buffers[p_cd->std_buffers],
  353.                   SCSI_BUFSIZE * len, p_sector, len);
  354.   if (status) {
  355.     long sector = p_sector;
  356.     for (i=p_cd->std_buffers; len; i++, len--)
  357.       p_cd->current_sectors[i] = sector++;
  358.     p_cd->buffer = p_cd->buffers[p_cd->std_buffers];
  359.   }
  360.  
  361.   return status;
  362. }
  363.  
  364. int Test_Unit_Ready (CDROM *p_cd)
  365. {
  366.   if (p_cd->use_trackdisk) {
  367.     p_cd->scsireq->io_Command = TD_CHANGENUM;
  368.     if (!DoIO ((struct IORequest *) p_cd->scsireq)) {
  369.       if (p_cd->scsireq->io_Error==0)
  370.         p_cd->t_changeint = p_cd->scsireq->io_Actual;
  371.     }
  372.     p_cd->scsireq->io_Command = TD_CHANGESTATE;
  373.     if (!DoIO ((struct IORequest *) p_cd->scsireq)) {
  374.       if (p_cd->scsireq->io_Error==0 &&
  375.           p_cd->scsireq->io_Actual==0)
  376.         return TRUE;
  377.     }
  378.     return FALSE;
  379.   } else {
  380.     int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  381.     static unsigned char cmd[6] = { 0, 0, 0, 0, 0, 0 };
  382.  
  383.     return Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], SCSI_BUFSIZE,
  384.                     cmd, 6, SCSIF_READ);
  385.   }
  386. }
  387.  
  388. int Is_XA_Mode_Disk (CDROM *p_cd)
  389. {
  390.   static unsigned char cmd[10] = { 0xC7, 3, 0, 0, 0, 0, 0, 0, 0, 0 };
  391.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  392.  
  393.   if (!Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], 4,
  394.               cmd, 10, SCSIF_READ))
  395.     return FALSE;
  396.  
  397.   return *(p_cd->buffers[dummy_buf]) == 0x20;
  398. }
  399.  
  400. int Mode_Select (CDROM *p_cd, int p_mode, int p_block_length)
  401. {
  402.   static unsigned char cmd[6] = { 0x15, 0x10, 0, 0, 12, 0 };
  403.   static unsigned char mode[12] = { 0, 0, 0, 8,
  404.                     0, 0, 0, 0, 0, 0, 0, 0 };
  405.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  406.  
  407.   if (p_cd->use_trackdisk)
  408.     return FALSE;
  409.  
  410.   p_cd->block_length = p_block_length;
  411.   switch (p_cd->block_length) {
  412.   case 2048:
  413.     p_cd->blocking_factor = 0;
  414.     break;
  415.   case 1024:
  416.     p_cd->blocking_factor = 1;
  417.     break;
  418.   case 512:
  419.     p_cd->blocking_factor = 2;
  420.     break;
  421.   }
  422.  
  423.   mode[4] = p_mode;
  424.   mode[9] = p_block_length >> 16;
  425.   mode[10] = (p_block_length >> 8) & 0xff;
  426.   mode[11] = p_block_length & 0xff;
  427.  
  428.   memcpy (p_cd->buffers[dummy_buf], mode, sizeof (mode));
  429.   return Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], sizeof (mode),
  430.                 cmd, 6, SCSIF_WRITE);
  431. }
  432.  
  433. int Inquire (CDROM *p_cd, t_inquiry_data *p_data)
  434. {
  435.   static unsigned char cmd[6] = { 0x12, 0, 0, 0, 96, 0 };
  436.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  437.   
  438.   if (p_cd->use_trackdisk)
  439.     return FALSE;
  440.  
  441.   if (!Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], 96,
  442.               cmd, 6, SCSIF_READ))
  443.     return FALSE;
  444.   
  445.   memcpy (p_data, p_cd->buffers[dummy_buf], sizeof (*p_data));
  446.   return 1;
  447. }
  448.  
  449. #define TOC_SIZE 804
  450.  
  451. t_toc_data *Read_TOC (CDROM *p_cd, t_toc_header *p_toc_header)
  452. {
  453.   static unsigned char cmd[10] = { 0x43, 0, 0, 0, 0, 0, 0,
  454.                      TOC_SIZE >> 8, TOC_SIZE & 0xff, 0 };
  455.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  456.  
  457.   if (p_cd->use_trackdisk)
  458.     return NULL;
  459.  
  460.   if (!Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], TOC_SIZE,
  461.               cmd, 10, SCSIF_READ))
  462.     return NULL;
  463.  
  464.   memcpy (p_toc_header, p_cd->buffers[dummy_buf], sizeof (*p_toc_header));
  465.   return (t_toc_data *) (p_cd->buffers[dummy_buf] + 4);
  466. }
  467.  
  468. int Has_Audio_Tracks (CDROM *p_cd)
  469. {
  470.   t_toc_header hdr;
  471.   t_toc_data *toc;
  472.   int i, len;
  473.   
  474.   if (!(toc = Read_TOC (p_cd, &hdr)))
  475.     return FALSE;
  476.  
  477.   len = hdr.length / 8;
  478.   for (i=0; i<len; i++) {
  479.     if (toc[i].track_number != 0xAA &&
  480.         !(toc[i].flags & 4))
  481.       return toc[i].track_number;
  482.   }
  483.   return FALSE;
  484. }
  485.  
  486. /*
  487.  * Create a buffer containing the start addresses of all data tracks
  488.  * on the disk.
  489.  *
  490.  * Returns:
  491.  *  number of tracks or -1 on error.
  492.  */
  493.  
  494. int Data_Tracks (CDROM *p_cd, unsigned long** p_buf)
  495. {
  496.   int cnt=0;
  497.   t_toc_header hdr;
  498.   t_toc_data *toc;
  499.   int i, j, len;
  500.   
  501.   if (!(toc = Read_TOC (p_cd, &hdr)))
  502.     return -1;
  503.  
  504.   len = hdr.length / 8;
  505.  
  506.   /* count number of data tracks: */
  507.   for (i=0; i<len; i++)
  508.     if (toc[i].track_number != 0xAA && (toc[i].flags & 4))
  509.       cnt++;
  510.  
  511.   if (cnt == 0)
  512.     return 0;
  513.  
  514.   /* allocate memory for output buffer: */
  515.   *p_buf = (unsigned long*) AllocVec (cnt * sizeof (unsigned long*),
  516.                         MEMF_PUBLIC);
  517.   if (!*p_buf)
  518.     return -1;
  519.  
  520.   /* fill output buffer: */
  521.   for (i=0, j=0; i<len; i++)
  522.     if (toc[i].track_number != 0xAA && (toc[i].flags & 4))
  523.       (*p_buf)[j++] = toc[i].address;
  524.  
  525.   return cnt;
  526. }
  527.  
  528. int Start_Play_Audio (CDROM *p_cd)
  529. {
  530.   static unsigned char cmd[10] = { 0x48, 0, 0, 0, 0, 1, 0, 99, 99, 0 };
  531.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  532.  
  533.   if (p_cd->use_trackdisk || p_cd->drive_type == DRIVE_ANY)
  534.     return FALSE;
  535.  
  536.   cmd[4] = Has_Audio_Tracks (p_cd);
  537.  
  538.   return Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], 0,
  539.                     cmd, 10, SCSIF_WRITE);
  540. }
  541.  
  542. int Stop_Play_Audio (CDROM *p_cd)
  543. {
  544.   static unsigned char cmd[6] = { 0x1B, 0, 0, 0, 0, 0 };
  545.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  546.  
  547.   if (p_cd->use_trackdisk || p_cd->drive_type == DRIVE_ANY)
  548.     return FALSE;
  549.  
  550.   return Do_SCSI_Command (p_cd, p_cd->buffers[dummy_buf], 0,
  551.                     cmd, 6, SCSIF_WRITE);
  552. }
  553.  
  554. int Block_Length (CDROM *p_cd)
  555. {
  556.   static unsigned char cmd[6] = { 0x1A, 0, 1, 0, 100, 0 };
  557.   int dummy_buf = p_cd->std_buffers + p_cd->file_buffers;
  558.   unsigned char *buf = p_cd->buffers[dummy_buf];
  559.  
  560.   if (p_cd->use_trackdisk)
  561.     return 0;
  562.   
  563.   if (!Do_SCSI_Command (p_cd, buf, 100,    cmd, 6, SCSIF_READ))
  564.     return 0;
  565.  
  566.   if (buf[3] == 0)
  567.     return 0;
  568.   
  569.   return (buf[9]<<16) + (buf[10]<<8) + buf[11];
  570. }
  571.  
  572. void Cleanup_CDROM (CDROM *p_cd)
  573. {
  574.   int bufs = p_cd->std_buffers + p_cd->file_buffers + 1;
  575.  
  576.   if (p_cd->device_open)
  577.     CloseDevice ((struct IORequest *) p_cd->scsireq);
  578.   if (p_cd->scsireq)
  579.     DeleteIORequest (p_cd->scsireq);
  580.   if (p_cd->port)
  581.     DeleteMsgPort (p_cd->port);
  582.   if (p_cd->last_used)
  583.     FreeMem (p_cd->last_used, sizeof (unsigned long) * p_cd->std_buffers);
  584.   if (p_cd->current_sectors)
  585.     FreeMem (p_cd->current_sectors, sizeof (long) * bufs);
  586.   if (p_cd->buffers)
  587.     FreeMem (p_cd->buffers, sizeof (unsigned char *) * bufs);
  588.   if (p_cd->buffer_data)
  589.     FreeMem (p_cd->buffer_data, SCSI_BUFSIZE * bufs + 15);
  590.   FreeMem (p_cd, sizeof (CDROM));
  591. }
  592.  
  593. void Clear_Sector_Buffers (CDROM *p_cd)
  594. {
  595.   int i;
  596.   int bufs = p_cd->std_buffers + p_cd->file_buffers + 1;
  597.  
  598.   for (i=0; i<bufs; i++)
  599.     p_cd->current_sectors[i] = -1;
  600. }
  601.