1 /* Copyright 2000 Enhanced Software Technologies Inc.
2 * Released under terms of the GNU General Public License as
3 * required by the license on 'mtxl.c'.
7 * $Date: 2001/06/05 17:10:21 $
11 /* What this does: Basically dumps out contents of:
12 * Mode Sense: Element Address Assignment Page (0x1d)
13 * 1Eh (Transport Geometry Parameters) has a bit which indicates is
14 * a robot is capable of rotating the media. It`s the
15 * `Rotate` bit, byte 2, bit 1.
16 * Device Capabilities page (0x1f)
17 * Inquiry -- prints full inquiry info.
22 * If there is a byte 55, we use the Exabyte extension to
23 * print out whether we have a bar code reader or not. This is
26 * Next, we request element status on the drives. We do not
27 * request volume tags though. If Exabyte
28 * extensions are supported, we report the following information for
32 * EXCEPT (with ASC and ASCQ), if there is a problem.
33 * SCSI address and LUN
34 * Tape drive Serial number
42 DEVICE_TYPE MediumChangerFD; /* historic purposes... */
46 /* A table for printing out the peripheral device type as ASCII. */
47 static char *PeripheralDeviceType[32] = {
63 "Bridging Expander", /* 0x10 */
64 "Reserved", /* 0x11 */
65 "Reserved", /* 0x12 */
66 "Reserved", /* 0x13 */
67 "Reserved", /* 0x14 */
68 "Reserved", /* 0x15 */
69 "Reserved", /* 0x16 */
70 "Reserved", /* 0x17 */
71 "Reserved", /* 0x18 */
72 "Reserved", /* 0x19 */
73 "Reserved", /* 0x1a */
74 "Reserved", /* 0x1b */
75 "Reserved", /* 0x1c */
76 "Reserved", /* 0x1d */
77 "Reserved", /* 0x1e */
82 /* okay, now for the structure of an Element Address Assignment Page: */
85 unsigned char Page_Code;
86 unsigned char Parameter_Length;
87 unsigned char MediumTransportElementAddress[2];
88 unsigned char NumMediumTransportElements[2];
89 unsigned char FirstStorageElementAdddress[2];
90 unsigned char NumStorageElements[2];
91 unsigned char FirstImportExportElementAddress[2];
92 unsigned char NumImportExportElements[2];
93 unsigned char FirstDataTransferElementAddress[2];
94 unsigned char NumDataTransferElements[2];
95 unsigned char Reserved[2];
98 /* okay, now for the structure of a transport geometry
101 typedef struct TGDP {
102 unsigned char Page_Code;
103 unsigned char ParameterLength;
104 unsigned char Rotate;
105 unsigned char ElementNumber; /* we don't care about this... */
109 /* Structure of the Device Capabilities Page: */
111 unsigned char Page_Code;
112 unsigned char ParameterLength;
113 unsigned char CanStore; /* bits about whether elements can store carts */
114 unsigned char Reserved;
115 unsigned char MT_Xfer; /* bits about whether mt->xx xfers work. */
116 unsigned char ST_Xfer; /* bits about whether st->xx xfers work. */
117 unsigned char IE_Xfer; /* bits about whether id->xx xfers work. */
118 unsigned char DT_Xfer; /* bits about whether DT->xx xfers work. */
119 unsigned char Reserved2[12]; /* more reserved data */
127 /* Okay, now for the inquiry information: */
129 static void ReportInquiry(DEVICE_TYPE MediumChangerFD)
131 RequestSense_T RequestSense;
135 Inquiry = RequestInquiry(MediumChangerFD,&RequestSense);
138 PrintRequestSense(&RequestSense);
139 FatalError("INQUIRY Command Failed\n");
142 printf("Product Type: %s\n",PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
143 printf("Vendor ID: '");
144 for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
145 printf("%c", Inquiry->VendorIdentification[i]);
146 printf("'\nProduct ID: '");
147 for (i = 0; i < sizeof(Inquiry->ProductIdentification); i++)
148 printf("%c", Inquiry->ProductIdentification[i]);
149 printf("'\nRevision: '");
150 for (i = 0; i < sizeof(Inquiry->ProductRevisionLevel); i++)
151 printf("%c", Inquiry->ProductRevisionLevel[i]);
153 if (Inquiry->MChngr) { /* check the attached-media-changer bit... */
154 printf("Attached Changer: Yes\n");
156 printf("Attached Changer: No\n");
158 /* Now see if we have a bar code flag: */
159 if (Inquiry->AdditionalLength > 50) { /* see if we have 56 bytes: */
160 if (Inquiry->VendorFlags & 1) {
161 printf("Bar Code Reader: Yes\n");
163 printf("Bar Code Reader: No\n");
167 free(Inquiry); /* well, we're about to exit, but ... */
171 /*********** MODE SENSE *******************/
172 /* We need 3 different mode sense pages. This is a generic
173 * routine for obtaining mode sense pages.
177 *mode_sense(DEVICE_TYPE fd, int pagenum, int alloc_len, RequestSense_T *RequestSense) {
179 unsigned char *input_buffer; /*the input buffer -- has junk prepended to
183 unsigned char *retval; /* the return value. */
186 if (alloc_len > 255) {
187 FatalError("mode_sense(6) can only read up to 255 characters!\n");
190 input_buffer=(unsigned char *)xzmalloc(256); /* overdo it, eh? */
192 /* clear the sense buffer: */
193 slow_bzero((char *)RequestSense,sizeof(RequestSense_T));
196 /* returns an array of bytes in the page, or, if not possible, NULL. */
197 CDB[0]=0x1a; /* Mode Sense(6) */
199 CDB[2]=pagenum; /* the page to read. */
201 CDB[4]=255; /* allocation length. This does max of 256 bytes! */
204 if (SCSI_ExecuteCommand(fd,Input,&CDB,6,
205 input_buffer,255,RequestSense) != 0) {
206 #ifdef DEBUG_MODE_SENSE
207 fprintf(stderr,"Could not execute mode sense...\n");
210 return NULL; /* sorry, couldn't do it. */
213 /* First skip past any header.... */
214 tmp=input_buffer+4+input_buffer[3];
215 /* now find out real length of page... */
217 retval=xmalloc(pagelen);
218 /* and copy our data to the new page. */
219 for (i=0;i<pagelen;i++) {
222 /* okay, free our input buffer: */
227 /* Report the Element Address Assignment Page */
228 static EAAP_Type *ReportEAAP(DEVICE_TYPE MediumChangerFD) {
230 RequestSense_T RequestSense;
232 EAAP=(EAAP_Type *)mode_sense(MediumChangerFD,0x1d,sizeof(EAAP_Type),&RequestSense);
235 printf("EAAP: No\n");
239 /* we did get an EAAP, so do our thing: */
240 printf("EAAP: Yes\n");
241 printf("Number of Medium Transport Elements: %d\n", ( ((unsigned int)EAAP->NumMediumTransportElements[0]<<8) + (unsigned int)EAAP->NumMediumTransportElements[1]));
242 printf("Number of Storage Elements: %d\n", ( ((unsigned int)EAAP->NumStorageElements[0]<<8) + (unsigned int)EAAP->NumStorageElements[1]));
243 printf("Number of Import/Export Element Elements: %d\n", ( ((unsigned int)EAAP->NumImportExportElements[0]<<8) + (unsigned int)EAAP->NumImportExportElements[1]));
244 printf("Number of Data Transfer Elements: %d\n", ( ((unsigned int)EAAP->NumDataTransferElements[0]<<8) + (unsigned int)EAAP->NumDataTransferElements[1]));
249 /* See if we can get some invert information: */
251 static void Report_TGDP(DEVICE_TYPE MediumChangerFD) {
254 RequestSense_T RequestSense;
256 result=(TGDP_Type *)mode_sense(MediumChangerFD,0x1e,255,&RequestSense);
259 printf("Transport Geometry Descriptor Page: No\n");
263 printf("Transport Geometry Descriptor Page: Yes\n");
265 /* Now print out the invert bit: */
266 if ( result->Rotate & 1 ) {
267 printf("Invertable: Yes\n");
269 printf("Invertable: No\n");
275 /* Okay, let's get the Device Capabilities Page. We don't care
276 * about much here, just whether 'mtx transfer' will work (i.e.,
280 static void Report_DCP(DEVICE_TYPE MediumChangerFD) {
282 RequestSense_T RequestSense;
285 result=(DCP_Type *)mode_sense(MediumChangerFD,0x1f,sizeof(DCP_Type),&RequestSense);
287 printf("Device Configuration Page: No\n");
291 printf("Device Configuration Page: Yes\n");
293 /* okay, now see if we can do xfers: */
294 if (result->ST_Xfer & ST_BIT) {
295 printf("Can Transfer: Yes\n");
297 printf("Can Transfer: No\n");
299 /* We don't care about anything else at the moment, eventually we
300 * do want to add the inport/export stuff here too...
307 FatalError("Usage: loaderinfo -f <generic-device>\n");
311 /* we only have one argument: "-f <device>". */
312 int main(int argc, char **argv) {
318 fprintf(stderr,"argc=%d",argc);
322 if (strcmp(argv[1],"-f")!=0) {
327 fd=SCSI_OpenDevice(filename);
329 /* Now to call the various routines: */