277 lines
7.9 KiB
Plaintext
277 lines
7.9 KiB
Plaintext
$OpenBSD: patch-interface_scsi_interface_c,v 1.3 2005/12/23 06:31:31 jakemsr Exp $
|
|
--- interface/scsi_interface.c.orig Fri Mar 23 17:15:46 2001
|
|
+++ interface/scsi_interface.c Thu Dec 22 22:30:02 2005
|
|
@@ -23,6 +23,7 @@ static void tweak_SG_buffer(cdrom_drive
|
|
int table,reserved;
|
|
char buffer[256];
|
|
|
|
+#ifdef __linux__
|
|
/* maximum transfer size? */
|
|
if(ioctl(d->cdda_fd,SG_GET_RESERVED_SIZE,&reserved)){
|
|
/* Up, guess not. */
|
|
@@ -31,6 +32,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,20 +58,27 @@ 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
|
|
}
|
|
|
|
static void reset_scsi(cdrom_drive *d){
|
|
int arg;
|
|
d->enable_cdda(d,0);
|
|
|
|
+#ifdef __linux__
|
|
cdmessage(d,"sending SG SCSI reset... ");
|
|
if(ioctl(d->cdda_fd,SG_SCSI_RESET,&arg))
|
|
+#endif
|
|
+#if defined (__NetBSD__) || defined (__OpenBSD__)
|
|
+ cdmessage(d,"sending SCSI reset... ");
|
|
+ if(ioctl(d->cdda_fd,CDIOCRESET,&arg))
|
|
+#endif
|
|
cdmessage(d,"FAILED: EBUSY\n");
|
|
else
|
|
cdmessage(d,"OK\n");
|
|
@@ -74,6 +86,7 @@ static void reset_scsi(cdrom_drive *d){
|
|
d->enable_cdda(d,1);
|
|
}
|
|
|
|
+#ifdef __linux__
|
|
static void clear_garbage(cdrom_drive *d){
|
|
fd_set fdset;
|
|
struct timeval tv;
|
|
@@ -104,6 +117,7 @@ static void clear_garbage(cdrom_drive *d
|
|
flag=1;
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
/* process a complete scsi command. */
|
|
static int handle_scsi_cmd(cdrom_drive *d,
|
|
@@ -114,11 +128,16 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
unsigned char bytefill,
|
|
int bytecheck){
|
|
int status = 0;
|
|
+#ifdef __linux__
|
|
struct sg_header *sg_hd=(struct sg_header *)d->sg;
|
|
long writebytes=SG_OFF+cmd_len+in_size;
|
|
-
|
|
+#endif
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ scsireq_t *sreq = (scsireq_t *)d->sg;
|
|
+#endif
|
|
/* generic scsi device services */
|
|
|
|
+#ifdef __linux__
|
|
/* clear out any possibly preexisting garbage */
|
|
clear_garbage(d);
|
|
|
|
@@ -213,8 +232,38 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
}
|
|
}
|
|
}
|
|
+#endif /* __linux__ */
|
|
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ 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 = 10000; /* 10s */
|
|
+
|
|
+ status = ioctl(d->cdda_fd, SCIOCCOMMAND, (void *) sreq);
|
|
+ if (status < 0)
|
|
+ return(TR_ILLEGAL);
|
|
+#endif
|
|
+
|
|
errno=0;
|
|
+#ifdef __linux__
|
|
status = read(d->cdda_fd, sg_hd, SG_OFF + out_size);
|
|
sigprocmask ( SIG_UNBLOCK, &(d->sigset), NULL );
|
|
|
|
@@ -229,6 +278,13 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
char key=sg_hd->sense_buffer[2]&0xf;
|
|
char ASC=sg_hd->sense_buffer[12];
|
|
char ASCQ=sg_hd->sense_buffer[13];
|
|
+#endif
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ if (sreq->sense[0]){
|
|
+ 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 +322,19 @@ static int handle_scsi_cmd(cdrom_drive *
|
|
commands still get through. Perhaps no data comes back even
|
|
though the target reports success? */
|
|
|
|
+#ifdef __linux__
|
|
if(bytecheck && in_size+cmd_len<out_size){
|
|
+#endif
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ if(bytecheck && out_size){
|
|
+#endif
|
|
long i,flag=0;
|
|
+#ifdef __linux__
|
|
for(i=in_size;i<out_size;i++)
|
|
+#endif
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ for(i=0;i<out_size;i++)
|
|
+#endif
|
|
if(d->sg_buffer[i]!=bytefill){
|
|
flag=1;
|
|
break;
|
|
@@ -600,6 +666,24 @@ 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,16 +917,28 @@ 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
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ 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);
|
|
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]));
|
|
+#endif
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ (int)(sreq->sense[2]&0xf),
|
|
+ (int)(sreq->sense[12]),
|
|
+ (int)(sreq->sense[13]));
|
|
+#endif
|
|
cdmessage(d,b);
|
|
sprintf(b," Transport error: %s\n",strerror_tr[err]);
|
|
cdmessage(d,b);
|
|
@@ -852,9 +948,16 @@ static long scsi_read_map (cdrom_drive *
|
|
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]));
|
|
+#endif
|
|
+#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
+ (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));
|
|
}
|
|
@@ -1308,21 +1411,37 @@ static void check_fua_bit(cdrom_drive *d
|
|
}
|
|
|
|
static int check_atapi(cdrom_drive *d){
|
|
+#ifdef __linux__
|
|
int atapiret=-1;
|
|
+#endif
|
|
+#if defined (__NetBSD__) || defined (__OpenBSD__)
|
|
+ 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");
|
|
|
|
+#ifdef __linux__
|
|
if (ioctl(fd,SG_EMULATED_HOST,&atapiret)){
|
|
+#endif
|
|
+#if defined (__NetBSD__) || defined (__OpenBSD__)
|
|
+ if(ioctl(fd,SCIOCIDENTIFY,&scaddr)){
|
|
+#endif
|
|
cderror(d,"\tSG_EMULATED_HOST ioctl() failed!\n");
|
|
return(-1);
|
|
} else {
|
|
+#ifdef __linux__
|
|
if(atapiret==1){
|
|
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
|
|
+#if defined (__NetBSD__) || defined (__OpenBSD__)
|
|
+ if(scaddr.type == TYPE_ATAPI){
|
|
+ cdmessage(d,"\tDrive is ATAPI\n");
|
|
+#endif
|
|
d->is_atapi=1;
|
|
}else{
|
|
cdmessage(d,"\tDrive is SCSI\n");
|
|
@@ -1434,7 +1553,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){
|