diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2007-12-28 16:21:07 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2007-12-28 16:21:07 +0000 |
commit | 1b13a61c1674815943b907f246443a2f77322491 (patch) | |
tree | 7755b56255f37fea6207e63308efe581f7870b86 /sys/dev/ata | |
parent | 72cfb58a94217ff9e2a3702e5d361663d7c66a37 (diff) |
implement emulation of vpd page 83, the device identification page. if the
disk provides a wwn, use it, otherwise do our best to generate an id from
the model and serial number.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/atascsi.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c index 1fe99ac16ad..8e231a2ea2a 100644 --- a/sys/dev/ata/atascsi.c +++ b/sys/dev/ata/atascsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atascsi.c,v 1.55 2007/12/28 16:19:14 dlg Exp $ */ +/* $OpenBSD: atascsi.c,v 1.56 2007/12/28 16:21:06 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -75,6 +75,7 @@ void atascsi_disk_cmd_done(struct ata_xfer *); int atascsi_disk_inq(struct scsi_xfer *); int atascsi_disk_inquiry(struct scsi_xfer *); int atascsi_disk_serial(struct scsi_xfer *); +int atascsi_disk_ident(struct scsi_xfer *); int atascsi_disk_capacity(struct scsi_xfer *); int atascsi_disk_sync(struct scsi_xfer *); void atascsi_disk_sync_done(struct ata_xfer *); @@ -476,6 +477,8 @@ atascsi_disk_inq(struct scsi_xfer *xs) switch (inq->pagecode) { case SI_PG_SERIAL: return (atascsi_disk_serial(xs)); + case SI_PG_DEVID: + return (atascsi_disk_ident(xs)); default: return (atascsi_done(xs, XS_DRIVER_STUFFUP)); } @@ -569,6 +572,58 @@ atascsi_disk_serial(struct scsi_xfer *xs) } int +atascsi_disk_ident(struct scsi_xfer *xs) +{ + struct scsi_link *link = xs->sc_link; + struct atascsi *as = link->adapter_softc; + struct ata_port *ap = as->as_ports[link->target]; + struct { + struct scsi_vpd_hdr hdr; + struct scsi_vpd_devid_hdr devid_hdr; + u_int8_t devid[68]; + } pg; + u_int8_t *p; + size_t pg_len; + + bzero(&pg, sizeof(pg)); + if (ap->ap_identify.features87 & ATA_ID_F87_WWN) { + pg_len = 8; + + pg.devid_hdr.pi_code = VPD_DEVID_CODE_BINARY; + pg.devid_hdr.flags = VPD_DEVID_ASSOC_LU | VPD_DEVID_TYPE_NAA; + + /* XXX ata_identify field(s) should be renamed */ + bcopy(&ap->ap_identify.naa_ieee_oui, pg.devid, pg_len); + } else { + pg_len = 68; + + pg.devid_hdr.pi_code = VPD_DEVID_CODE_ASCII; + pg.devid_hdr.flags = VPD_DEVID_ASSOC_LU | VPD_DEVID_TYPE_T10; + + p = pg.devid; + bcopy("ATA ", p, 8); + p += 8; + bcopy(ap->ap_identify.model, p, + sizeof(ap->ap_identify.model)); + p += sizeof(ap->ap_identify.model); + bcopy(ap->ap_identify.serial, p, + sizeof(ap->ap_identify.serial)); + } + + pg.devid_hdr.len = pg_len; + pg_len += sizeof(pg.devid_hdr); + + pg.hdr.device = T_DIRECT; + pg.hdr.page_code = SI_PG_DEVID; + pg.hdr.page_length = pg_len; + pg_len += sizeof(pg.hdr); + + bcopy(&pg, xs->data, MIN(pg_len, xs->datalen)); + + return (atascsi_done(xs, XS_NOERROR)); +} + +int atascsi_disk_sync(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; |