openbsd-ports/audio/cdparanoia/patches/patch-interface_scsi_interface_c
2007-10-27 15:01:53 +00:00

277 lines
8.0 KiB
Plaintext

$OpenBSD: patch-interface_scsi_interface_c,v 1.4 2007/10/27 15:01:53 espie Exp $
--- interface/scsi_interface.c.orig Sat Mar 24 02:15:46 2001
+++ interface/scsi_interface.c Sat Oct 27 16:57:49 2007
@@ -23,6 +23,7 @@ static void tweak_SG_buffer(cdrom_drive *d){
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 *d){
}
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 *d){
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 *d,
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 *d,
}
}
}
+#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 *d,
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 *d,
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 *d){
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 *d, void *p, lo
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 *d, void *p, lo
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){