home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 5
/
FreshFish_July-August1994.bin
/
new
/
disk
/
cdrom
/
amicdrom
/
cdrom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-18
|
16KB
|
613 lines
/* cdrom.c:
*
* Basic interaction with the CDROM drive.
*
* ----------------------------------------------------------------------
* This code is (C) Copyright 1993,1994 by Frank Munkert.
* All rights reserved.
* This software may be freely distributed and redistributed for
* non-commercial purposes, provided this notice is included.
* ----------------------------------------------------------------------
* History:
*
* 18-May-94 fmu New drive model: MODEL_CDU_8002 (= Apple CD 150).
* 17-May-94 fmu Sense length 20 instead of 18 (needed by ALF controller).
* 17-Feb-94 fmu Added support for Toshiba 4101.
* 06-Feb-94 dmb - Fixed bug in Test_Unit_Ready() trackdisk support.
* - Fixed bug in Open_CDROM (size of request)
* - Added function Clear_Sector_Buffers().
* 01-Jan-94 fmu Added function Data_Tracks() for multisession support.
* 11-Dec-93 fmu - Memory type can now be chosen by the user.
* - Addional parameter p_direction for Do_SCSI_Command().
* - Start_Play_Audio() now plays all tracks.
* - Mode_Select() instead of Select_XA_Mode().
* - Support for CDROM drives with 512, 1024 or 2048 bytes
* per block.
* 06-Dec-93 fmu New drive type DRIVE_SCSI_2.
* 09-Nov-93 fmu Added Select_XA_Mode.
* 23-Oct-93 fmu Open_CDROM now returns an error code that tell what
* went wrong.
* 09-Oct-93 fmu SAS/C support added.
* 03-Oct-93 fmu New buffering algorithm.
* 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 <string.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#ifdef AZTEC_C
#include <pragmas/exec_lib.h>
#endif
#ifdef LATTICE
#include <pragmas/exec_pragmas.h>
#endif
#if defined (_DCC) && defined (REGISTERED)
#include <pragmas/exec_pragmas.h>
extern struct Library *SysBase;
#endif
#include <devices/trackdisk.h>
#include <limits.h>
#include "cdrom.h"
int g_cdrom_errno;
int g_ignore_blocklength = FALSE;
void Determine_Drive_Type (CDROM *p_cd)
{
t_inquiry_data data;
char buf[33];
p_cd->scsi_compliance = 1;
p_cd->model = MODEL_ANY;
if (!Inquire (p_cd, &data))
return;
if ((data.version & 0x7) >= 2)
p_cd->scsi_compliance = 2;
if (strncmp (data.vendor, "TOSHIBA", 7) == 0) {
memcpy (buf, data.product, 32);
buf[32] = 0;
if (strstr (buf, "3401") || strstr (buf, "4101"))
p_cd->model = MODEL_TOSHIBA_3401;
} else if (strncmp (data.vendor, "SONY", 4) == 0) {
memcpy (buf, data.product, 32);
buf[32] = 0;
if (strstr (buf, "CDU-8002"))
p_cd->model = MODEL_CDU_8002;
}
}
CDROM *Open_CDROM (char *p_device, int p_scsi_id, int p_use_trackdisk,
unsigned long p_memory_type,
int p_std_buffers, int p_file_buffers)
{
CDROM *cd;
int i;
int bufs = p_std_buffers + p_file_buffers + 1;
g_cdrom_errno = CDROMERR_NO_MEMORY;
cd = AllocMem (sizeof (CDROM),
MEMF_PUBLIC | MEMF_CLEAR | p_memory_type);
if (!cd)
return NULL;
cd->std_buffers = p_std_buffers;
cd->file_buffers = p_file_buffers;
cd->buffer_data = AllocMem (SCSI_BUFSIZE * bufs + 15,
MEMF_PUBLIC | p_memory_type);
if (!cd->buffer_data) {
Cleanup_CDROM (cd);
return NULL;
}
cd->buffers = AllocMem (sizeof (unsigned char *) * bufs, MEMF_PUBLIC);
if (!cd->buffers) {
Cleanup_CDROM (cd);
return NULL;
}
cd->current_sectors = AllocMem (sizeof (long) * bufs, MEMF_PUBLIC);
if (!cd->current_sectors) {
Cleanup_CDROM (cd);
return NULL;
}
cd->last_used = AllocMem (sizeof (unsigned long) * p_std_buffers,
MEMF_PUBLIC | MEMF_CLEAR);
if (!cd->last_used) {
Cleanup_CDROM (cd);
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<bufs; i++)
cd->buffers[i] = cd->buffers[0] + i * SCSI_BUFSIZE;
cd->port = CreateMsgPort ();
if (!cd->port) {
g_cdrom_errno = CDROMERR_MSGPORT;
Cleanup_CDROM (cd);
return NULL;
}
cd->scsireq = CreateIORequest (cd->port, sizeof (struct IOExtTD));
if (!cd->scsireq) {
g_cdrom_errno = CDROMERR_IOREQ;
Cleanup_CDROM (cd);
return NULL;
}
if (OpenDevice ((UBYTE *) p_device, p_scsi_id,
(struct IORequest *) cd->scsireq, 0)) {
g_cdrom_errno = CDROMERR_DEVICE;
Cleanup_CDROM (cd);
return NULL;
}
cd->device_open = TRUE;
for (i=0; i<bufs; i++)
cd->current_sectors[i] = -1;
cd->use_trackdisk = p_use_trackdisk;
cd->t_changeint = -1;
cd->t_changeint2 = -2;
/* The LUN is the 2nd digit of the SCSI id number: */
cd->lun = (p_scsi_id / 10) % 10;
/* 'tick' is incremented every time a sector is accessed. */
cd->tick = 0;
g_cdrom_errno = 0;
Determine_Drive_Type (cd);
if (g_ignore_blocklength) {
cd->block_length = 0;
cd->blocking_factor = 0;
} else {
cd->block_length = Block_Length (cd);
switch (cd->block_length) {
case 2048:
cd->blocking_factor = 0;
break;
case 1024:
cd->blocking_factor = 1;
break;
case 512:
cd->blocking_factor = 2;
break;
case 0:
cd->blocking_factor = 0;
break;
default:
g_cdrom_errno = CDROMERR_BLOCKSIZE;
Cleanup_CDROM (cd);
return NULL;
}
}
return cd;
}
int Do_SCSI_Command (CDROM *p_cd, unsigned char *p_buf, long p_buf_length,
unsigned char *p_command, int p_length, int p_direction)
{
int bufs = p_cd->std_buffers + p_cd->file_buffers + 1;
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 | p_direction;
p_cd->cmd.scsi_SenseData = (UBYTE *) p_cd->sense;
p_cd->cmd.scsi_SenseLength = 20;
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<bufs; 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 };
int bufs = p_cd->std_buffers + p_cd->file_buffers + 1;
#ifdef DEBUG_SECTORS
extern void *dbprintf (char *, ...);
if (p_number_of_sectors == 1)
dbprintf ("[%ld]", p_sector);
else
dbprintf ("[%ld-%ld]", p_sector, p_sector + p_number_of_sectors - 1);
#endif
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<bufs; i++)
p_cd->current_sectors[i] = -1;
return 0;
} else
return 1;
} else {
long sector = p_sector << p_cd->blocking_factor;
cmd[5] = sector & 0xff;
cmd[4] = (sector >> 8) & 0xff;
cmd[3] = (sector >> 16) & 0x1f;
cmd[8] = p_number_of_sectors << p_cd->blocking_factor;
return Do_SCSI_Command (p_cd, p_buf, p_buf_length, cmd, sizeof (cmd),
SCSIF_READ);
}
}
/* Read one sector from the CDROM drive.
*/
int Read_Sector (CDROM *p_cd, long p_sector)
{
int status;
int i;
int maxbuf = p_cd->std_buffers;
int loc;
p_cd->tick++;
for (i=0; i<maxbuf; i++)
if (p_cd->current_sectors[i] == p_sector) {
p_cd->buffer = p_cd->buffers[i];
p_cd->last_used[i] = p_cd->tick;