home *** CD-ROM | disk | FTP | other *** search
- /* cdrom.c:
- *
- * Basic interaction with the CDROM drive.
- *
- * ----------------------------------------------------------------------
- * This code is (C) Copyright 1993 by Frank Munkert.
- * All rights reserved.
- * This software may be freely distributed and redistributed for
- * non-commercial purposes, provided this notice is included.
- * ----------------------------------------------------------------------
- * History:
- *
- * 27-Sep-93 fmu - Added support for multi-LUN devices.
- * 24-Sep-93 fmu - SCSI buffers may now reside in fast or chip memory.
- * - TD_CHANGESTATE instead of CMD_READ in Test_Unit_Ready
- */
-
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
-
- #include <devices/trackdisk.h>
-
- #include "cdrom.h"
-
- CDROM *Open_CDROM (char *p_device, int p_scsi_id, int p_use_trackdisk,
- int p_use_fast_mem)
- {
- CDROM *cd;
- int i;
-
- cd = AllocMem (sizeof (CDROM),
- MEMF_PUBLIC | MEMF_CLEAR |
- (p_use_fast_mem ? MEMF_FAST : MEMF_CHIP));
- if (!cd)
- return NULL;
-
- cd->buffer_data = AllocMem (SCSI_BUFSIZE * SCSI_BUFFERS + 15,
- MEMF_PUBLIC |
- (p_use_fast_mem ? MEMF_FAST : MEMF_CHIP));
- if (!cd->buffer_data) {
- FreeMem (cd, sizeof (CDROM));
- return NULL;
- }
-
- /* make the buffer quad-word aligned. This greatly helps
- * performance on '040-powered systems with DMA SCSI
- * controllers.
- */
-
- cd->buffers[0] = (UBYTE *)(((ULONG)cd->buffer_data + 15) & ~15);
-
- for (i=1; i<SCSI_BUFFERS; i++)
- cd->buffers[i] = cd->buffers[0] + i * SCSI_BUFSIZE;
-
- cd->port = CreateMsgPort ();
- if (!cd->port) {
- FreeMem (cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
- FreeMem (cd, sizeof (CDROM));
- return NULL;
- }
-
- cd->scsireq = CreateIORequest (cd->port, sizeof (struct IOStdReq));
- if (!cd->scsireq) {
- DeletePort (cd->port);
- FreeMem (cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
- FreeMem (cd, sizeof (CDROM));
- return NULL;
- }
-
- if (OpenDevice ((UBYTE *) p_device, p_scsi_id,
- (struct IORequest *) cd->scsireq, 0)) {
- DeleteIORequest (cd->scsireq);
- DeleteMsgPort (cd->port);
- FreeMem (cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
- FreeMem (cd, sizeof (CDROM));
- return NULL;
- }
-
- for (i=0; i<SCSI_BUFFERS; i++)
- cd->current_sectors[i] = -1;
-
- cd->use_trackdisk = p_use_trackdisk;
-
- /* The LUN is the 2nd digit of the SCSI id number: */
- cd->lun = (p_scsi_id / 10) % 10;
-
- return cd;
- }
-
- int Do_SCSI_Command (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
- unsigned char *p_command, int p_length)
- {
- p_cd->scsireq->io_Length = sizeof (struct SCSICmd);
- p_cd->scsireq->io_Data = (APTR) &p_cd->cmd;
- p_cd->scsireq->io_Command = HD_SCSICMD;
-
- p_cd->cmd.scsi_Data = (UWORD *) p_buf;
- p_cd->cmd.scsi_Length = p_buf_length;
- p_cd->cmd.scsi_Flags = SCSIF_AUTOSENSE | SCSIF_READ;
- p_cd->cmd.scsi_SenseData = (UBYTE *) p_cd->sense;
- p_cd->cmd.scsi_SenseLength = 18;
- p_cd->cmd.scsi_SenseActual = 0;
- p_cd->cmd.scsi_Command = (UBYTE *) p_command;
- p_cd->cmd.scsi_CmdLength = p_length;
-
- p_command[1] |= p_cd->lun << 5;
-
- DoIO ((struct IORequest *) p_cd->scsireq);
- if (p_cd->cmd.scsi_Status) {
- int i;
- for (i=0; i<SCSI_BUFFERS; i++)
- p_cd->current_sectors[i] = -1;
- return 0;
- } else
- return 1;
- }
-
- int Read_From_Drive (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
- long p_sector, int p_number_of_sectors)
- {
- static unsigned char cmd[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- if (p_cd->use_trackdisk) {
- p_cd->scsireq->io_Length = 2048 * p_number_of_sectors;
- p_cd->scsireq->io_Data = (APTR) p_buf;
- p_cd->scsireq->io_Offset = (ULONG) p_sector * 2048;
- p_cd->scsireq->io_Command = CMD_READ;
-
- DoIO ((struct IORequest *) p_cd->scsireq);
- if (p_cd->scsireq->io_Error) {
- int i;
- for (i=0; i<SCSI_BUFFERS; i++)
- p_cd->current_sectors[i] = -1;
- return 0;
- } else
- return 1;
- } else {
- cmd[5] = p_sector & 0xff;
- cmd[4] = (p_sector >> 8) & 0xff;
- cmd[3] = (p_sector >> 16) & 0x1f;
-
- cmd[8] = p_number_of_sectors;
-
- return Do_SCSI_Command (p_cd, p_buf, p_buf_length, cmd, sizeof (cmd));
- }
- }
-
- int Read_Sector_With_Lookahead (CDROM *p_cd, long p_sector, long p_last_sector)
- {
- int status;
- int i;
- static int loc = 0;
-
- for (i=0; i<SCSI_BUFFERS; i++)
- if (p_cd->current_sectors[i] == p_sector) {
- p_cd->buffer = p_cd->buffers[i];
- return 1;
- }
-
- if (p_sector >= p_last_sector) {
-
- loc++;
- if (loc == SCSI_BUFFERS)
- loc=0;
-
- status = Read_From_Drive (p_cd, p_cd->buffers[loc], SCSI_BUFSIZE,
- p_sector, 1);
- if (status) {
- p_cd->current_sectors[loc] = p_sector;
- p_cd->buffer = p_cd->buffers[loc];
- }
-
- } else {
-
- int len = p_last_sector - p_sector + 1;
-
- if (len > SCSI_BUFFERS)
- len = SCSI_BUFFERS;
-
- status = Read_From_Drive (p_cd, p_cd->buffers[0], SCSI_BUFSIZE * len,
- p_sector, len);
- if (status) {
- for (i=0; i<len; i++)
- p_cd->current_sectors[i] = p_sector + i;
- p_cd->buffer = p_cd->buffers[0];
- }
-
- }
-
- return status;
- }
-
- int Read_Sector (CDROM *p_cd, long p_sector)
- {
- return Read_Sector_With_Lookahead (p_cd, p_sector, p_sector);
- }
-
- int Test_Unit_Ready (CDROM *p_cd)
- {
- p_cd->current_sectors[0] = -1;
- if (p_cd->use_trackdisk) {
- p_cd->scsireq->io_Command = TD_CHANGESTATE;
-
- if (!DoIO ((struct IORequest *) p_cd->scsireq)) {
- if (!p_cd->scsireq->io_Actual)
- return 1;
- }
- return 0;
- } else {
- static unsigned char cmd[6] = { 0, 0, 0, 0, 0, 0 };
-
- return Do_SCSI_Command (p_cd, p_cd->buffers[0], SCSI_BUFSIZE, cmd, 6);
- }
- }
-
- void Cleanup_CDROM (CDROM *p_cd)
- {
- CloseDevice ((struct IORequest *) p_cd->scsireq);
- DeleteIORequest (p_cd->scsireq);
- DeleteMsgPort (p_cd->port);
- FreeMem (p_cd->buffer_data, SCSI_BUFSIZE * SCSI_BUFFERS + 15);
- FreeMem (p_cd, sizeof (CDROM));
- }
-