cdda_device_name to struct cdrom_drive. This makes a number of hacks in various places superfluous and should fix the KDE multimedia issues. Bump revision. Recursive bump will follow, since the major version changed.
506 lines
13 KiB
Text
506 lines
13 KiB
Text
$NetBSD: patch-cg,v 1.8 2006/03/07 06:29:04 joerg Exp $
|
|
|
|
--- interface/scsi_interface.c.orig 2001-03-24 12:15:46.000000000 +1100
|
|
+++ interface/scsi_interface.c
|
|
@@ -23,6 +23,8 @@ static void tweak_SG_buffer(cdrom_drive
|
|
int table,reserved;
|
|
char buffer[256];
|
|
|
|
+#if !defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+#ifdef __linux__
|
|
/* maximum transfer size? */
|
|
if(ioctl(d->cdda_fd,SG_GET_RESERVED_SIZE,&reserved)){
|
|
/* Up, guess not. */
|
|
@@ -31,6 +33,10 @@ static void tweak_SG_buffer(cdrom_drive
|
|
}
|
|
|
|
if(ioctl(d->cdda_fd,SG_GET_SG_TABLESIZE,&table))table=1;
|
|
+#else
|
|
+ reserved = 32*1024; /* ? */
|
|
+ table = 1;
|
|
+#endif
|
|
{
|
|
int cur;
|
|
|
|
@@ -53,14 +59,24 @@ static void tweak_SG_buffer(cdrom_drive
|
|
cdmessage(d,buffer);
|
|
}
|
|
|
|
+#ifdef __linux__
|
|
/* Disable command queue; we don't need it, no reason to have it on */
|
|
reserved=0;
|
|
if(ioctl(d->cdda_fd,SG_SET_COMMAND_Q,&reserved)){
|
|
cdmessage(d,"\tCouldn't disable command queue! Continuing anyway...\n");
|
|
}
|
|
-
|
|
+#endif
|
|
+#else /* FreeBSD */
|
|
+ d->nsectors = 26; /* FreeBSD only supports 64K I/O transfer size */
|
|
+ d->bigbuff = d->nsectors * CD_FRAMESIZE_RAW;
|
|
+
|
|
+ sprintf(buffer,"\tSetting default read size to %d sectors (%d bytes).\n\n",
|
|
+ d->nsectors,d->nsectors*CD_FRAMESIZE_RAW);
|
|
+ cdmessage(d,buffer);
|
|
+#endif
|
|
}
|
|
|
|
+#ifdef __linux__
|
|
static void reset_scsi(cdrom_drive *d){
|
|
int arg;
|
|
d->enable_cdda(d,0);
|
|
@@ -74,6 +90,44 @@ static void reset_scsi(cdrom_drive *d){
|
|
d->enable_cdda(d,1);
|
|
}
|
|
|
|
+#elif defined(__NetBSD__)
|
|
+static void reset_scsi(cdrom_drive *d){
|
|
+ int arg;
|
|
+ d->enable_cdda(d,0);
|
|
+
|
|
+ cdmessage(d,"sending SCSI reset... ");
|
|
+ if(ioctl(d->cdda_fd,CDIOCRESET,&arg))
|
|
+ cdmessage(d,"FAILED: EBUSY\n");
|
|
+ else
|
|
+ cdmessage(d,"OK\n");
|
|
+
|
|
+ d->enable_cdda(d,1);
|
|
+}
|
|
+
|
|
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+static void reset_scsi(cdrom_drive *d) {
|
|
+ d->enable_cdda(d,0);
|
|
+
|
|
+ d->ccb->ccb_h.func_code = XPT_RESET_DEV;
|
|
+ d->ccb->ccb_h.timeout = 5000;
|
|
+
|
|
+ cdmessage(d, "sending SCSI reset... ");
|
|
+ if (cam_send_ccb(d->dev, d->ccb)) {
|
|
+ cdmessage(d, "error sending XPT_RESET_DEV CCB");
|
|
+ } else {
|
|
+
|
|
+ if (((d->ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) ||
|
|
+ ((d->ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))
|
|
+ cdmessage(d,"OK\n");
|
|
+ else
|
|
+ cdmessage(d,"FAILED\n");
|
|
+ }
|
|
+
|
|
+ d->enable_cdda(d,1);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef __linux__
|
|
static void clear_garbage(cdrom_drive *d){
|
|
fd_set fdset;
|
|
struct timeval tv;
|
|
@@ -104,21 +158,30 @@ static void clear_garbage(cdrom_drive *d
|
|
flag=1;
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
/* process a complete scsi command. */
|
|
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
|
|
static int handle_scsi_cmd(cdrom_drive *d,
|
|
unsigned int cmd_len,
|
|
unsigned int in_size,
|
|
unsigned int out_size,
|
|
|
|
- unsigned char bytefill,
|
|
+ unsigned int bfill,
|
|
int bytecheck){
|
|
+ unsigned char bytefill = bfill;
|
|
int status = 0;
|
|
+#ifdef __linux__
|
|
struct sg_header *sg_hd=(struct sg_header *)d->sg;
|
|
long writebytes=SG_OFF+cmd_len+in_size;
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ scsireq_t *sreq = (scsireq_t *)d->sg;
|
|
+#endif
|
|
|
|
/* generic scsi device services */
|
|
|
|
+#ifdef __linux__
|
|
/* clear out any possibly preexisting garbage */
|
|
clear_garbage(d);
|
|
|
|
@@ -224,11 +287,53 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
if(errno==0)errno=EIO;
|
|
return(TR_EREAD);
|
|
}
|
|
+#endif /* __linux__ */
|
|
|
|
- if(sg_hd->sense_buffer[0]){
|
|
+#ifdef __NetBSD__
|
|
+ if (in_size && out_size) {
|
|
+ warnx("handle_scsi_cmd: in and out is not supported");
|
|
+ abort();
|
|
+ }
|
|
+ memset(sreq, 0, sizeof(scsireq_t));
|
|
+ sreq->cmdlen = cmd_len;
|
|
+ memcpy(sreq->cmd, d->sg_buffer, cmd_len);
|
|
+ if (in_size) {
|
|
+ sreq->flags = SCCMD_WRITE;
|
|
+ sreq->databuf = d->sg_buffer + cmd_len;
|
|
+ sreq->datalen = in_size;
|
|
+ }
|
|
+ if (out_size) {
|
|
+ sreq->flags = SCCMD_READ;
|
|
+ sreq->databuf = d->sg_buffer;
|
|
+ sreq->datalen = out_size;
|
|
+ if(bytecheck)
|
|
+ memset(d->sg_buffer, bytefill, out_size);
|
|
+ }
|
|
+ sreq->senselen = SENSEBUFLEN;
|
|
+ sreq->timeout = 60000; /* 60s */
|
|
+
|
|
+ status = ioctl(d->cdda_fd, SCIOCCOMMAND, (void *) sreq);
|
|
+ if (status < 0)
|
|
+ return(TR_ILLEGAL);
|
|
+#endif
|
|
+
|
|
+#ifdef __linux__
|
|
+ if(sg_hd->sense_buffer[0])
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ if (sreq->sense[0])
|
|
+#endif
|
|
+ {
|
|
+#ifdef __linux__
|
|
char key=sg_hd->sense_buffer[2]&0xf;
|
|
char ASC=sg_hd->sense_buffer[12];
|
|
char ASCQ=sg_hd->sense_buffer[13];
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ char key = sreq->sense[2]&0xf;
|
|
+ char ASC = sreq->sense[12];
|
|
+ char ASCQ = sreq->sense[13];
|
|
+#endif
|
|
switch(key){
|
|
case 0:
|
|
if(errno==0)errno=EIO;
|
|
@@ -266,9 +371,20 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
commands still get through. Perhaps no data comes back even
|
|
though the target reports success? */
|
|
|
|
- if(bytecheck && in_size+cmd_len<out_size){
|
|
+#ifdef __linux__
|
|
+ if(bytecheck && in_size+cmd_len<out_size)
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ if(bytecheck && out_size)
|
|
+#endif
|
|
+ {
|
|
long i,flag=0;
|
|
+#ifdef __linux__
|
|
for(i=in_size;i<out_size;i++)
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ for(i=0;i<out_size;i++)
|
|
+#endif
|
|
if(d->sg_buffer[i]!=bytefill){
|
|
flag=1;
|
|
break;
|
|
@@ -284,6 +400,83 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
return(0);
|
|
}
|
|
|
|
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+static int handle_scsi_cmd(cdrom_drive *d,
|
|
+ unsigned int cmd_len,
|
|
+ unsigned int out_size,
|
|
+ unsigned int in_size,
|
|
+ unsigned char bytefill,
|
|
+ int bytecheck) {
|
|
+ int result;
|
|
+
|
|
+ bzero(&d->ccb->csio, sizeof(d->ccb->csio));
|
|
+
|
|
+ memcpy(d->ccb->csio.cdb_io.cdb_bytes, d->sg_buffer, cmd_len);
|
|
+
|
|
+ if (bytecheck && out_size == 0)
|
|
+ memset(d->sg_buffer, bytefill, in_size);
|
|
+
|
|
+ cam_fill_csio(&d->ccb->csio,
|
|
+ /* retries */ 0,
|
|
+ /* cbfcnp */ NULL,
|
|
+ /* flags */ CAM_DEV_QFRZDIS | (out_size ? CAM_DIR_OUT : CAM_DIR_IN),
|
|
+ /* tag_action */ MSG_SIMPLE_Q_TAG,
|
|
+ /* data_ptr */ out_size ? d->sg_buffer + cmd_len : d->sg_buffer,
|
|
+ /* dxfer_len */ out_size ? out_size : in_size,
|
|
+ /* sense_len */ SSD_FULL_SIZE,
|
|
+ /* cdb_len */ cmd_len,
|
|
+ /* timeout */ 60000); /* XXX */
|
|
+
|
|
+ if ((result = cam_send_ccb(d->dev, d->ccb)) < 0 ||
|
|
+ (d->ccb->ccb_h.status & CAM_STATUS_MASK) == 0 /* hack? */)
|
|
+ return TR_EREAD;
|
|
+
|
|
+ if ((d->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP &&
|
|
+ (d->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR) {
|
|
+ fprintf (stderr, "\t\terror returned from SCSI command:\n"
|
|
+ "\t\tccb->ccb_h.status == %d\n", d->ccb->ccb_h.status);
|
|
+ errno = EIO;
|
|
+ return TR_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ if (d->ccb->csio.dxfer_len != in_size) {
|
|
+ errno = EIO;
|
|
+ return TR_EREAD;
|
|
+ }
|
|
+
|
|
+ if (d->ccb->csio.sense_data.error_code & SSD_ERRCODE) {
|
|
+ switch (d->ccb->csio.sense_data.flags & SSD_KEY) {
|
|
+ case SSD_KEY_NO_SENSE:
|
|
+ errno = EIO;
|
|
+ return TR_UNKNOWN;
|
|
+ case SSD_KEY_RECOVERED_ERROR:
|
|
+ break;
|
|
+ case SSD_KEY_NOT_READY:
|
|
+ errno = EBUSY;
|
|
+ return TR_BUSY;
|
|
+ case SSD_KEY_MEDIUM_ERROR:
|
|
+ errno = EIO;
|
|
+ if (d->ccb->csio.sense_data.add_sense_code == 0x0c &&
|
|
+ d->ccb->csio.sense_data.add_sense_code_qual == 0x09)
|
|
+ return TR_STREAMING;
|
|
+ else
|
|
+ return TR_MEDIUM;
|
|
+ case SSD_KEY_HARDWARE_ERROR:
|
|
+ errno = EIO;
|
|
+ return TR_FAULT;
|
|
+ case SSD_KEY_ILLEGAL_REQUEST:
|
|
+ errno = EINVAL;
|
|
+ return TR_ILLEGAL;
|
|
+ default:
|
|
+ errno = EIO;
|
|
+ return TR_UNKNOWN;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
/* Group 1 (10b) command */
|
|
|
|
static int mode_sense_atapi(cdrom_drive *d,int size,int page){
|
|
@@ -600,6 +793,23 @@ static int scsi_read_toc2 (cdrom_drive *
|
|
return(tracks);
|
|
}
|
|
|
|
+/* Set operating speed */
|
|
+static int scsi_setspeed(cdrom_drive *d, int speed)
|
|
+{
|
|
+ if (speed == 0)
|
|
+ speed = 0xffff; /* maximum speed */
|
|
+ else if (speed < 176)
|
|
+ speed *= 176;
|
|
+
|
|
+ memset(d->sg_buffer, 0, 12);
|
|
+ d->sg_buffer[0] = 0xbb; /* set speed */
|
|
+ d->sg_buffer[2] = speed >> 8;
|
|
+ d->sg_buffer[3] = speed;
|
|
+ d->sg_buffer[4] = -1;
|
|
+ d->sg_buffer[5] = -1;
|
|
+ return handle_scsi_cmd(d, 12, 0, 0, 0, 0);
|
|
+}
|
|
+
|
|
/* These do one 'extra' copy in the name of clean code */
|
|
|
|
static int i_read_28 (cdrom_drive *d, void *p, long begin, long sectors){
|
|
@@ -833,30 +1043,59 @@ static long scsi_read_map (cdrom_drive *
|
|
while(1) {
|
|
if((err=map(d,(p?buffer:NULL),begin,sectors))){
|
|
if(d->report_all){
|
|
+#ifdef __linux__
|
|
struct sg_header *sg_hd=(struct sg_header *)d->sg;
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ scsireq_t *sreq=(scsireq_t *)d->sg;
|
|
+#endif
|
|
char b[256];
|
|
|
|
sprintf(b,"scsi_read error: sector=%ld length=%ld retry=%d\n",
|
|
begin,sectors,retry_count);
|
|
+ fputs(b, stderr);
|
|
cdmessage(d,b);
|
|
sprintf(b," Sense key: %x ASC: %x ASCQ: %x\n",
|
|
+#ifdef __linux__
|
|
(int)(sg_hd->sense_buffer[2]&0xf),
|
|
(int)(sg_hd->sense_buffer[12]),
|
|
(int)(sg_hd->sense_buffer[13]));
|
|
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+ d->ccb->csio.sense_data.flags & SSD_KEY,
|
|
+ d->ccb->csio.sense_data.add_sense_code,
|
|
+ d->ccb->csio.sense_data.add_sense_code_qual);
|
|
+#elif defined(__NetBSD__)
|
|
+ (int)(sreq->sense[2]&0xf),
|
|
+ (int)(sreq->sense[12]),
|
|
+ (int)(sreq->sense[13]));
|
|
+#endif
|
|
+ fputs(b, stderr);
|
|
cdmessage(d,b);
|
|
sprintf(b," Transport error: %s\n",strerror_tr[err]);
|
|
+ fputs(b, stderr);
|
|
cdmessage(d,b);
|
|
sprintf(b," System error: %s\n",strerror(errno));
|
|
+ fputs(b, stderr);
|
|
cdmessage(d,b);
|
|
|
|
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
|
|
fprintf(stderr,"scsi_read error: sector=%ld length=%ld retry=%d\n",
|
|
begin,sectors,retry_count);
|
|
fprintf(stderr," Sense key: %x ASC: %x ASCQ: %x\n",
|
|
+#ifdef __linux__
|
|
(int)(sg_hd->sense_buffer[2]&0xf),
|
|
(int)(sg_hd->sense_buffer[12]),
|
|
- (int)(sg_hd->sense_buffer[13]));
|
|
+ (int)(sg_hd->sense_buffer[13])
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ (int)(sreq->sense[2]&0xf),
|
|
+ (int)(sreq->sense[12]),
|
|
+ (int)(sreq->sense[13])
|
|
+#endif
|
|
+ );
|
|
fprintf(stderr," Transport error: %s\n",strerror_tr[err]);
|
|
fprintf(stderr," System error: %s\n",strerror(errno));
|
|
+#endif
|
|
}
|
|
|
|
if(!d->error_retry)return(-7);
|
|
@@ -1307,22 +1546,45 @@ static void check_fua_bit(cdrom_drive *d
|
|
return;
|
|
}
|
|
|
|
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
|
|
static int check_atapi(cdrom_drive *d){
|
|
+#ifdef __linux__
|
|
int atapiret=-1;
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ struct scsi_addr scaddr;
|
|
+#endif
|
|
int fd = d->cdda_fd; /* this is the correct fd (not ioctl_fd), as the
|
|
generic device is the device we need to check */
|
|
|
|
cdmessage(d,"\nChecking for SCSI emulation...\n");
|
|
|
|
- if (ioctl(fd,SG_EMULATED_HOST,&atapiret)){
|
|
+#ifdef __linux__
|
|
+ if (ioctl(fd,SG_EMULATED_HOST,&atapiret))
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ if(ioctl(fd,SCIOCIDENTIFY,&scaddr))
|
|
+#endif
|
|
+ {
|
|
cderror(d,"\tSG_EMULATED_HOST ioctl() failed!\n");
|
|
return(-1);
|
|
} else {
|
|
- if(atapiret==1){
|
|
+#ifdef __linux__
|
|
+ if(atapiret==1)
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ if(scaddr.type == TYPE_ATAPI)
|
|
+#endif
|
|
+ {
|
|
+#ifdef __linux__
|
|
cdmessage(d,"\tDrive is ATAPI (using SCSI host adaptor emulation)\n");
|
|
/* Disable kernel SCSI command translation layer for access through sg */
|
|
if (ioctl(fd,SG_SET_TRANSFORM,0))
|
|
cderror(d,"\tCouldn't disable kernel command translation layer\n");
|
|
+#endif
|
|
+#ifdef __NetBSD__
|
|
+ cdmessage(d,"\tDrive is ATAPI\n");
|
|
+#endif
|
|
d->is_atapi=1;
|
|
}else{
|
|
cdmessage(d,"\tDrive is SCSI\n");
|
|
@@ -1332,6 +1594,46 @@ static int check_atapi(cdrom_drive *d){
|
|
return(d->is_atapi);
|
|
}
|
|
}
|
|
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+static int
|
|
+check_atapi(cdrom_drive *d)
|
|
+{
|
|
+ bzero(&(&d->ccb->ccb_h)[1], sizeof(d->ccb->cpi) - sizeof(d->ccb->ccb_h));
|
|
+
|
|
+ d->ccb->ccb_h.func_code = XPT_PATH_INQ;
|
|
+
|
|
+ cdmessage(d, "\nChecking for ATAPICAM...\n");
|
|
+
|
|
+ if (cam_send_ccb(d->dev, d->ccb) < 0) {
|
|
+ cderror(d, "\terror sending XPT_PATH_INQ CCB: ");
|
|
+ cderror(d, cam_errbuf);
|
|
+ cderror(d, "\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if ((d->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
|
+ cderror(d, "\tXPT_PATH_INQ CCB failed: ");
|
|
+ cderror(d, cam_errbuf);
|
|
+ cderror(d, "\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * if the bus device name is `ata', we're (obviously)
|
|
+ * running ATAPICAM.
|
|
+ */
|
|
+
|
|
+ if (strncmp(d->ccb->cpi.dev_name, "ata", 3) == 0) {
|
|
+ cdmessage(d, "\tDrive is ATAPI (using ATAPICAM)\n");
|
|
+ d->is_atapi = 1;
|
|
+ } else {
|
|
+ cdmessage(d, "\tDrive is SCSI\n");
|
|
+ d->is_atapi = 0;
|
|
+ }
|
|
+
|
|
+ return d->is_atapi;
|
|
+}
|
|
+#endif
|
|
|
|
static int check_mmc(cdrom_drive *d){
|
|
char *b;
|
|
@@ -1379,6 +1681,7 @@ static void check_exceptions(cdrom_drive
|
|
}
|
|
}
|
|
|
|
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
|
|
/* request vendor brand and model */
|
|
unsigned char *scsi_inquiry(cdrom_drive *d){
|
|
memcpy(d->sg_buffer,(char[]){ 0x12,0,0,0,56,0},6);
|
|
@@ -1389,6 +1692,7 @@ unsigned char *scsi_inquiry(cdrom_drive
|
|
}
|
|
return (d->sg_buffer);
|
|
}
|
|
+#endif
|
|
|
|
|
|
int scsi_init_drive(cdrom_drive *d){
|
|
@@ -1434,7 +1738,7 @@ int scsi_init_drive(cdrom_drive *d){
|
|
|
|
d->read_toc = (!memcmp(d->drive_model, "IMS", 3) && !d->is_atapi) ? scsi_read_toc2 :
|
|
scsi_read_toc;
|
|
- d->set_speed = NULL;
|
|
+ d->set_speed = scsi_setspeed;
|
|
|
|
|
|
if(!d->is_atapi){
|
|
@@ -1458,8 +1762,12 @@ int scsi_init_drive(cdrom_drive *d){
|
|
check_fua_bit(d);
|
|
|
|
d->error_retry=1;
|
|
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
|
|
d->sg=realloc(d->sg,d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128);
|
|
d->sg_buffer=d->sg+SG_OFF;
|
|
+#else
|
|
+ d->sg_buffer = realloc(d->sg_buffer, d->nsectors * CD_FRAMESIZE_RAW);
|
|
+#endif
|
|
d->report_all=1;
|
|
return(0);
|
|
}
|