pkgsrc/audio/cdparanoia/patches/patch-cg
joerg 9bc4bc08f9 Sync DragonFly/FreeBSD support with FreeBSD ports by adding
cdda_device_name to struct cdrom_drive. This makes a number of
hacks in various places superfluous and should fix the KDE multimedia
issues. Bump revision. Recursive bump will follow, since the major
version changed.
2006-03-07 06:29:03 +00:00

506 lines
13 KiB
Text

$NetBSD: patch-cg,v 1.8 2006/03/07 06:29:04 joerg Exp $
--- interface/scsi_interface.c.orig 2001-03-24 12:15:46.000000000 +1100
+++ interface/scsi_interface.c
@@ -23,6 +23,8 @@ static void tweak_SG_buffer(cdrom_drive
int table,reserved;
char buffer[256];
+#if !defined(__FreeBSD__) || defined(__DragonFly__)
+#ifdef __linux__
/* maximum transfer size? */
if(ioctl(d->cdda_fd,SG_GET_RESERVED_SIZE,&reserved)){
/* Up, guess not. */
@@ -31,6 +33,10 @@ static void tweak_SG_buffer(cdrom_drive
}
if(ioctl(d->cdda_fd,SG_GET_SG_TABLESIZE,&table))table=1;
+#else
+ reserved = 32*1024; /* ? */
+ table = 1;
+#endif
{
int cur;
@@ -53,14 +59,24 @@ static void tweak_SG_buffer(cdrom_drive
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
+#else /* FreeBSD */
+ d->nsectors = 26; /* FreeBSD only supports 64K I/O transfer size */
+ d->bigbuff = d->nsectors * CD_FRAMESIZE_RAW;
+
+ sprintf(buffer,"\tSetting default read size to %d sectors (%d bytes).\n\n",
+ d->nsectors,d->nsectors*CD_FRAMESIZE_RAW);
+ cdmessage(d,buffer);
+#endif
}
+#ifdef __linux__
static void reset_scsi(cdrom_drive *d){
int arg;
d->enable_cdda(d,0);
@@ -74,6 +90,44 @@ static void reset_scsi(cdrom_drive *d){
d->enable_cdda(d,1);
}
+#elif defined(__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);
+}
+
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+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
+
+#ifdef __linux__
static void clear_garbage(cdrom_drive *d){
fd_set fdset;
struct timeval tv;
@@ -104,21 +158,30 @@ static void clear_garbage(cdrom_drive *d
flag=1;
}
}
+#endif
/* process a complete scsi command. */
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
static int handle_scsi_cmd(cdrom_drive *d,
unsigned int cmd_len,
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 +287,53 @@ static int handle_scsi_cmd(cdrom_drive *
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 +371,20 @@ static int handle_scsi_cmd(cdrom_drive *
commands still get through. Perhaps no data comes back even
though the target reports success? */
- if(bytecheck && in_size+cmd_len<out_size){
+#ifdef __linux__
+ if(bytecheck && in_size+cmd_len<out_size)
+#endif
+#ifdef __NetBSD__
+ if(bytecheck && out_size)
+#endif
+ {
long i,flag=0;
+#ifdef __linux__
for(i=in_size;i<out_size;i++)
+#endif
+#ifdef __NetBSD__
+ for(i=0;i<out_size;i++)
+#endif
if(d->sg_buffer[i]!=bytefill){
flag=1;
break;
@@ -284,6 +400,83 @@ static int handle_scsi_cmd(cdrom_drive *
return(0);
}
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+static int handle_scsi_cmd(cdrom_drive *d,
+ unsigned int cmd_len,
+ unsigned int out_size,
+ unsigned int in_size,
+ unsigned char bytefill,
+ int bytecheck) {
+ int result;
+
+ bzero(&d->ccb->csio, sizeof(d->ccb->csio));
+
+ memcpy(d->ccb->csio.cdb_io.cdb_bytes, d->sg_buffer, cmd_len);
+
+ if (bytecheck && out_size == 0)
+ memset(d->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->sg_buffer + cmd_len : d->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;
+ }
+
+ if (d->ccb->csio.sense_data.error_code & SSD_ERRCODE) {
+ switch (d->ccb->csio.sense_data.flags & SSD_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 (d->ccb->csio.sense_data.add_sense_code == 0x0c &&
+ d->ccb->csio.sense_data.add_sense_code_qual == 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;
+ }
+ }
+
+ return 0;
+}
+#endif
+
/* Group 1 (10b) command */
static int mode_sense_atapi(cdrom_drive *d,int size,int page){
@@ -600,6 +793,23 @@ static int scsi_read_toc2 (cdrom_drive *
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,30 +1043,59 @@ static long scsi_read_map (cdrom_drive *
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);
+ fputs(b, stderr);
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]));
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+ d->ccb->csio.sense_data.flags & SSD_KEY,
+ d->ccb->csio.sense_data.add_sense_code,
+ d->ccb->csio.sense_data.add_sense_code_qual);
+#elif defined(__NetBSD__)
+ (int)(sreq->sense[2]&0xf),
+ (int)(sreq->sense[12]),
+ (int)(sreq->sense[13]));
+#endif
+ fputs(b, stderr);
cdmessage(d,b);
sprintf(b," Transport error: %s\n",strerror_tr[err]);
+ fputs(b, stderr);
cdmessage(d,b);
sprintf(b," System error: %s\n",strerror(errno));
+ fputs(b, stderr);
cdmessage(d,b);
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
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));
+#endif
}
if(!d->error_retry)return(-7);
@@ -1307,22 +1546,45 @@ static void check_fua_bit(cdrom_drive *d
return;
}
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
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");
@@ -1332,6 +1594,46 @@ static int check_atapi(cdrom_drive *d){
return(d->is_atapi);
}
}
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+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.
+ */
+
+ if (strncmp(d->ccb->cpi.dev_name, "ata", 3) == 0) {
+ cdmessage(d, "\tDrive is ATAPI (using ATAPICAM)\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){
char *b;
@@ -1379,6 +1681,7 @@ static void check_exceptions(cdrom_drive
}
}
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
/* request vendor brand and model */
unsigned char *scsi_inquiry(cdrom_drive *d){
memcpy(d->sg_buffer,(char[]){ 0x12,0,0,0,56,0},6);
@@ -1389,6 +1692,7 @@ unsigned char *scsi_inquiry(cdrom_drive
}
return (d->sg_buffer);
}
+#endif
int scsi_init_drive(cdrom_drive *d){
@@ -1434,7 +1738,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){
@@ -1458,8 +1762,12 @@ int scsi_init_drive(cdrom_drive *d){
check_fua_bit(d);
d->error_retry=1;
+#if !defined(__FreeBSD__) && !defined(__DragonFly__)
d->sg=realloc(d->sg,d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128);
d->sg_buffer=d->sg+SG_OFF;
+#else
+ d->sg_buffer = realloc(d->sg_buffer, d->nsectors * CD_FRAMESIZE_RAW);
+#endif
d->report_all=1;
return(0);
}