$NetBSD: patch-cg,v 1.6 2002/03/04 14:45:14 itohy Exp $ --- interface/scsi_interface.c.orig Sat Mar 24 10:15:46 2001 +++ interface/scsi_interface.c Mon Mar 4 00:03:19 2002 @@ -23,6 +23,7 @@ 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 @@ } if(ioctl(d->cdda_fd,SG_GET_SG_TABLESIZE,&table))table=1; +#else + reserved = 32*1024; /* ? */ + table = 1; +#endif { int cur; @@ -53,11 +58,13 @@ 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 } @@ -65,8 +72,14 @@ 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 +#ifdef __NetBSD__ + 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 +87,7 @@ d->enable_cdda(d,1); } +#ifdef __linux__ static void clear_garbage(cdrom_drive *d){ fd_set fdset; struct timeval tv; @@ -104,6 +118,7 @@ flag=1; } } +#endif /* process a complete scsi command. */ static int handle_scsi_cmd(cdrom_drive *d, @@ -111,14 +126,21 @@ 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 +246,53 @@ 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 +330,20 @@ commands still get through. Perhaps no data comes back even though the target reports success? */ - if(bytecheck && in_size+cmd_lensg_buffer[i]!=bytefill){ flag=1; break; @@ -600,6 +675,23 @@ 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 +925,29 @@ 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); 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])); + (int)(sg_hd->sense_buffer[13]) +#endif +#ifdef __NetBSD__ + (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 +957,17 @@ 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)); } @@ -1308,21 +1421,43 @@ } 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"); @@ -1434,7 +1569,7 @@ 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){