MFprojects/zfsd:
- Add low-level support for SATA Enclosure Management Bridge (SEMB) devices -- SATA equivalents of the SCSI SES/SAF-TE devices. - Add some utility functions for SCSI SAF-TE devices access. Sponsored by: iXsystems, Inc.
This commit is contained in:
parent
76dcec5d09
commit
3089bb2e84
@ -456,7 +456,7 @@ getdevtree(void)
|
||||
case DEV_MATCH_DEVICE: {
|
||||
struct device_match_result *dev_result;
|
||||
char vendor[16], product[48], revision[16];
|
||||
char tmpstr[256];
|
||||
char fw[5], tmpstr[256];
|
||||
|
||||
dev_result =
|
||||
&ccb.cdm.matches[i].result.device_result;
|
||||
@ -495,6 +495,25 @@ getdevtree(void)
|
||||
sizeof(revision));
|
||||
sprintf(tmpstr, "<%s %s>", product,
|
||||
revision);
|
||||
} else if (dev_result->protocol == PROTO_SEMB) {
|
||||
struct sep_identify_data *sid;
|
||||
|
||||
sid = (struct sep_identify_data *)
|
||||
&dev_result->ident_data;
|
||||
cam_strvis(vendor, sid->vendor_id,
|
||||
sizeof(sid->vendor_id),
|
||||
sizeof(vendor));
|
||||
cam_strvis(product, sid->product_id,
|
||||
sizeof(sid->product_id),
|
||||
sizeof(product));
|
||||
cam_strvis(revision, sid->product_rev,
|
||||
sizeof(sid->product_rev),
|
||||
sizeof(revision));
|
||||
cam_strvis(fw, sid->firmware_rev,
|
||||
sizeof(sid->firmware_rev),
|
||||
sizeof(fw));
|
||||
sprintf(tmpstr, "<%s %s %s %s>",
|
||||
vendor, product, revision, fw);
|
||||
} else {
|
||||
sprintf(tmpstr, "<>");
|
||||
}
|
||||
|
@ -108,6 +108,16 @@ ata_op_string(struct ata_cmd *cmd)
|
||||
case 0x51: return ("CONFIGURE_STREAM");
|
||||
case 0x60: return ("READ_FPDMA_QUEUED");
|
||||
case 0x61: return ("WRITE_FPDMA_QUEUED");
|
||||
case 0x67:
|
||||
if (cmd->features == 0xec)
|
||||
return ("SEP_ATTN IDENTIFY");
|
||||
switch (cmd->lba_low) {
|
||||
case 0x00: return ("SEP_ATTN READ BUFFER");
|
||||
case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS");
|
||||
case 0x80: return ("SEP_ATTN WRITE BUFFER");
|
||||
case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC");
|
||||
}
|
||||
return ("SEP_ATTN");
|
||||
case 0x70: return ("SEEK");
|
||||
case 0x87: return ("CFA_TRANSLATE_SECTOR");
|
||||
case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
|
||||
@ -286,6 +296,21 @@ ata_print_ident(struct ata_params *ident_data)
|
||||
printf(" device\n");
|
||||
}
|
||||
|
||||
void
|
||||
semb_print_ident(struct sep_identify_data *ident_data)
|
||||
{
|
||||
char vendor[9], product[17], revision[5], fw[5], in[7], ins[5];
|
||||
|
||||
cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor));
|
||||
cam_strvis(product, ident_data->product_id, 16, sizeof(product));
|
||||
cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision));
|
||||
cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw));
|
||||
cam_strvis(in, ident_data->interface_id, 6, sizeof(in));
|
||||
cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins));
|
||||
printf("<%s %s %s %s> SEMB %s %s device\n",
|
||||
vendor, product, revision, fw, in, ins);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ata_logical_sector_size(struct ata_params *ident_data)
|
||||
{
|
||||
@ -695,3 +720,86 @@ ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry)
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
semb_receive_diagnostic_results(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
uint8_t tag_action, int pcv, uint8_t page_code,
|
||||
uint8_t *data_ptr, uint16_t length, uint32_t timeout)
|
||||
{
|
||||
|
||||
length = min(length, 1020);
|
||||
length = (length + 3) & ~3;
|
||||
cam_fill_ataio(ataio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/CAM_DIR_IN,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
length,
|
||||
timeout);
|
||||
ata_28bit_cmd(ataio, ATA_SEP_ATTN,
|
||||
pcv ? page_code : 0, 0x02, length / 4);
|
||||
}
|
||||
|
||||
void
|
||||
semb_send_diagnostic(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
|
||||
{
|
||||
|
||||
length = min(length, 1020);
|
||||
length = (length + 3) & ~3;
|
||||
cam_fill_ataio(ataio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
length,
|
||||
timeout);
|
||||
ata_28bit_cmd(ataio, ATA_SEP_ATTN,
|
||||
length > 0 ? data_ptr[0] : 0, 0x82, length / 4);
|
||||
}
|
||||
|
||||
void
|
||||
semb_read_buffer(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
uint8_t tag_action, uint8_t page_code,
|
||||
uint8_t *data_ptr, uint16_t length, uint32_t timeout)
|
||||
{
|
||||
|
||||
length = min(length, 1020);
|
||||
length = (length + 3) & ~3;
|
||||
cam_fill_ataio(ataio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/CAM_DIR_IN,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
length,
|
||||
timeout);
|
||||
ata_28bit_cmd(ataio, ATA_SEP_ATTN,
|
||||
page_code, 0x00, length / 4);
|
||||
}
|
||||
|
||||
void
|
||||
semb_write_buffer(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
|
||||
{
|
||||
|
||||
length = min(length, 1020);
|
||||
length = (length + 3) & ~3;
|
||||
cam_fill_ataio(ataio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
length,
|
||||
timeout);
|
||||
ata_28bit_cmd(ataio, ATA_SEP_ATTN,
|
||||
length > 0 ? data_ptr[0] : 0, 0x80, length / 4);
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,20 @@ struct ata_res {
|
||||
u_int8_t sector_count_exp;
|
||||
};
|
||||
|
||||
struct sep_identify_data {
|
||||
uint8_t length; /* Enclosure descriptor length */
|
||||
uint8_t subenc_id; /* Sub-enclosure identifier */
|
||||
uint8_t logical_id[8]; /* Enclosure logical identifier (WWN) */
|
||||
uint8_t vendor_id[8]; /* Vendor identification string */
|
||||
uint8_t product_id[16]; /* Product identification string */
|
||||
uint8_t product_rev[4]; /* Product revision string */
|
||||
uint8_t channel_id; /* Channel identifier */
|
||||
uint8_t firmware_rev[4];/* Firmware revision */
|
||||
uint8_t interface_id[6];/* Interface spec ("S-E-S "/"SAF-TE")*/
|
||||
uint8_t interface_rev[4];/* Interface spec revision */
|
||||
uint8_t vend_spec[11]; /* Vendor specific information */
|
||||
};
|
||||
|
||||
int ata_version(int ver);
|
||||
|
||||
char * ata_op_string(struct ata_cmd *cmd);
|
||||
@ -126,4 +140,26 @@ int ata_speed2revision(u_int speed);
|
||||
int ata_identify_match(caddr_t identbuffer, caddr_t table_entry);
|
||||
int ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry);
|
||||
|
||||
void semb_print_ident(struct sep_identify_data *ident_data);
|
||||
|
||||
void semb_receive_diagnostic_results(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
uint8_t tag_action, int pcv, uint8_t page_code,
|
||||
uint8_t *data_ptr, uint16_t allocation_length, uint32_t timeout);
|
||||
|
||||
void semb_send_diagnostic(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint8_t *data_ptr, uint16_t param_list_length,
|
||||
uint32_t timeout);
|
||||
|
||||
void semb_read_buffer(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
uint8_t tag_action, uint8_t page_code,
|
||||
uint8_t *data_ptr, uint16_t allocation_length, uint32_t timeout);
|
||||
|
||||
void semb_write_buffer(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint8_t *data_ptr, uint16_t param_list_length,
|
||||
uint32_t timeout);
|
||||
|
||||
#endif
|
||||
|
@ -776,6 +776,20 @@ adaasync(void *callback_arg, u_int32_t code,
|
||||
"due to status 0x%x\n", status);
|
||||
break;
|
||||
}
|
||||
case AC_ADVINFO_CHANGED:
|
||||
{
|
||||
uintptr_t buftype;
|
||||
|
||||
buftype = (uintptr_t)arg;
|
||||
if (buftype == CDAI_TYPE_PHYS_PATH) {
|
||||
struct ada_softc *softc;
|
||||
|
||||
softc = periph->softc;
|
||||
disk_attr_changed(softc->disk, "GEOM::physpath",
|
||||
M_NOWAIT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AC_SENT_BDR:
|
||||
case AC_BUS_RESET:
|
||||
{
|
||||
@ -1088,8 +1102,8 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
* them and the only alternative would be to
|
||||
* not attach the device on failure.
|
||||
*/
|
||||
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
|
||||
adaasync, periph, periph->path);
|
||||
xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
|
||||
AC_ADVINFO_CHANGED, adaasync, periph, periph->path);
|
||||
|
||||
/*
|
||||
* Schedule a periodic event to occasionally send an
|
||||
|
@ -93,6 +93,8 @@ typedef enum {
|
||||
PROBE_FULL_INQUIRY,
|
||||
PROBE_PM_PID,
|
||||
PROBE_PM_PRV,
|
||||
PROBE_IDENTIFY_SES,
|
||||
PROBE_IDENTIFY_SAFTE,
|
||||
PROBE_INVALID
|
||||
} probe_action;
|
||||
|
||||
@ -110,6 +112,8 @@ static char *probe_action_text[] = {
|
||||
"PROBE_FULL_INQUIRY",
|
||||
"PROBE_PM_PID",
|
||||
"PROBE_PM_PRV",
|
||||
"PROBE_IDENTIFY_SES",
|
||||
"PROBE_IDENTIFY_SAFTE",
|
||||
"PROBE_INVALID"
|
||||
};
|
||||
|
||||
@ -266,7 +270,8 @@ probeschedule(struct cam_periph *periph)
|
||||
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
|
||||
|
||||
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) ||
|
||||
periph->path->device->protocol == PROTO_SATAPM)
|
||||
periph->path->device->protocol == PROTO_SATAPM ||
|
||||
periph->path->device->protocol == PROTO_SEMB)
|
||||
PROBE_SET_ACTION(softc, PROBE_RESET);
|
||||
else
|
||||
PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
|
||||
@ -300,7 +305,8 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
if (softc->restart) {
|
||||
softc->restart = 0;
|
||||
if ((path->device->flags & CAM_DEV_UNCONFIGURED) ||
|
||||
path->device->protocol == PROTO_SATAPM)
|
||||
path->device->protocol == PROTO_SATAPM ||
|
||||
path->device->protocol == PROTO_SEMB)
|
||||
softc->action = PROBE_RESET;
|
||||
else
|
||||
softc->action = PROBE_IDENTIFY;
|
||||
@ -622,6 +628,30 @@ negotiate:
|
||||
10 * 1000);
|
||||
ata_pm_read_cmd(ataio, 1, 15);
|
||||
break;
|
||||
case PROBE_IDENTIFY_SES:
|
||||
cam_fill_ataio(ataio,
|
||||
1,
|
||||
probedone,
|
||||
/*flags*/CAM_DIR_IN,
|
||||
0,
|
||||
/*data_ptr*/(u_int8_t *)&softc->ident_data,
|
||||
/*dxfer_len*/sizeof(softc->ident_data),
|
||||
30 * 1000);
|
||||
ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02,
|
||||
sizeof(softc->ident_data) / 4);
|
||||
break;
|
||||
case PROBE_IDENTIFY_SAFTE:
|
||||
cam_fill_ataio(ataio,
|
||||
1,
|
||||
probedone,
|
||||
/*flags*/CAM_DIR_IN,
|
||||
0,
|
||||
/*data_ptr*/(u_int8_t *)&softc->ident_data,
|
||||
/*dxfer_len*/sizeof(softc->ident_data),
|
||||
30 * 1000);
|
||||
ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00,
|
||||
sizeof(softc->ident_data) / 4);
|
||||
break;
|
||||
case PROBE_INVALID:
|
||||
CAM_DEBUG(path, CAM_DEBUG_INFO,
|
||||
("probestart: invalid action state\n"));
|
||||
@ -758,12 +788,16 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
struct ata_params *ident_buf;
|
||||
struct scsi_inquiry_data *inq_buf;
|
||||
probe_softc *softc;
|
||||
struct cam_path *path;
|
||||
cam_status status;
|
||||
u_int32_t priority;
|
||||
u_int caps;
|
||||
int found = 1;
|
||||
int changed = 1, found = 1;
|
||||
static const uint8_t fake_device_id_hdr[8] =
|
||||
{0, SVPD_DEVICE_ID, 0, 12,
|
||||
SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8};
|
||||
|
||||
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
|
||||
|
||||
@ -771,6 +805,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
path = done_ccb->ccb_h.path;
|
||||
priority = done_ccb->ccb_h.pinfo.priority;
|
||||
ident_buf = &path->device->ident_data;
|
||||
inq_buf = &path->device->inq_data;
|
||||
|
||||
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||
if (softc->restart) {
|
||||
@ -819,6 +854,18 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
} else if (softc->action == PROBE_SETDMAAA &&
|
||||
status == CAM_ATA_STATUS_ERROR) {
|
||||
goto noerror;
|
||||
|
||||
/*
|
||||
* SES and SAF-TE SEPs have different IDENTIFY commands,
|
||||
* but SATA specification doesn't tell how to identify them.
|
||||
* Until better way found, just try another if first fail.
|
||||
*/
|
||||
} else if (softc->action == PROBE_IDENTIFY_SES &&
|
||||
status == CAM_ATA_STATUS_ERROR) {
|
||||
PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE);
|
||||
xpt_release_ccb(done_ccb);
|
||||
xpt_schedule(periph, priority);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -862,6 +909,10 @@ noerror:
|
||||
xpt_action((union ccb *)&cts);
|
||||
path->device->protocol = PROTO_SATAPM;
|
||||
PROBE_SET_ACTION(softc, PROBE_PM_PID);
|
||||
} else if (sign == 0xc33c &&
|
||||
done_ccb->ccb_h.target_id != 15) {
|
||||
path->device->protocol = PROTO_SEMB;
|
||||
PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES);
|
||||
} else if (sign == 0xeb14 &&
|
||||
done_ccb->ccb_h.target_id != 15) {
|
||||
path->device->protocol = PROTO_SCSI;
|
||||
@ -881,7 +932,6 @@ noerror:
|
||||
{
|
||||
struct ccb_pathinq cpi;
|
||||
int16_t *ptr;
|
||||
int changed = 1;
|
||||
|
||||
ident_buf = &softc->ident_data;
|
||||
for (ptr = (int16_t *)ident_buf;
|
||||
@ -936,6 +986,11 @@ noerror:
|
||||
path->device->serial_num = NULL;
|
||||
path->device->serial_num_len = 0;
|
||||
}
|
||||
if (path->device->device_id != NULL) {
|
||||
free(path->device->device_id, M_CAMXPT);
|
||||
path->device->device_id = NULL;
|
||||
path->device->device_id_len = 0;
|
||||
}
|
||||
path->device->serial_num =
|
||||
(u_int8_t *)malloc((sizeof(ident_buf->serial) + 1),
|
||||
M_CAMXPT, M_NOWAIT);
|
||||
@ -948,6 +1003,18 @@ noerror:
|
||||
path->device->serial_num_len =
|
||||
strlen(path->device->serial_num);
|
||||
}
|
||||
if (ident_buf->enabled.extension &
|
||||
ATA_SUPPORT_64BITWWN) {
|
||||
path->device->device_id =
|
||||
malloc(16, M_CAMXPT, M_NOWAIT);
|
||||
if (path->device->device_id != NULL) {
|
||||
path->device->device_id_len = 16;
|
||||
bcopy(&fake_device_id_hdr,
|
||||
path->device->device_id, 8);
|
||||
bcopy(ident_buf->wwn,
|
||||
path->device->device_id + 8, 8);
|
||||
}
|
||||
}
|
||||
|
||||
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
|
||||
}
|
||||
@ -1092,11 +1159,9 @@ notsata:
|
||||
case PROBE_INQUIRY:
|
||||
case PROBE_FULL_INQUIRY:
|
||||
{
|
||||
struct scsi_inquiry_data *inq_buf;
|
||||
u_int8_t periph_qual, len;
|
||||
|
||||
path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
|
||||
inq_buf = &path->device->inq_data;
|
||||
|
||||
periph_qual = SID_QUAL(inq_buf);
|
||||
|
||||
@ -1200,6 +1265,48 @@ notsata:
|
||||
xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb);
|
||||
}
|
||||
break;
|
||||
case PROBE_IDENTIFY_SES:
|
||||
case PROBE_IDENTIFY_SAFTE:
|
||||
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
|
||||
/* Check that it is the same device. */
|
||||
if (bcmp(&softc->ident_data, ident_buf, 53)) {
|
||||
/* Device changed. */
|
||||
xpt_async(AC_LOST_DEVICE, path, NULL);
|
||||
} else {
|
||||
bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
|
||||
changed = 0;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
|
||||
/* Clean up from previous instance of this device */
|
||||
if (path->device->device_id != NULL) {
|
||||
free(path->device->device_id, M_CAMXPT);
|
||||
path->device->device_id = NULL;
|
||||
path->device->device_id_len = 0;
|
||||
}
|
||||
path->device->device_id =
|
||||
malloc(16, M_CAMXPT, M_NOWAIT);
|
||||
if (path->device->device_id != NULL) {
|
||||
path->device->device_id_len = 16;
|
||||
bcopy(&fake_device_id_hdr,
|
||||
path->device->device_id, 8);
|
||||
bcopy(((uint8_t*)ident_buf) + 2,
|
||||
path->device->device_id + 8, 8);
|
||||
}
|
||||
|
||||
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
|
||||
}
|
||||
|
||||
if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
|
||||
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
|
||||
xpt_acquire_device(path->device);
|
||||
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
|
||||
xpt_action(done_ccb);
|
||||
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
|
||||
done_ccb);
|
||||
}
|
||||
break;
|
||||
case PROBE_INVALID:
|
||||
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO,
|
||||
("probedone: invalid action state\n"));
|
||||
@ -1624,10 +1731,20 @@ ata_dev_advinfo(union ccb *start_ccb)
|
||||
device = start_ccb->ccb_h.path->device;
|
||||
cdai = &start_ccb->cdai;
|
||||
switch(cdai->buftype) {
|
||||
case CDAI_TYPE_SCSI_DEVID:
|
||||
if (cdai->flags & CDAI_FLAG_STORE)
|
||||
return;
|
||||
cdai->provsiz = device->device_id_len;
|
||||
if (device->device_id_len == 0)
|
||||
break;
|
||||
amt = device->device_id_len;
|
||||
if (cdai->provsiz > cdai->bufsiz)
|
||||
amt = cdai->bufsiz;
|
||||
memcpy(cdai->buf, device->device_id, amt);
|
||||
break;
|
||||
case CDAI_TYPE_SERIAL_NUM:
|
||||
if (cdai->flags & CDAI_FLAG_STORE)
|
||||
break;
|
||||
start_ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
return;
|
||||
cdai->provsiz = device->serial_num_len;
|
||||
if (device->serial_num_len == 0)
|
||||
break;
|
||||
@ -1636,8 +1753,45 @@ ata_dev_advinfo(union ccb *start_ccb)
|
||||
amt = cdai->bufsiz;
|
||||
memcpy(cdai->buf, device->serial_num, amt);
|
||||
break;
|
||||
default:
|
||||
case CDAI_TYPE_PHYS_PATH:
|
||||
if (cdai->flags & CDAI_FLAG_STORE) {
|
||||
if (device->physpath != NULL)
|
||||
free(device->physpath, M_CAMXPT);
|
||||
device->physpath_len = cdai->bufsiz;
|
||||
/* Clear existing buffer if zero length */
|
||||
if (cdai->bufsiz == 0)
|
||||
break;
|
||||
device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT);
|
||||
if (device->physpath == NULL) {
|
||||
start_ccb->ccb_h.status = CAM_REQ_ABORTED;
|
||||
return;
|
||||
}
|
||||
memcpy(device->physpath, cdai->buf, cdai->bufsiz);
|
||||
} else {
|
||||
cdai->provsiz = device->physpath_len;
|
||||
if (device->physpath_len == 0)
|
||||
break;
|
||||
amt = device->physpath_len;
|
||||
if (cdai->provsiz > cdai->bufsiz)
|
||||
amt = cdai->bufsiz;
|
||||
memcpy(cdai->buf, device->physpath, amt);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
start_ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
|
||||
if (cdai->flags & CDAI_FLAG_STORE) {
|
||||
int owned;
|
||||
|
||||
owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx);
|
||||
if (owned == 0)
|
||||
mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx);
|
||||
xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path,
|
||||
(void *)(uintptr_t)cdai->buftype);
|
||||
if (owned == 0)
|
||||
mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,6 +242,7 @@ typedef enum {
|
||||
PROTO_ATA, /* AT Attachment */
|
||||
PROTO_ATAPI, /* AT Attachment Packetized Interface */
|
||||
PROTO_SATAPM, /* SATA Port Multiplier */
|
||||
PROTO_SEMB, /* SATA Enclosure Management Bridge */
|
||||
} cam_proto;
|
||||
|
||||
typedef enum {
|
||||
|
@ -1080,6 +1080,9 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
|
||||
else if (path->device->protocol == PROTO_ATA ||
|
||||
path->device->protocol == PROTO_SATAPM)
|
||||
ata_print_ident(&path->device->ident_data);
|
||||
else if (path->device->protocol == PROTO_SEMB)
|
||||
semb_print_ident(
|
||||
(struct sep_identify_data *)&path->device->ident_data);
|
||||
else
|
||||
printf("Unknown protocol device\n");
|
||||
if (bootverbose && path->device->serial_num_len > 0) {
|
||||
@ -4859,7 +4862,8 @@ xpt_finishconfig_task(void *context, int pending)
|
||||
* attached. For any devices like that, announce the
|
||||
* passthrough driver so the user will see something.
|
||||
*/
|
||||
xpt_for_all_devices(xptpassannouncefunc, NULL);
|
||||
if (!bootverbose)
|
||||
xpt_for_all_devices(xptpassannouncefunc, NULL);
|
||||
|
||||
/* Release our hook so that the boot can continue. */
|
||||
config_intrhook_disestablish(xsoftc.xpt_config_hook);
|
||||
|
@ -5740,6 +5740,66 @@ scsi_send_diagnostic(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
timeout);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
uint8_t tag_action, int mode,
|
||||
uint8_t buffer_id, u_int32_t offset,
|
||||
uint8_t *data_ptr, uint32_t allocation_length,
|
||||
uint8_t sense_len, uint32_t timeout)
|
||||
{
|
||||
struct scsi_read_buffer *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_read_buffer *)&csio->cdb_io.cdb_bytes;
|
||||
memset(scsi_cmd, 0, sizeof(*scsi_cmd));
|
||||
scsi_cmd->opcode = READ_BUFFER;
|
||||
scsi_cmd->byte2 = mode;
|
||||
scsi_cmd->buffer_id = buffer_id;
|
||||
scsi_ulto3b(offset, scsi_cmd->offset);
|
||||
scsi_ulto3b(allocation_length, scsi_cmd->length);
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/CAM_DIR_IN,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
allocation_length,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, int mode,
|
||||
uint8_t buffer_id, u_int32_t offset,
|
||||
uint8_t *data_ptr, uint32_t param_list_length,
|
||||
uint8_t sense_len, uint32_t timeout)
|
||||
{
|
||||
struct scsi_write_buffer *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_write_buffer *)&csio->cdb_io.cdb_bytes;
|
||||
memset(scsi_cmd, 0, sizeof(*scsi_cmd));
|
||||
scsi_cmd->opcode = WRITE_BUFFER;
|
||||
scsi_cmd->byte2 = mode;
|
||||
scsi_cmd->buffer_id = buffer_id;
|
||||
scsi_ulto3b(offset, scsi_cmd->offset);
|
||||
scsi_ulto3b(param_list_length, scsi_cmd->length);
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
param_list_length,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
|
@ -1267,6 +1267,8 @@ struct scsi_vpd_id_descriptor
|
||||
#define SCSI_PROTO_RDMA 0x04
|
||||
#define SCSI_PROTO_iSCSI 0x05
|
||||
#define SCSI_PROTO_SAS 0x06
|
||||
#define SCSI_PROTO_ADT 0x07
|
||||
#define SCSI_PROTO_ATA 0x08
|
||||
#define SVPD_ID_PROTO_SHIFT 4
|
||||
#define SVPD_ID_CODESET_BINARY 0x01
|
||||
#define SVPD_ID_CODESET_ASCII 0x02
|
||||
@ -1400,6 +1402,13 @@ struct scsi_service_action_in
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_diag_page {
|
||||
uint8_t page_code;
|
||||
uint8_t page_specific_flags;
|
||||
uint8_t length[2];
|
||||
uint8_t params[0];
|
||||
};
|
||||
|
||||
struct scsi_read_capacity
|
||||
{
|
||||
u_int8_t opcode;
|
||||
@ -2352,6 +2361,20 @@ void scsi_send_diagnostic(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
uint16_t param_list_length, uint8_t sense_len,
|
||||
uint32_t timeout);
|
||||
|
||||
void scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
uint8_t tag_action, int mode,
|
||||
uint8_t buffer_id, u_int32_t offset,
|
||||
uint8_t *data_ptr, uint32_t allocation_length,
|
||||
uint8_t sense_len, uint32_t timeout);
|
||||
|
||||
void scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, int mode,
|
||||
uint8_t buffer_id, u_int32_t offset,
|
||||
uint8_t *data_ptr, uint32_t param_list_length,
|
||||
uint8_t sense_len, uint32_t timeout);
|
||||
|
||||
void scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int readop, u_int8_t byte2,
|
||||
|
@ -318,6 +318,7 @@ struct ata_params {
|
||||
#define ATA_READ_VERIFY48 0x42
|
||||
#define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */
|
||||
#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */
|
||||
#define ATA_SEP_ATTN 0x67 /* SEP request */
|
||||
#define ATA_SEEK 0x70 /* seek */
|
||||
#define ATA_PACKET_CMD 0xa0 /* packet command */
|
||||
#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user