$NetBSD: patch-cg,v 1.15 2018/09/27 19:23:09 ryoon Exp $ - fix ripping on NetBSD/amd64 - build fix on DragonFly - build fix on NetBSD with SSP --- interface/scsi_interface.c.orig 2008-09-11 20:33:30.000000000 +0000 +++ interface/scsi_interface.c @@ -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 @@ static void tweak_SG_buffer(cdrom_drive 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 @@ static void tweak_SG_buffer(cdrom_drive 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 @@ static void tweak_SG_buffer(cdrom_drive 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 @@ static void clear_garbage(cdrom_drive *d flag=1; } } +#endif static int check_sbp_error(const unsigned char status, const unsigned char *sbp) { @@ -172,6 +188,7 @@ static int check_sbp_error(const unsigne 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 @@ static int sgio_handle_scsi_cmd(cdrom_dr 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,161 @@ static int sgio_handle_scsi_cmd(cdrom_dr 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__ */ + +#if defined(__FreeBSD__) +static int fb_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){ + int result; + int error_code, sense_key, asc, ascq; + + bzero(&d->ccb->csio, sizeof(d->ccb->csio)); + + memcpy(d->ccb->csio.cdb_io.cdb_bytes, d->private->sg_buffer, cmd_len); + + if (bytecheck && out_size == 0) + memset(d->private->sg_buffer, bytefill, in_size); + + cam_fill_csio(&d->ccb->csio, + /* retries */ 0, + /* cbfcnp */ NULL, + /* flags */ CAM_DEV_QFRZDIS | (out_size ? CAM_DIR_OUT : CAM_DIR_IN), + /* tag_action */ MSG_SIMPLE_Q_TAG, + /* data_ptr */ out_size ? d->private->sg_buffer + cmd_len : d->private->sg_buffer, + /* dxfer_len */ out_size ? out_size : in_size, + /* sense_len */ SSD_FULL_SIZE, + /* cdb_len */ cmd_len, + /* timeout */ 60000); /* XXX */ + + if ((result = cam_send_ccb(d->dev, d->ccb)) < 0 || + (d->ccb->ccb_h.status & CAM_STATUS_MASK) == 0 /* hack? */) + return TR_EREAD; + + if ((d->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP && + (d->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR) { + fprintf (stderr, "\t\terror returned from SCSI command:\n" + "\t\tccb->ccb_h.status == %d\n", d->ccb->ccb_h.status); + errno = EIO; + return TR_UNKNOWN; + } + + if (d->ccb->csio.dxfer_len != in_size) { + errno = EIO; + return TR_EREAD; + } + + scsi_extract_sense(&d->ccb->csio.sense_data, &error_code, &sense_key, + &asc, &ascq); + + switch (error_code) { + case SSD_CURRENT_ERROR: + case SSD_DEFERRED_ERROR: +#if (CAM_VERSION > 0x15) + case SSD_DESC_CURRENT_ERROR: + case SSD_DESC_DEFERRED_ERROR: +#endif + switch (sense_key) { + case SSD_KEY_NO_SENSE: + errno = EIO; + return TR_UNKNOWN; + case SSD_KEY_RECOVERED_ERROR: + break; + case SSD_KEY_NOT_READY: + errno = EBUSY; + return TR_BUSY; + case SSD_KEY_MEDIUM_ERROR: + errno = EIO; + if ((asc == 0x0c) && (ascq == 0x09)) + return TR_STREAMING; + else + return TR_MEDIUM; + case SSD_KEY_HARDWARE_ERROR: + errno = EIO; + return TR_FAULT; + case SSD_KEY_ILLEGAL_REQUEST: + errno = EINVAL; + return TR_ILLEGAL; + default: + errno = EIO; + return TR_UNKNOWN; + } + default: + break; + } + + return 0; +} +#endif /* __FreeBSD__ */ static int handle_scsi_cmd(cdrom_drive *d, unsigned char *cmd, @@ -427,9 +603,17 @@ static int handle_scsi_cmd(cdrom_drive * 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 +#if defined(__FreeBSD__) + return fb_handle_scsi_cmd(d,cmd,cmd_len,in_size,out_size,bytefill,bytecheck,sense); +#endif } @@ -453,6 +637,7 @@ static int test_unit_ready(cdrom_drive * 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 +656,45 @@ static void reset_scsi(cdrom_drive *d){ 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 + +#if defined(__FreeBSD__) +static void reset_scsi(cdrom_drive *d) { + d->enable_cdda(d,0); + + d->ccb->ccb_h.func_code = XPT_RESET_DEV; + d->ccb->ccb_h.timeout = 5000; + + cdmessage(d, "sending SCSI reset... "); + if (cam_send_ccb(d->dev, d->ccb)) { + cdmessage(d, "error sending XPT_RESET_DEV CCB"); + } else { + + if (((d->ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) || + ((d->ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT)) + cdmessage(d,"OK\n"); + else + cdmessage(d,"FAILED\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]; @@ -657,6 +881,7 @@ static int scsi_read_toc (cdrom_drive *d /* read the header first */ unsigned char sense[SG_MAX_SENSE]; unsigned char cmd[10] = { 0x43, 0, 0, 0, 0, 0, 1, 0, 12, 0}; + const char cmd_43[10] = { 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}; cmd[1]=d->lun<<5; if (handle_scsi_cmd (d,cmd,10, 0, 12,'\377',1,sense)){ @@ -674,7 +899,7 @@ static int scsi_read_toc (cdrom_drive *d } for (i = first; i <= last; i++){ - memcpy(cmd, (char []){ 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}, 10); + memcpy(cmd, cmd_43, sizeof(cmd_43)); cmd[1]=d->lun<<5; cmd[6]=i; @@ -695,7 +920,7 @@ static int scsi_read_toc (cdrom_drive *d } } - memcpy(cmd, (char []){ 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}, 10); + memcpy(cmd, cmd_43, sizeof(cmd_43)); cmd[1]=d->lun<<5; cmd[6]=0xAA; @@ -745,7 +970,8 @@ static int scsi_read_toc2 (cdrom_drive * } for (i = 0; i < tracks; i++){ - memcpy(cmd, (char[]){ 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10); + const char cmd_e5[10] = { 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + memcpy(cmd, cmd_e5, sizeof(cmd_e5)); cmd[5]=i+1; cmd[8]=255; @@ -1587,6 +1813,7 @@ static void check_cache(cdrom_drive *d){ } } +#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 +1843,79 @@ static int check_atapi(cdrom_drive *d){ 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 + +#if defined(__FreeBSD__) +static int +check_atapi(cdrom_drive *d) +{ + bzero(&(&d->ccb->ccb_h)[1], sizeof(d->ccb->cpi) - sizeof(d->ccb->ccb_h)); + + d->ccb->ccb_h.func_code = XPT_PATH_INQ; + + cdmessage(d, "\nChecking for ATAPICAM...\n"); + + if (cam_send_ccb(d->dev, d->ccb) < 0) { + cderror(d, "\terror sending XPT_PATH_INQ CCB: "); + cderror(d, cam_errbuf); + cderror(d, "\n"); + return -1; + } + + if ((d->ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + cderror(d, "\tXPT_PATH_INQ CCB failed: "); + cderror(d, cam_errbuf); + cderror(d, "\n"); + return -1; + } + + /* + * if the bus device name is `ata', we're (obviously) + * running ATAPICAM. + * same for the new ahci(4) and siis(4) drivers and future others + * which use SATA transport too... + */ + + if (strncmp(d->ccb->cpi.dev_name, "ata", 3) == 0 || +#if __FreeBSD_version >= 800102 + d->ccb->cpi.transport == XPORT_SATA || +#endif + d->ccb->cpi.transport == XPORT_ATA) { + cdmessage(d, "\tDrive is ATAPI (using ATAPICAM or direct CAM (S)ATA transport)\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; @@ -1664,6 +1963,7 @@ static void check_exceptions(cdrom_drive } } +#if !defined(__FreeBSD__) && !defined(__DragonFly__) /* request vendor brand and model */ unsigned char *scsi_inquiry(cdrom_drive *d){ unsigned char sense[SG_MAX_SENSE]; @@ -1675,6 +1975,7 @@ unsigned char *scsi_inquiry(cdrom_drive } return (d->private->sg_buffer); } +#endif int scsi_init_drive(cdrom_drive *d){ int ret;