$NetBSD: patch-cg,v 1.12 2009/09/10 19:14:46 wiz Exp $ --- interface/scsi_interface.c.orig 2008-09-11 20:33:30.000000000 +0000 +++ interface/scsi_interface.c 2009-09-10 12:02:02.000000000 +0000 @@ -12,7 +12,16 @@ #include "common_interface.h" #include "utils.h" #include -static int timed_ioctl(cdrom_drive *d, int fd, int command, void *arg){ +#include + +#ifdef __NetBSD__ +#define SG_MAX_SENSE SENSEBUFLEN +#define IOCTL_CMD unsigned long +#else +#define IOCTL_CMD int +#endif + +static int timed_ioctl(cdrom_drive *d, int fd, IOCTL_CMD command, void *arg){ struct timespec tv1; struct timespec tv2; int ret1=clock_gettime(d->private->clock,&tv1); @@ -36,6 +45,7 @@ int table, reserved, cur, err; char buffer[256]; +#ifdef __linux__ /* SG_SET_RESERVED_SIZE doesn't actually allocate or reserve anything. * what it _does_ do is give you an error if you ask for a value * larger than q->max_sectors (the length of the device's bio request @@ -54,6 +64,10 @@ implement working sg lists with SG_IO devices, so who knows... */ if (ioctl(d->cdda_fd, SG_GET_SG_TABLESIZE, &table) < 0) table=1; +#else + reserved = 32*1024; /* ? */ + table = 1; +#endif sprintf(buffer,"\tDMA scatter/gather table entries: %d\n\t" "table entry size: %d bytes\n\t" @@ -93,6 +107,7 @@ cdmessage(d,buffer); } +#if defined(__linux__) || defined(__DragonFly__) static void clear_garbage(cdrom_drive *d){ fd_set fdset; struct timeval tv; @@ -123,6 +138,7 @@ flag=1; } } +#endif static int check_sbp_error(const unsigned char status, const unsigned char *sbp) { @@ -172,6 +188,7 @@ return 0; } +#if defined(__linux__) || defined(__DragonFly__) /* process a complete scsi command. */ static int sg2_handle_scsi_cmd(cdrom_drive *d, unsigned char *cmd, @@ -356,7 +373,11 @@ hdr.timeout = 50000; hdr.interface_id = 'S'; hdr.dxferp = d->private->sg_buffer; +#if defined(__DragonFly__) + hdr.flags = 0; +#else hdr.flags = SG_FLAG_DIRECT_IO; /* direct IO if we can get it */ +#endif /* scary buffer fill hack */ if(bytecheck && out_size>in_size) @@ -417,6 +438,71 @@ errno = 0; return 0; } +#endif /* __linux__ */ + +#ifdef __NetBSD__ +static int nb_handle_scsi_cmd(cdrom_drive *d, + unsigned char *cmd, + unsigned int cmd_len, + unsigned int in_size, + unsigned int out_size, + unsigned char bytefill, + int bytecheck, + unsigned char *sense_buffer){ + int status = 0; + scsireq_t *sreq = (scsireq_t *)d->private->sg_hd; + + memset(sense_buffer,0,SENSEBUFLEN); + memcpy(d->private->sg_buffer,cmd+cmd_len,in_size); + + 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, cmd, cmd_len); + if (in_size) { + sreq->flags = SCCMD_WRITE; + sreq->databuf = d->private->sg_buffer; + sreq->datalen = in_size; + } + if (out_size) { + sreq->flags = SCCMD_READ; + sreq->databuf = d->private->sg_buffer; + sreq->datalen = out_size; + if(bytecheck) + memset(d->private->sg_buffer, bytefill, out_size); + } + sreq->senselen = SENSEBUFLEN; + sreq->timeout = 60000; /* 60s */ + + status = timed_ioctl(d, d->cdda_fd, SCIOCCOMMAND, (void *) sreq); + if (status < 0) + return(TR_ILLEGAL); + memcpy(sense_buffer,sreq->sense,SENSEBUFLEN); + status = check_sbp_error(sreq->status,sense_buffer); + if (status) + return status; + + if(bytecheck && out_size){ + long i,flag=0; + for(i=0;iprivate->sg_buffer[i]!=bytefill){ + flag=1; + break; + } + + if(!flag){ + errno=EINVAL; + return(TR_ILLEGAL); + } + } + + errno=0; + return 0; +} +#endif /* __NetBSD__ */ static int handle_scsi_cmd(cdrom_drive *d, unsigned char *cmd, @@ -427,9 +513,14 @@ int bytecheck, unsigned char *sense){ +#if defined(__linux__) || defined(__DragonFly__) if(d->interface == SGIO_SCSI || d->interface == SGIO_SCSI_BUGGY1) return sgio_handle_scsi_cmd(d,cmd,cmd_len,in_size,out_size,bytefill,bytecheck,sense); return sg2_handle_scsi_cmd(d,cmd,cmd_len,in_size,out_size,bytefill,bytecheck,sense); +#endif +#ifdef __NetBSD__ + return nb_handle_scsi_cmd(d,cmd,cmd_len,in_size,out_size,bytefill,bytecheck,sense); +#endif } @@ -453,6 +544,7 @@ return 1; } +#if defined(__linux__) || defined(__DragonFly__) static void reset_scsi(cdrom_drive *d){ int arg,tries=0; d->enable_cdda(d,0); @@ -471,6 +563,22 @@ d->enable_cdda(d,1); } +#endif + +#ifdef __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); +} +#endif static int mode_sense_atapi(cdrom_drive *d,int size,int page){ unsigned char sense[SG_MAX_SENSE]; @@ -1587,6 +1695,7 @@ } } +#if defined(__linux__) || defined(__DragonFly__) static int check_atapi(cdrom_drive *d){ int atapiret=-1; int fd = d->cdda_fd; /* check the device we'll actually be using to read */ @@ -1616,7 +1725,32 @@ return(d->is_atapi); } -} +} +#endif + +#ifdef __NetBSD__ +static int check_atapi(cdrom_drive *d){ + struct scsi_addr scaddr; + int fd = d->cdda_fd; /* check the device we'll actually be using to read */ + + cdmessage(d,"\nChecking for SCSI emulation...\n"); + + if (ioctl(fd,SCIOCIDENTIFY,&scaddr)){ + cderror(d,"\tSG_EMULATED_HOST ioctl() failed!\n"); + return(-1); + } else { + if(scaddr.type == TYPE_ATAPI){ + cdmessage(d,"\tDrive is ATAPI\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){ unsigned char *b;