1/*
2 * scsi_serial.c
3 *
4 * Code related to requesting and getting an id from a scsi device
5 *
6 * Copyright (C) IBM Corp. 2003
7 *
8 * Author:
9 *	Patrick Mansfield<patmans@us.ibm.com>
10 *
11 *	This program is free software; you can redistribute it and/or modify it
12 *	under the terms of the GNU General Public License as published by the
13 *	Free Software Foundation version 2 of the License.
14 */
15
16#include <sys/types.h>
17#include <sys/ioctl.h>
18#include <stdio.h>
19#include <errno.h>
20#include <string.h>
21#include <fcntl.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <syslog.h>
25#include <scsi/sg.h>
26
27#include "../../udev.h"
28#include "scsi.h"
29#include "scsi_id.h"
30#include "scsi_id_version.h"
31
32/*
33 * A priority based list of id, naa, and binary/ascii for the identifier
34 * descriptor in VPD page 0x83.
35 *
36 * Brute force search for a match starting with the first value in the
37 * following id_search_list. This is not a performance issue, since there
38 * is normally one or some small number of descriptors.
39 */
40static const struct scsi_id_search_values id_search_list[] = {
41	{ SCSI_ID_NAA,	SCSI_ID_NAA_IEEE_REG_EXTENDED,	SCSI_ID_BINARY },
42	{ SCSI_ID_NAA,	SCSI_ID_NAA_IEEE_REG_EXTENDED,	SCSI_ID_ASCII },
43	{ SCSI_ID_NAA,	SCSI_ID_NAA_IEEE_REG,	SCSI_ID_BINARY },
44	{ SCSI_ID_NAA,	SCSI_ID_NAA_IEEE_REG,	SCSI_ID_ASCII },
45	/*
46	 * Devices already exist using NAA values that are now marked
47	 * reserved. These should not conflict with other values, or it is
48	 * a bug in the device. As long as we find the IEEE extended one
49	 * first, we really don't care what other ones are used. Using
50	 * don't care here means that a device that returns multiple
51	 * non-IEEE descriptors in a random order will get different
52	 * names.
53	 */
54	{ SCSI_ID_NAA,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_BINARY },
55	{ SCSI_ID_NAA,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_ASCII },
56	{ SCSI_ID_EUI_64,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_BINARY },
57	{ SCSI_ID_EUI_64,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_ASCII },
58	{ SCSI_ID_T10_VENDOR,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_BINARY },
59	{ SCSI_ID_T10_VENDOR,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_ASCII },
60	{ SCSI_ID_VENDOR_SPECIFIC,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_BINARY },
61	{ SCSI_ID_VENDOR_SPECIFIC,	SCSI_ID_NAA_DONT_CARE,	SCSI_ID_ASCII },
62};
63
64static const char hex_str[]="0123456789abcdef";
65
66/*
67 * Values returned in the result/status, only the ones used by the code
68 * are used here.
69 */
70
71#define DID_NO_CONNECT			0x01	/* Unable to connect before timeout */
72#define DID_BUS_BUSY			0x02	/* Bus remain busy until timeout */
73#define DID_TIME_OUT			0x03	/* Timed out for some other reason */
74#define DRIVER_TIMEOUT			0x06
75#define DRIVER_SENSE			0x08	/* Sense_buffer has been set */
76
77/* The following "category" function returns one of the following */
78#define SG_ERR_CAT_CLEAN		0	/* No errors or other information */
79#define SG_ERR_CAT_MEDIA_CHANGED	1	/* interpreted from sense buffer */
80#define SG_ERR_CAT_RESET		2	/* interpreted from sense buffer */
81#define SG_ERR_CAT_TIMEOUT		3
82#define SG_ERR_CAT_RECOVERED		4 	/* Successful command after recovered err */
83#define SG_ERR_CAT_NOTSUPPORTED 	5	/* Illegal / unsupported command */
84#define SG_ERR_CAT_SENSE		98	/* Something else in the sense buffer */
85#define SG_ERR_CAT_OTHER		99	/* Some other error/warning */
86
87static int sg_err_category_new(int scsi_status, int msg_status, int
88			       host_status, int driver_status, const
89			       unsigned char *sense_buffer, int sb_len)
90{
91	scsi_status &= 0x7e;
92
93
94	/*
95	 * checks msg_status
96	 */
97	if (!scsi_status && !msg_status && !host_status && !driver_status)
98		return SG_ERR_CAT_CLEAN;
99
100	if ((scsi_status == SCSI_CHECK_CONDITION) ||
101	    (scsi_status == SCSI_COMMAND_TERMINATED) ||
102	    ((driver_status & 0xf) == DRIVER_SENSE)) {
103		if (sense_buffer && (sb_len > 2)) {
104			int sense_key;
105			unsigned char asc;
106
107			if (sense_buffer[0] & 0x2) {
108				sense_key = sense_buffer[1] & 0xf;
109				asc = sense_buffer[2];
110			} else {
111				sense_key = sense_buffer[2] & 0xf;
112				asc = (sb_len > 12) ? sense_buffer[12] : 0;
113			}
114
115			if (sense_key == RECOVERED_ERROR)
116				return SG_ERR_CAT_RECOVERED;
117			else if (sense_key == UNIT_ATTENTION) {
118				if (0x28 == asc)
119					return SG_ERR_CAT_MEDIA_CHANGED;
120				if (0x29 == asc)
121					return SG_ERR_CAT_RESET;
122			} else if (sense_key == ILLEGAL_REQUEST) {
123				return SG_ERR_CAT_NOTSUPPORTED;
124			}
125		}
126		return SG_ERR_CAT_SENSE;
127	}
128	if (!host_status) {
129		if ((host_status == DID_NO_CONNECT) ||
130		    (host_status == DID_BUS_BUSY) ||
131		    (host_status == DID_TIME_OUT))
132			return SG_ERR_CAT_TIMEOUT;
133	}
134	if (!driver_status) {
135		if (driver_status == DRIVER_TIMEOUT)
136			return SG_ERR_CAT_TIMEOUT;
137	}
138	return SG_ERR_CAT_OTHER;
139}
140
141static int sg_err_category3(struct sg_io_hdr *hp)
142{
143	return sg_err_category_new(hp->status, hp->msg_status,
144				   hp->host_status, hp->driver_status,
145				   hp->sbp, hp->sb_len_wr);
146}
147
148static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
149{
150	unsigned char *sense_buffer;
151	int s;
152	int sb_len;
153	int code;
154	int sense_class;
155	int sense_key;
156	int descriptor_format;
157	int asc, ascq;
158#ifdef DUMP_SENSE
159	char out_buffer[256];
160	int i, j;
161#endif
162
163
164	dbg("got check condition\n");
165
166	sb_len = io->sb_len_wr;
167	if (sb_len < 1) {
168		info("%s: sense buffer empty", dev_scsi->kernel);
169		return -1;
170	}
171
172	sense_buffer = io->sbp;
173	sense_class = (sense_buffer[0] >> 4) & 0x07;
174	code = sense_buffer[0] & 0xf;
175
176	if (sense_class == 7) {
177		/*
178		 * extended sense data.
179		 */
180		s = sense_buffer[7] + 8;
181		if (sb_len < s) {
182			info("%s: sense buffer too small %d bytes, %d bytes too short",
183			    dev_scsi->kernel, sb_len, s - sb_len);
184			return -1;
185		}
186		if ((code == 0x0) || (code == 0x1)) {
187			descriptor_format = 0;
188			sense_key = sense_buffer[2] & 0xf;
189			if (s < 14) {
190				/*
191				 * Possible?
192				 */
193				info("%s: sense result too" " small %d bytes",
194				    dev_scsi->kernel, s);
195				return -1;
196			}
197			asc = sense_buffer[12];
198			ascq = sense_buffer[13];
199		} else if ((code == 0x2) || (code == 0x3)) {
200			descriptor_format = 1;
201			sense_key = sense_buffer[1] & 0xf;
202			asc = sense_buffer[2];
203			ascq = sense_buffer[3];
204		} else {
205			info("%s: invalid sense code 0x%x",
206			    dev_scsi->kernel, code);
207			return -1;
208		}
209		info("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x",
210		    dev_scsi->kernel, sense_key, asc, ascq);
211	} else {
212		if (sb_len < 4) {
213			info("%s: sense buffer too small %d bytes, %d bytes too short",
214			    dev_scsi->kernel, sb_len, 4 - sb_len);
215			return -1;
216		}
217
218		if (sense_buffer[0] < 15)
219			info("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f);
220		else
221			info("%s: sense = %2x %2x",
222			    dev_scsi->kernel, sense_buffer[0], sense_buffer[2]);
223		info("%s: non-extended sense class %d code 0x%0x",
224		    dev_scsi->kernel, sense_class, code);
225
226	}
227
228#ifdef DUMP_SENSE
229	for (i = 0, j = 0; (i < s) && (j < 254); i++) {
230		dbg("i %d, j %d\n", i, j);
231		out_buffer[j++] = hex_str[(sense_buffer[i] & 0xf0) >> 4];
232		out_buffer[j++] = hex_str[sense_buffer[i] & 0x0f];
233		out_buffer[j++] = ' ';
234	}
235	out_buffer[j] = '\0';
236	info("%s: sense dump:", dev_scsi->kernel);
237	info("%s: %s", dev_scsi->kernel, out_buffer);
238
239#endif
240	return -1;
241}
242
243static int scsi_dump(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
244{
245	if (!io->status && !io->host_status && !io->msg_status &&
246	    !io->driver_status) {
247		/*
248		 * Impossible, should not be called.
249		 */
250		info("%s: called with no error", __FUNCTION__);
251		return -1;
252	}
253
254	info("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
255	    dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
256	if (io->status == SCSI_CHECK_CONDITION)
257		return scsi_dump_sense(dev_scsi, io);
258	else
259		return -1;
260}
261
262static int scsi_inquiry(struct sysfs_device *dev_scsi, int fd,
263			unsigned char evpd, unsigned char page,
264			unsigned char *buf, unsigned int buflen)
265{
266	unsigned char inq_cmd[INQUIRY_CMDLEN] =
267		{ INQUIRY_CMD, evpd, page, 0, buflen, 0 };
268	unsigned char sense[SENSE_BUFF_LEN];
269	struct sg_io_hdr io_hdr;
270	int retval;
271	int retry = 3; /* rather random */
272
273	if (buflen > SCSI_INQ_BUFF_LEN) {
274		info("buflen %d too long", buflen);
275		return -1;
276	}
277
278resend:
279	dbg("%s evpd %d, page 0x%x\n", dev_scsi->kernel, evpd, page);
280
281	memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
282	io_hdr.interface_id = 'S';
283	io_hdr.cmd_len = sizeof(inq_cmd);
284	io_hdr.mx_sb_len = sizeof(sense);
285	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
286	io_hdr.dxfer_len = buflen;
287	io_hdr.dxferp = buf;
288	io_hdr.cmdp = inq_cmd;
289	io_hdr.sbp = sense;
290	io_hdr.timeout = DEF_TIMEOUT;
291
292	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
293		info("%s: ioctl failed: %s", dev_scsi->kernel, strerror(errno));
294		retval = -1;
295		goto error;
296	}
297
298	retval = sg_err_category3(&io_hdr);
299
300	switch (retval) {
301		case SG_ERR_CAT_NOTSUPPORTED:
302			buf[1] = 0;
303			/* Fallthrough */
304		case SG_ERR_CAT_CLEAN:
305		case SG_ERR_CAT_RECOVERED:
306			retval = 0;
307			break;
308
309		default:
310			retval = scsi_dump(dev_scsi, &io_hdr);
311	}
312
313	if (!retval) {
314		retval = buflen;
315	} else if (retval > 0) {
316		if (--retry > 0) {
317			dbg("%s: Retrying ...\n", dev_scsi->kernel);
318			goto resend;
319		}
320		retval = -1;
321	}
322
323error:
324	if (retval < 0)
325		info("%s: Unable to get INQUIRY vpd %d page 0x%x.",
326		    dev_scsi->kernel, evpd, page);
327
328	return retval;
329}
330
331/* Get list of supported EVPD pages */
332static int do_scsi_page0_inquiry(struct sysfs_device *dev_scsi, int fd,
333				 unsigned char *buffer, unsigned int len)
334{
335	int retval;
336	const char *vendor;
337
338	memset(buffer, 0, len);
339	retval = scsi_inquiry(dev_scsi, fd, 1, 0x0, buffer, len);
340	if (retval < 0)
341		return 1;
342
343	if (buffer[1] != 0) {
344		info("%s: page 0 not available.", dev_scsi->kernel);
345		return 1;
346	}
347	if (buffer[3] > len) {
348		info("%s: page 0 buffer too long %d", dev_scsi->kernel,  buffer[3]);
349		return 1;
350	}
351
352	/*
353	 * Following check is based on code once included in the 2.5.x
354	 * kernel.
355	 *
356	 * Some ill behaved devices return the standard inquiry here
357	 * rather than the evpd data, snoop the data to verify.
358	 */
359	if (buffer[3] > MODEL_LENGTH) {
360		/*
361		 * If the vendor id appears in the page assume the page is
362		 * invalid.
363		 */
364		vendor = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
365		if (!vendor) {
366			info("%s: cannot get model attribute", dev_scsi->kernel);
367			return 1;
368		}
369		if (!strncmp((char *)&buffer[VENDOR_LENGTH], vendor, VENDOR_LENGTH)) {
370			info("%s: invalid page0 data", dev_scsi->kernel);
371			return 1;
372		}
373	}
374	return 0;
375}
376
377/*
378 * The caller checks that serial is long enough to include the vendor +
379 * model.
380 */
381static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial)
382{
383	const char *attr;
384	int ind;
385
386	attr = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
387	if (!attr) {
388		info("%s: cannot get vendor attribute", dev_scsi->kernel);
389		return 1;
390	}
391	strncpy(serial, attr, VENDOR_LENGTH);
392	ind = strlen(serial) - 1;
393
394	attr = sysfs_attr_get_value(dev_scsi->devpath, "model");
395	if (!attr) {
396		info("%s: cannot get model attribute", dev_scsi->kernel);
397		return 1;
398	}
399	strncat(serial, attr, MODEL_LENGTH);
400	ind = strlen(serial) - 1;
401	ind++;
402
403	/*
404	 * This is not a complete check, since we are using strncat/cpy
405	 * above, ind will never be too large.
406	 */
407	if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
408		info("%s: expected length %d, got length %d",
409		     dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
410		return 1;
411	}
412	return ind;
413}
414
415/**
416 * check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill
417 * serial number.
418 **/
419static int check_fill_0x83_id(struct sysfs_device *dev_scsi,
420			      unsigned char *page_83,
421			      const struct scsi_id_search_values
422			      *id_search, char *serial, char *serial_short, int max_len)
423{
424	int i, j, s, len;
425
426	/*
427	 * ASSOCIATION must be with the device (value 0)
428	 */
429	if ((page_83[1] & 0x30) != 0)
430		return 1;
431
432	if ((page_83[1] & 0x0f) != id_search->id_type)
433		return 1;
434
435	/*
436	 * Possibly check NAA sub-type.
437	 */
438	if ((id_search->naa_type != SCSI_ID_NAA_DONT_CARE) &&
439	    (id_search->naa_type != (page_83[4] & 0xf0) >> 4))
440		return 1;
441
442	/*
443	 * Check for matching code set - ASCII or BINARY.
444	 */
445	if ((page_83[0] & 0x0f) != id_search->code_set)
446		return 1;
447
448	/*
449	 * page_83[3]: identifier length
450	 */
451	len = page_83[3];
452	if ((page_83[0] & 0x0f) != SCSI_ID_ASCII)
453		/*
454		 * If not ASCII, use two bytes for each binary value.
455		 */
456		len *= 2;
457
458	/*
459	 * Add one byte for the NUL termination, and one for the id_type.
460	 */
461	len += 2;
462	if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
463		len += VENDOR_LENGTH + MODEL_LENGTH;
464
465	if (max_len < len) {
466		info("%s: length %d too short - need %d",
467		    dev_scsi->kernel, max_len, len);
468		return 1;
469	}
470
471	serial[0] = hex_str[id_search->id_type];
472
473	/*
474	 * For SCSI_ID_VENDOR_SPECIFIC prepend the vendor and model before
475	 * the id since it is not unique across all vendors and models,
476	 * this differs from SCSI_ID_T10_VENDOR, where the vendor is
477	 * included in the identifier.
478	 */
479	if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
480		if (prepend_vendor_model(dev_scsi, &serial[1]) < 0) {
481			dbg("prepend failed\n");
482			return 1;
483		}
484
485	i = 4; /* offset to the start of the identifier */
486	s = j = strlen(serial);
487	if ((page_83[0] & 0x0f) == SCSI_ID_ASCII) {
488		/*
489		 * ASCII descriptor.
490		 */
491		while (i < (4 + page_83[3]))
492			serial[j++] = page_83[i++];
493	} else {
494		/*
495		 * Binary descriptor, convert to ASCII, using two bytes of
496		 * ASCII for each byte in the page_83.
497		 */
498		while (i < (4 + page_83[3])) {
499			serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4];
500			serial[j++] = hex_str[page_83[i] & 0x0f];
501			i++;
502		}
503	}
504
505	strcpy(serial_short, &serial[s]);
506	return 0;
507}
508
509/* Extract the raw binary from VPD 0x83 pre-SPC devices */
510static int check_fill_0x83_prespc3(struct sysfs_device *dev_scsi,
511			           unsigned char *page_83,
512			           const struct scsi_id_search_values
513			           *id_search, char *serial, char *serial_short, int max_len)
514{
515	int i, j;
516
517	dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel);
518	serial[0] = hex_str[id_search->id_type];
519	/* serial has been memset to zero before */
520	j = strlen(serial);	/* j = 1; */
521
522	for (i = 0; i < page_83[3]; ++i) {
523		serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4];
524		serial[j++] = hex_str[ page_83[4+i] & 0x0f];
525	}
526	strcpy(serial_short, serial);
527	return 0;
528}
529
530
531/* Get device identification VPD page */
532static int do_scsi_page83_inquiry(struct sysfs_device *dev_scsi, int fd,
533				  char *serial, char *serial_short, int len)
534{
535	int retval;
536	unsigned int id_ind, j;
537	unsigned char page_83[SCSI_INQ_BUFF_LEN];
538
539	memset(page_83, 0, SCSI_INQ_BUFF_LEN);
540	retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83,
541			      SCSI_INQ_BUFF_LEN);
542	if (retval < 0)
543		return 1;
544
545	if (page_83[1] != PAGE_83) {
546		info("%s: Invalid page 0x83", dev_scsi->kernel);
547		return 1;
548	}
549
550
551	/*
552	 * Model 4, 5, and (some) model 6 EMC Symmetrix devices return
553	 * a page 83 reply according to SCSI-2 format instead of SPC-2/3.
554	 *
555	 * The SCSI-2 page 83 format returns an IEEE WWN in binary
556	 * encoded hexi-decimal in the 16 bytes following the initial
557	 * 4-byte page 83 reply header.
558	 *
559	 * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part
560	 * of an Identification descriptor.  The 3rd byte of the first
561	 * Identification descriptor is a reserved (BSZ) byte field.
562	 *
563	 * Reference the 7th byte of the page 83 reply to determine
564	 * whether the reply is compliant with SCSI-2 or SPC-2/3
565	 * specifications.  A zero value in the 7th byte indicates
566	 * an SPC-2/3 conformant reply, (i.e., the reserved field of the
567	 * first Identification descriptor).  This byte will be non-zero
568	 * for a SCSI-2 conformant page 83 reply from these EMC
569	 * Symmetrix models since the 7th byte of the reply corresponds
570	 * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is,
571	 * 0x006048.
572	 */
573
574	if (page_83[6] != 0)
575		return check_fill_0x83_prespc3(dev_scsi, page_83, id_search_list,
576					       serial, serial_short, len);
577
578	/*
579	 * Search for a match in the prioritized id_search_list.
580	 */
581	for (id_ind = 0;
582	     id_ind < sizeof(id_search_list)/sizeof(id_search_list[0]);
583	     id_ind++) {
584		/*
585		 * Examine each descriptor returned. There is normally only
586		 * one or a small number of descriptors.
587		 */
588		for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) {
589			retval = check_fill_0x83_id(dev_scsi, &page_83[j],
590						    &id_search_list[id_ind],
591						    serial, serial_short, len);
592			dbg("%s id desc %d/%d/%d\n", dev_scsi->kernel,
593				id_search_list[id_ind].id_type,
594				id_search_list[id_ind].naa_type,
595				id_search_list[id_ind].code_set);
596			if (!retval) {
597				dbg("	used\n");
598				return retval;
599			} else if (retval < 0) {
600				dbg("	failed\n");
601				return retval;
602			} else {
603				dbg("	not used\n");
604			}
605		}
606	}
607	return 1;
608}
609
610/*
611 * Get device identification VPD page for older SCSI-2 device which is not
612 * compliant with either SPC-2 or SPC-3 format.
613 *
614 * Return the hard coded error code value 2 if the page 83 reply is not
615 * conformant to the SCSI-2 format.
616 */
617static int do_scsi_page83_prespc3_inquiry(struct sysfs_device *dev_scsi, int fd,
618				          char *serial, char *serial_short, int len)
619{
620	int retval;
621	int i, j;
622	unsigned char page_83[SCSI_INQ_BUFF_LEN];
623
624	memset(page_83, 0, SCSI_INQ_BUFF_LEN);
625	retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
626	if (retval < 0)
627		return 1;
628
629	if (page_83[1] != PAGE_83) {
630		info("%s: Invalid page 0x83", dev_scsi->kernel);
631		return 1;
632	}
633	/*
634	 * Model 4, 5, and (some) model 6 EMC Symmetrix devices return
635	 * a page 83 reply according to SCSI-2 format instead of SPC-2/3.
636	 *
637	 * The SCSI-2 page 83 format returns an IEEE WWN in binary
638	 * encoded hexi-decimal in the 16 bytes following the initial
639	 * 4-byte page 83 reply header.
640	 *
641	 * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part
642	 * of an Identification descriptor.  The 3rd byte of the first
643	 * Identification descriptor is a reserved (BSZ) byte field.
644	 *
645	 * Reference the 7th byte of the page 83 reply to determine
646	 * whether the reply is compliant with SCSI-2 or SPC-2/3
647	 * specifications.  A zero value in the 7th byte indicates
648	 * an SPC-2/3 conformant reply, (i.e., the reserved field of the
649	 * first Identification descriptor).  This byte will be non-zero
650	 * for a SCSI-2 conformant page 83 reply from these EMC
651	 * Symmetrix models since the 7th byte of the reply corresponds
652	 * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is,
653	 * 0x006048.
654	 */
655	if (page_83[6] == 0)
656		return 2;
657
658	serial[0] = hex_str[id_search_list[0].id_type];
659	/*
660	 * The first four bytes contain data, not a descriptor.
661	 */
662	i = 4;
663	j = strlen(serial);
664	/*
665	 * Binary descriptor, convert to ASCII,
666	 * using two bytes of ASCII for each byte
667	 * in the page_83.
668	 */
669	while (i < (page_83[3]+4)) {
670		serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4];
671		serial[j++] = hex_str[page_83[i] & 0x0f];
672		i++;
673	}
674	dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel);
675	return 0;
676}
677
678/* Get unit serial number VPD page */
679static int do_scsi_page80_inquiry(struct sysfs_device *dev_scsi, int fd,
680				  char *serial, char *serial_short, int max_len)
681{
682	int retval;
683	int ser_ind;
684	int i;
685	int len;
686	unsigned char buf[SCSI_INQ_BUFF_LEN];
687
688	memset(buf, 0, SCSI_INQ_BUFF_LEN);
689	retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN);
690	if (retval < 0)
691		return retval;
692
693	if (buf[1] != PAGE_80) {
694		info("%s: Invalid page 0x80", dev_scsi->kernel);
695		return 1;
696	}
697
698	len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3];
699	if (max_len < len) {
700		info("%s: length %d too short - need %d",
701		    dev_scsi->kernel, max_len, len);
702		return 1;
703	}
704	/*
705	 * Prepend 'S' to avoid unlikely collision with page 0x83 vendor
706	 * specific type where we prepend '0' + vendor + model.
707	 */
708	serial[0] = 'S';
709	ser_ind = prepend_vendor_model(dev_scsi, &serial[1]);
710	if (ser_ind < 0)
711		return 1;
712	len = buf[3];
713	for (i = 4; i < len + 4; i++, ser_ind++)
714		serial[ser_ind] = buf[i];
715	memcpy(serial_short, &buf[4], len);
716	serial_short[len] = '\0';
717	return 0;
718}
719
720int scsi_std_inquiry(struct sysfs_device *dev_scsi, const char *devname,
721		     char *vendor, char *model, char *rev, char *type)
722{
723	int retval;
724	int fd;
725	unsigned char buf[SCSI_INQ_BUFF_LEN];
726
727	dbg("opening %s\n", devname);
728	fd = open(devname, O_RDONLY | O_NONBLOCK);
729	if (fd < 0) {
730		info("%s: cannot open %s: %s",
731		    dev_scsi->kernel, devname, strerror(errno));
732		return 1;
733	}
734
735	memset(buf, 0, SCSI_INQ_BUFF_LEN);
736	retval = scsi_inquiry(dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN);
737	if (retval < 0)
738		return retval;
739
740	memcpy(vendor, buf + 8, 8);
741	memcpy(model, buf + 16, 16);
742	memcpy(rev, buf + 32, 4);
743	sprintf(type,"%x", buf[0] & 0x1f);
744
745	if (close(fd) < 0)
746		info("%s: close failed: %s", dev_scsi->kernel, strerror(errno));
747
748	return 0;
749}
750
751int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname,
752		     int page_code, char *serial, char *serial_short, int len)
753{
754	unsigned char page0[SCSI_INQ_BUFF_LEN];
755	int fd;
756	int ind;
757	int retval;
758
759	memset(serial, 0, len);
760	dbg("opening %s\n", devname);
761	fd = open(devname, O_RDONLY | O_NONBLOCK);
762	if (fd < 0) {
763		info("%s: cannot open %s: %s",
764		    dev_scsi->kernel, devname, strerror(errno));
765		return 1;
766	}
767
768	if (page_code == PAGE_80) {
769		if (do_scsi_page80_inquiry(dev_scsi, fd, serial, serial_short, len)) {
770			retval = 1;
771			goto completed;
772		} else  {
773			retval = 0;
774			goto completed;
775		}
776	} else if (page_code == PAGE_83) {
777		if (do_scsi_page83_inquiry(dev_scsi, fd, serial, serial_short, len)) {
778			retval = 1;
779			goto completed;
780		} else  {
781			retval = 0;
782			goto completed;
783		}
784	} else if (page_code == PAGE_83_PRE_SPC3) {
785		retval = do_scsi_page83_prespc3_inquiry(dev_scsi, fd, serial, serial_short, len);
786		if (retval) {
787			/*
788			 * Fallback to servicing a SPC-2/3 compliant page 83
789			 * inquiry if the page 83 reply format does not
790			 * conform to pre-SPC3 expectations.
791			 */
792			if (retval == 2) {
793				if (do_scsi_page83_inquiry(dev_scsi, fd, serial, serial_short, len)) {
794					retval = 1;
795					goto completed;
796				} else  {
797					retval = 0;
798					goto completed;
799				}
800			}
801			else {
802				retval = 1;
803				goto completed;
804			}
805		} else  {
806			retval = 0;
807			goto completed;
808		}
809	} else if (page_code != 0x00) {
810		info("%s: unsupported page code 0x%d", dev_scsi->kernel, page_code);
811		return 1;
812	}
813
814	/*
815	 * Get page 0, the page of the pages. By default, try from best to
816	 * worst of supported pages: 0x83 then 0x80.
817	 */
818	if (do_scsi_page0_inquiry(dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) {
819		/*
820		 * Don't try anything else. Black list if a specific page
821		 * should be used for this vendor+model, or maybe have an
822		 * optional fall-back to page 0x80 or page 0x83.
823		 */
824		retval = 1;
825		goto completed;
826	}
827
828	dbg("%s: Checking page0\n", dev_scsi->kernel);
829
830	for (ind = 4; ind <= page0[3] + 3; ind++)
831		if (page0[ind] == PAGE_83)
832			if (!do_scsi_page83_inquiry(dev_scsi, fd,
833						    serial, serial_short, len)) {
834				/*
835				 * Success
836				 */
837				retval = 0;
838				goto completed;
839			}
840
841	for (ind = 4; ind <= page0[3] + 3; ind++)
842		if (page0[ind] == PAGE_80)
843			if (!do_scsi_page80_inquiry(dev_scsi, fd,
844						    serial, serial_short, len)) {
845				/*
846				 * Success
847				 */
848				retval = 0;
849				goto completed;
850			}
851	retval = 1;
852completed:
853	if (close(fd) < 0)
854		info("%s: close failed: %s", dev_scsi->kernel, strerror(errno));
855	return retval;
856}
857