From b6831605b29be3bd40709899b100143b0cf1b67c Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 5 Oct 2006 14:21:34 +0000 Subject: [PATCH] Made use of SCSI_IOCTL_GET_BUS_NUMBER in hope of cdrecord compatibility --- cdrskin/cdrskin.c | 67 ++++++++++++++++++++++--------------- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 35 ++++++++++--------- libburn/libburn.h | 16 ++++----- libburn/sg.c | 56 ++++++++++++++++++++++--------- libburn/sg.h | 2 +- libburn/transport.h | 1 + 7 files changed, 111 insertions(+), 68 deletions(-) diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 9ce5cdd..e854220 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -1472,9 +1472,9 @@ int Cdrpreskin__cdrecord_to_dev(char *adr, char device_adr[Cdrskin_adrleN], return(0); } } else { - if(busno<0 || busno>255) { + if(busno<0) { fprintf(stderr, - "cdrskin: FATAL : dev=[Prefix:]Bus,Target,Lun expects Bus out of {0..255}\n"); + "cdrskin: FATAL : dev=[Prefix:]Bus,Target,Lun expects Bus number >= 0\n"); return(0); } if((strncmp(adr,"ATA",3)==0 && (adr[3]==0 || adr[3]==':')) || @@ -1487,7 +1487,8 @@ int Cdrpreskin__cdrecord_to_dev(char *adr, char device_adr[Cdrskin_adrleN], } else { int ret; - ret= burn_drive_convert_scsi_adr(busno,-1,*driveno,lun_no,device_adr); + ret= burn_drive_convert_scsi_adr(busno,-1,-1,*driveno,lun_no, + device_adr); if(ret==0) { fprintf(stderr, "cdrskin: FATAL : Cannot find /dev/sgN with Bus,Target,Lun = %d,%d,%d\n", @@ -2910,8 +2911,8 @@ wrong_devno:; pseudo transport groups: 0 volatile drive number, 1 /dev/sgN, 2 /dev/hdX, - 1000+busno = non-pseudo SCSI bus - 2000+busno = pseudo-ATA|ATAPI SCSI bus (currently busno==2) + 1000000+busno = non-pseudo SCSI bus + 2000000+busno = pseudo-ATA|ATAPI SCSI bus (currently busno==2) */ int Cdrskin_driveno_to_btldev(struct CdrskiN *skin, int driveno, char btldev[Cdrskin_adrleN], int flag) @@ -2936,21 +2937,24 @@ int Cdrskin_driveno_to_btldev(struct CdrskiN *skin, int driveno, #ifdef Cdrskin_libburn_has_convert_scsi_adR if(!skin->preskin->old_pseudo_scsi_adr) { - int host_no= -1,channel_no= -1,target_no= -1,lun_no= -1; + int host_no= -1,channel_no= -1,target_no= -1,lun_no= -1, bus_no= -1; - ret= burn_drive_obtain_scsi_adr(loc,&host_no,&channel_no,&target_no, - &lun_no); + ret= burn_drive_obtain_scsi_adr(loc,&bus_no,&host_no,&channel_no, + &target_no,&lun_no); if(ret<=0) { if(strncmp(loc,"/dev/hd",7)==0) if(loc[7]>='a' && loc[7]<='z') if(loc[8]==0) { + + /* >>> implement new ATA enumeration here */ + sprintf(btldev,"2,%d,0",loc[7]-'a'); - {ret= 2002; goto adr_translation;} + {ret= 2000002; goto adr_translation;} } goto fallback; } else { - sprintf(btldev,"%d,%d,%d",host_no,target_no,lun_no); - ret= 1000+host_no; + sprintf(btldev,"%d,%d,%d",bus_no,target_no,lun_no); + ret= 1000000+bus_no; goto adr_translation; } } @@ -3034,9 +3038,14 @@ int Cdrskin_scanbus(struct CdrskiN *skin, int flag) { int ret,i,busno,first_on_bus,pseudo_transport_group= 0,skipped_devices= 0; char shellsafe[5*Cdrskin_strleN+2],perms[40],btldev[Cdrskin_adrleN]; - char adr[Cdrskin_adrleN],*raw_dev; + char adr[Cdrskin_adrleN],*raw_dev,*drives_shown= NULL; struct stat stbuf; + drives_shown= malloc(skin->n_drives+1); + if(drives_shown==NULL) + {ret= -1; goto ex;} + for(i=0;in_drives;i++) + drives_shown[i]= 0; if(flag&1) { printf("cdrskin: Overview of accessible drives (%d found) :\n", skin->n_drives); @@ -3074,43 +3083,43 @@ int Cdrskin_scanbus(struct CdrskiN *skin, int flag) printf("-----------------------------------------------------------------------------\n"); } else { if(!skin->preskin->old_pseudo_scsi_adr) { - pseudo_transport_group= 1000; + pseudo_transport_group= 1000000; raw_dev= skin->preskin->raw_device_adr; if(strncmp(raw_dev,"ATA",3)==0 && (raw_dev[3]==0 || raw_dev[3]==':')) - pseudo_transport_group= 2000; + pseudo_transport_group= 2000000; if(strncmp(raw_dev,"ATAPI",5)==0 && (raw_dev[5]==0 || raw_dev[5]==':')) - pseudo_transport_group= 2000; - if(pseudo_transport_group==2000) { + pseudo_transport_group= 2000000; + if(pseudo_transport_group==2000000) { fprintf(stderr,"scsidev: 'ATA'\ndevname: 'ATA'\n"); fprintf(stderr,"scsibus: -2 target: -2 lun: -2\n"); } } /* >>> fprintf(stderr,"Linux sg driver version: 3.1.25\n"); */ printf("Using libburn version '%s'.\n", Cdrskin_libburn_versioN); - if(pseudo_transport_group!=1000) + if(pseudo_transport_group!=1000000) printf( "cdrskin: NOTE : The printed addresses are not cdrecord compatible !\n"); - for(busno= 0;busno<16;busno++) { + for(busno= 0;busno<=16;busno++) { first_on_bus= 1; for(i=0;in_drives;i++) { ret= Cdrskin_driveno_to_btldev(skin,i,btldev,1); - if(ret==pseudo_transport_group + busno) - ret= busno; - if(ret!=busno) { - if((ret%1000)==busno) { + if(busno==16 && drives_shown[i]==0) { + if(ret/1000000 != pseudo_transport_group) { skipped_devices++; if(skin->verbosity>=Cdrskin_verbose_debuG) ClN(fprintf(stderr,"cdrskin_debug: skipping drive '%s%s'\n", - ((ret/1000)==2?"ATA:":""), btldev)); - } + ((ret/1000000)==2?"ATA:":""), btldev)); + continue; + } + } else if(ret != pseudo_transport_group + busno) continue; - } if(first_on_bus) printf("scsibus%d:\n",busno); first_on_bus= 0; printf("\t%s\t %d) '%-8s' '%-16s' '%-4s' Removable CD-ROM\n", btldev,i,skin->drives[i].vendor,skin->drives[i].product,"?..?"); + drives_shown[i]= 1; } } } @@ -3121,10 +3130,14 @@ int Cdrskin_scanbus(struct CdrskiN *skin, int flag) else printf("cdrskin: NOTE : There was 1 drives not shown.\n"); printf("cdrskin: HINT : To surely see all drives try option: --devices\n"); - if(pseudo_transport_group!=2000) + if(pseudo_transport_group!=2000000) printf("cdrskin: HINT : or try options: dev=ATA -scanbus\n"); } - return(1); + ret= 1; +ex:; + if(drives_shown!=NULL) + free((char *) drives_shown); + return(ret); } diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index fa75755..e090b04 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.10.03.162719" +#define Cdrskin_timestamP "2006.10.05.142628" diff --git a/libburn/drive.c b/libburn/drive.c index 7b58250..e49a679 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -806,7 +806,8 @@ int burn_drive_find_devno(dev_t devno, char adr[]) /** Try to obtain host,channel,target,lun from path. @return 1 = success , 0 = failure , -1 = severe error */ -int burn_drive_obtain_scsi_adr(char *path, int *host_no, int *channel_no, +int burn_drive_obtain_scsi_adr(char *path, + int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no) { int ret, i; @@ -824,6 +825,7 @@ int burn_drive_obtain_scsi_adr(char *path, int *host_no, int *channel_no, *channel_no = drive_array[i].channel; *target_no = drive_array[i].id; *lun_no = drive_array[i].lun; + *bus_no = drive_array[i].bus_no; if (*host_no < 0 || *channel_no < 0 || *target_no < 0 || *lun_no < 0) return 0; @@ -831,21 +833,22 @@ int burn_drive_obtain_scsi_adr(char *path, int *host_no, int *channel_no, } } - ret = sg_obtain_scsi_adr(path, host_no, channel_no, target_no, lun_no); + ret = sg_obtain_scsi_adr(path, bus_no, host_no, channel_no, + target_no, lun_no); return ret; } /* ts A60923 */ -int burn_drive_convert_scsi_adr(int host_no, int channel_no, int target_no, - int lun_no, char adr[]) +int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no, + int target_no, int lun_no, char adr[]) { char fname[4096],msg[4096+100]; - int i, ret = 0, first = 1; + int i, ret = 0, first = 1, i_bus_no = -1; int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1; - sprintf(msg,"burn_drive_convert_scsi_adr( %d,%d,%d,%d )", - host_no, channel_no, target_no, lun_no); + sprintf(msg,"burn_drive_convert_scsi_adr( %d,%d,%d,%d,%d )", + bus_no, host_no, channel_no, target_no, lun_no); burn_drive_adr_debug_msg(msg, NULL); while (1) { @@ -853,9 +856,11 @@ int burn_drive_convert_scsi_adr(int host_no, int channel_no, int target_no, if(ret <= 0) break; first = 0; - ret = burn_drive_obtain_scsi_adr(fname, &i_host_no, + ret = burn_drive_obtain_scsi_adr(fname, &i_bus_no, &i_host_no, &i_channel_no, &i_target_no, &i_lun_no); if(ret <= 0) + continue; + if(bus_no >=0 && i_bus_no != bus_no) continue; if(host_no >=0 && i_host_no != host_no) continue; @@ -881,23 +886,23 @@ int burn_drive_convert_scsi_adr(int host_no, int channel_no, int target_no, int burn_drive_find_scsi_equiv(char *path, char adr[]) { int ret = 0; - int host_no, channel_no, target_no, lun_no; + int bus_no, host_no, channel_no, target_no, lun_no; char msg[4096]; - ret = burn_drive_obtain_scsi_adr(path, &host_no, &channel_no, - &target_no, &lun_no); + ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no, + &target_no, &lun_no); if(ret <= 0) { sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d\n", path, ret); burn_drive_adr_debug_msg(msg, NULL); return 0; } - sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : %d,%d,%d,%d", - path, host_no, channel_no, target_no, lun_no); + sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : (%d),%d,%d,%d,%d", + path, bus_no, host_no, channel_no, target_no, lun_no); burn_drive_adr_debug_msg(msg, NULL); - ret= burn_drive_convert_scsi_adr(host_no, channel_no, target_no, - lun_no, adr); + ret= burn_drive_convert_scsi_adr(-1, host_no, channel_no, target_no, + lun_no, adr); return ret; } diff --git a/libburn/libburn.h b/libburn/libburn.h index a00358c..2072804 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -568,27 +568,27 @@ int burn_drive_is_enumerable_adr(char *adr); int burn_drive_convert_fs_adr(char *path, char adr[]); /* ts A60923 */ -/** Try to convert a given SCSI address of bus, channel, target, lun into +/** Try to convert a given SCSI address of bus,host,channel,target,lun into a persistent drive address. If a SCSI address component parameter is < 0 then it is not decisive and the first enumerated address which matches the >= 0 parameters is taken as result. + Note: bus and (host,channel) are supposed to be redundant. @param adr An application provided array of at least BURN_DRIVE_ADR_LEN characters size. The persistent address gets copied to it. @return 1 = success , 0 = failure , -1 = severe error */ -int burn_drive_convert_scsi_adr(int host_no, int channel_no, int target_no, - int lun_no, char adr[]); +int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no, + int target_no, int lun_no, char adr[]); -/* ts A60923 */ -/** Try to obtain host,channel,target,lun from path. If there is an SCSI +/* ts A60923 - A61005 */ +/** Try to obtain bus,host,channel,target,lun from path. If there is an SCSI address at all, then this call should succeed with a persistent drive address obtained via burn_drive_get_adr(). It is also supposed to succeed with any device file of a (possibly emulated) SCSI device. @return 1 = success , 0 = failure , -1 = severe error */ -int burn_drive_obtain_scsi_adr(char *path, int *host_no, int *channel_no, - int *target_no, int *lun_no); - +int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no, + int *channel_no, int *target_no, int *lun_no); /** Grab a drive. This must be done before the drive can be used (for reading, writing, etc). diff --git a/libburn/sg.c b/libburn/sg.c index 5f0e68b..bd7b847 100644 --- a/libburn/sg.c +++ b/libburn/sg.c @@ -26,8 +26,8 @@ #include "libdax_msgs.h" extern struct libdax_msgs *libdax_messenger; -static void enumerate_common(char *fname, int host_no, int channel_no, - int target_no, int lun_no); +static void enumerate_common(char *fname, int bus_no, int host_no, + int channel_no, int target_no, int lun_no); /* ts A51221 */ int burn_drive_is_banned(char *device_address); @@ -156,9 +156,6 @@ int sg_is_enumerable_adr(char *adr) ret= sg_give_next_adr(&i, fname, sizeof(fname), first); if(ret <= 0) break; -/* <<< - fprintf(stderr,"libburn experimental: idx %d : %s\n",i,fname); -*/ first = 0; if (strcmp(adr, fname) == 0) return 1; @@ -243,7 +240,7 @@ int sg_open_scsi_siblings(char *path, int driveno, int sibling_fds[], int *sibling_count, int host_no, int channel_no, int id_no, int lun_no) { - int tld, i, ret, fd; + int tld, i, ret, fd, i_bus_no = -1; int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1; char msg[161], fname[81]; @@ -257,7 +254,7 @@ int sg_open_scsi_siblings(char *path, int driveno, for (tld = 0; tldev[tld][0] != 0; tld++) { for (i = 0; i < 32; i++) { sprintf(fname, tldev[tld], i); - ret = sg_obtain_scsi_adr(fname, &i_host_no, + ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no, &i_channel_no, &i_target_no, &i_lun_no); if (ret <= 0) continue; @@ -340,7 +337,7 @@ void ata_enumerate(void) } if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) continue; - enumerate_common(fname, -1, -1, -1, -1); + enumerate_common(fname, -1, -1, -1, -1, -1); } } @@ -348,6 +345,7 @@ void sg_enumerate(void) { struct sg_scsi_id sid; int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret; + int bus_no = -1; char fname[10]; for (i = 0; i < 32; i++) { @@ -362,6 +360,13 @@ void sg_enumerate(void) /* found a drive */ ioctl(fd, SG_GET_SCSI_ID, &sid); + +#ifdef SCSI_IOCTL_GET_BUS_NUMBER + /* Hearsay A61005 */ + if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus_no) == -1) + bus_no = -1; +#endif + if (sg_close_drive_fd(fname, -1, &fd, sid.scsi_type == TYPE_ROM ) <= 0) continue; @@ -381,20 +386,27 @@ void sg_enumerate(void) /* the final occupation will be done in sg_grab() */ sg_release_siblings(sibling_fds, &sibling_count); } - - enumerate_common(fname, sid.host_no, sid.channel, - sid.scsi_id, sid.lun); +#ifdef SCSI_IOCTL_GET_BUS_NUMBER + if(bus_no == -1) + bus_no = 1000 * (sid.host_no + 1) + sid.channel; +#else + bus_no = sid.host_no; +#endif + enumerate_common(fname, bus_no, sid.host_no, sid.channel, + sid.scsi_id, sid.lun); } } -/* ts A60923 : introduced new SCSI parameters */ -static void enumerate_common(char *fname, int host_no, int channel_no, - int target_no, int lun_no) + +/* ts A60923 - A61005 : introduced new SCSI parameters */ +static void enumerate_common(char *fname, int bus_no, int host_no, + int channel_no, int target_no, int lun_no) { int i; struct burn_drive *t; struct burn_drive out; /* ts A60923 */ + out.bus_no = bus_no; out.host = host_no; out.id = target_no; out.channel = channel_no; @@ -731,7 +743,7 @@ enum response scsi_error(struct burn_drive *d, unsigned char *sense, /** Try to obtain SCSI address parameters. @return 1 is success , 0 is failure */ -int sg_obtain_scsi_adr(char *path, int *host_no, int *channel_no, +int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no) { int fd, ret; @@ -749,8 +761,14 @@ int sg_obtain_scsi_adr(char *path, int *host_no, int *channel_no, if(fd < 0) return 0; +#ifdef SCSI_IOCTL_GET_BUS_NUMBER + /* Hearsay A61005 */ + if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus_no) == -1) + *bus_no = -1; +#endif + /* http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/scsi_g_idlun.html */ - ret= ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun); + ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun); sg_close_drive_fd(path, -1, &fd, 0); if (ret == -1) @@ -759,5 +777,11 @@ int sg_obtain_scsi_adr(char *path, int *host_no, int *channel_no, *channel_no= (idlun.x>>16)&255; *target_no= (idlun.x)&255; *lun_no= (idlun.x>>8)&255; +#ifdef SCSI_IOCTL_GET_BUS_NUMBER + if(*bus_no == -1) + *bus_no = 1000 * (*host_no + 1) + *channel_no; +#else + *bus_no= *host_no; +#endif return 1; } diff --git a/libburn/sg.h b/libburn/sg.h index ec92ecf..02a64c0 100644 --- a/libburn/sg.h +++ b/libburn/sg.h @@ -15,7 +15,7 @@ int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry); /* ts A60922 ticket 33 */ int sg_give_next_adr(int *idx, char adr[], int adr_size, int initialize); int sg_is_enumerable_adr(char *adr); -int sg_obtain_scsi_adr(char *path, int *host_no, int *channel_no, +int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no); /* ts A60926 : ticket 33 ++ */ diff --git a/libburn/transport.h b/libburn/transport.h index cbb5027..47ae092 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -95,6 +95,7 @@ struct scsi_mode_data /** Gets initialized in enumerate_common() and burn_drive_register() */ struct burn_drive { + int bus_no; int host; int id; int channel;