-/* $OpenBSD: scsiconf.c,v 1.134 2008/07/22 00:40:37 dlg Exp $ */
+/* $OpenBSD: scsiconf.c,v 1.135 2008/07/22 01:01:31 dlg Exp $ */
/* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
/*
*/
int scsi_probedev(struct scsibus_softc *, int, int);
+void scsi_devid(struct scsi_link *);
+int scsi_devid_pg83(struct scsi_link *);
+
struct scsi_device probe_switch = {
NULL,
NULL,
scsi_probedev(struct scsibus_softc *scsi, int target, int lun)
{
const struct scsi_quirk_inquiry_pattern *finger;
- struct scsi_inquiry_data *inqbuf;
+ struct scsi_inquiry_data *inqbuf;
struct scsi_attach_args sa;
struct scsi_link *sc_link;
struct cfdata *cf;
break;
}
+ scsi_devid(sc_link);
+
if (lun == 0 || scsi->sc_link[target][0] == NULL)
;
else if (sc_link->flags & SDEV_UMASS)
;
+ else if (sc_link->id.d_type != DEVID_NONE &&
+ !DEVID_CMP(&scsi->sc_link[target][0]->id, &sc_link->id))
+ ;
else if (memcmp(inqbuf, &scsi->sc_link[target][0]->inqdata,
sizeof(*inqbuf)) == 0) {
/* The device doesn't distinguish between LUNs. */
return (bestmatch);
}
+
+void
+scsi_devid(struct scsi_link *link)
+{
+ struct {
+ struct scsi_vpd_hdr hdr;
+ u_int8_t list[32];
+ } __packed pg;
+ int pg80 = 0, pg83 = 0, i;
+
+ if (SCSISPC(link->inqdata.version) >= 2) {
+ if (scsi_inquire_vpd(link, &pg, sizeof(pg), SI_PG_SUPPORTED,
+ scsi_autoconf) != 0)
+ return;
+
+ for (i = 0; i < MIN(sizeof(pg.list), pg.hdr.page_length); i++) {
+ switch (pg.list[i]) {
+ case SI_PG_SERIAL:
+ pg80 = 1;
+ break;
+ case SI_PG_DEVID:
+ pg83 = 1;
+ break;
+ }
+ }
+
+ if (pg83 && scsi_devid_pg83(link) == 0)
+ return;
+#ifdef notyet
+ if (pg80 && scsi_devid_pg80(link) == 0)
+ return;
+#endif
+ }
+}
+
+int
+scsi_devid_pg83(struct scsi_link *link)
+{
+ struct scsi_vpd_hdr hdr;
+ struct scsi_vpd_devid_hdr dhdr;
+ u_int8_t *pg, *id;
+ int type, idtype = 0, idlen;
+ int len, pos;
+ int rv;
+
+ rv = scsi_inquire_vpd(link, &hdr, sizeof(hdr), SI_PG_DEVID,
+ scsi_autoconf);
+ if (rv != 0)
+ return (rv);
+
+ len = sizeof(hdr) + hdr.page_length;
+ pg = malloc(len, M_TEMP, M_WAITOK);
+
+ rv = scsi_inquire_vpd(link, pg, len, SI_PG_DEVID, scsi_autoconf);
+ if (rv != 0)
+ goto err;
+
+ pos = sizeof(hdr);
+
+ do {
+ if (len - pos < sizeof(dhdr)) {
+ rv = EIO;
+ goto err;
+ }
+ memcpy(&dhdr, &pg[pos], sizeof(dhdr));
+ pos += sizeof(dhdr);
+ if (len - pos < dhdr.len) {
+ rv = EIO;
+ goto err;
+ }
+
+ if (VPD_DEVID_ASSOC(dhdr.flags) == VPD_DEVID_ASSOC_LU) {
+ type = VPD_DEVID_TYPE(dhdr.flags);
+ switch (type) {
+ case VPD_DEVID_TYPE_NAA:
+ case VPD_DEVID_TYPE_EUI64:
+ case VPD_DEVID_TYPE_T10:
+ if (type >= idtype) {
+ idtype = type;
+ idlen = dhdr.len;
+ id = &pg[pos];
+ }
+ break;
+
+ default:
+ /* skip */
+ break;
+ }
+ }
+
+ pos += dhdr.len;
+ } while (idtype != VPD_DEVID_TYPE_NAA && len != pos);
+
+ if (idtype > 0) {
+ link->id.d_id = malloc(idlen, M_DEVBUF, M_WAITOK);
+
+ switch (idtype) {
+ case VPD_DEVID_TYPE_NAA:
+ link->id.d_type = DEVID_NAA;
+ break;
+ case VPD_DEVID_TYPE_EUI64:
+ link->id.d_type = DEVID_EUI;
+ break;
+ case VPD_DEVID_TYPE_T10:
+ link->id.d_type = DEVID_T10;
+ break;
+ }
+ link->id.d_len = idlen;
+ memcpy(link->id.d_id, id, idlen);
+ } else
+ rv = ENODEV;
+
+err:
+ free(pg, M_TEMP);
+ return (rv);
+}
-/* $OpenBSD: scsiconf.h,v 1.93 2008/06/21 21:11:34 krw Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.94 2008/07/22 01:01:31 dlg Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
#include <machine/cpu.h>
#include <scsi/scsi_debug.h>
+#define DEVID_NONE 0
+#define DEVID_NAA 1
+#define DEVID_EUI 2
+#define DEVID_T10 3
+
+struct devid {
+ int d_type;
+ u_int d_len;
+ u_int8_t *d_id;
+};
+
+#define DEVID_CMP(_a, _b) ( \
+ (_a) != NULL && \
+ (_b) != NULL && \
+ (_a)->d_type != DEVID_NONE && \
+ (_a)->d_type == (_b)->d_type && \
+ (_a)->d_len == (_b)->d_len && \
+ bcmp((_a)->d_id, (_b)->d_id, (_a)->d_len) == 0 \
+)
+
/*
* The following documentation tries to describe the relationship between the
* various structures defined in this file:
void *adapter_softc; /* needed for call to foo_scsi_cmd */
struct scsibus_softc *bus; /* link to the scsibus we're on */
struct scsi_inquiry_data inqdata; /* copy of INQUIRY data from probe */
+ struct devid id;
};
int scsiprint(void *, const char *);