$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_lensg_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){