From owner-svn-src-projects@FreeBSD.ORG Sat Aug 20 09:31:52 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8E728106566B; Sat, 20 Aug 2011 09:31:52 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7D35E8FC0C; Sat, 20 Aug 2011 09:31:52 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p7K9VqaV042754; Sat, 20 Aug 2011 09:31:52 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p7K9VqxA042741; Sat, 20 Aug 2011 09:31:52 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201108200931.p7K9VqxA042741@svn.freebsd.org> From: Alexander Motin Date: Sat, 20 Aug 2011 09:31:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r225024 - in projects/zfsd/head: sbin/camcontrol sys/cam sys/cam/ata sys/cam/scsi sys/sys X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Aug 2011 09:31:52 -0000 Author: mav Date: Sat Aug 20 09:31:52 2011 New Revision: 225024 URL: http://svn.freebsd.org/changeset/base/225024 Log: Add support for SATA Enclosure Management Bridge (SEMB). Modified: projects/zfsd/head/sbin/camcontrol/camcontrol.c projects/zfsd/head/sys/cam/ata/ata_all.c projects/zfsd/head/sys/cam/ata/ata_all.h projects/zfsd/head/sys/cam/ata/ata_da.c projects/zfsd/head/sys/cam/ata/ata_xpt.c projects/zfsd/head/sys/cam/cam_ccb.h projects/zfsd/head/sys/cam/cam_xpt.c projects/zfsd/head/sys/cam/scsi/scsi_all.h projects/zfsd/head/sys/cam/scsi/scsi_enc.c projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c projects/zfsd/head/sys/sys/ata.h Modified: projects/zfsd/head/sbin/camcontrol/camcontrol.c ============================================================================== --- projects/zfsd/head/sbin/camcontrol/camcontrol.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sbin/camcontrol/camcontrol.c Sat Aug 20 09:31:52 2011 (r225024) @@ -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, "<>"); } @@ -1131,7 +1150,7 @@ atacapprint(struct ata_params *parm) printf("firmware revision %.8s\n", parm->revision); printf("serial number %.20s\n", parm->serial); if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) { - printf("WWN %02x%02x%02x%02x\n", + printf("WWN %04x%04x%04x%04x\n", parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]); } if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) { Modified: projects/zfsd/head/sys/cam/ata/ata_all.c ============================================================================== --- projects/zfsd/head/sys/cam/ata/ata_all.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/ata/ata_all.c Sat Aug 20 09:31:52 2011 (r225024) @@ -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 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,45 @@ ata_static_identify_match(caddr_t identb } 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); +} + Modified: projects/zfsd/head/sys/cam/ata/ata_all.h ============================================================================== --- projects/zfsd/head/sys/cam/ata/ata_all.h Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/ata/ata_all.h Sat Aug 20 09:31:52 2011 (r225024) @@ -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,16 @@ 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); + #endif Modified: projects/zfsd/head/sys/cam/ata/ata_da.c ============================================================================== --- projects/zfsd/head/sys/cam/ata/ata_da.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/ata/ata_da.c Sat Aug 20 09:31:52 2011 (r225024) @@ -754,6 +754,20 @@ adaasync(void *callback_arg, u_int32_t c "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: { @@ -1066,8 +1080,8 @@ adaregister(struct cam_periph *periph, v * 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 Modified: projects/zfsd/head/sys/cam/ata/ata_xpt.c ============================================================================== --- projects/zfsd/head/sys/cam/ata/ata_xpt.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/ata/ata_xpt.c Sat Aug 20 09:31:52 2011 (r225024) @@ -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" }; @@ -260,7 +264,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); @@ -294,7 +299,8 @@ probestart(struct cam_periph *periph, un 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; @@ -609,6 +615,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")); @@ -745,12 +775,16 @@ probedone(struct cam_periph *periph, uni { 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")); @@ -758,6 +792,7 @@ probedone(struct cam_periph *periph, uni 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) { @@ -806,6 +841,18 @@ probedone(struct cam_periph *periph, uni } 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; } /* @@ -849,6 +896,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; @@ -868,7 +919,6 @@ noerror: { struct ccb_pathinq cpi; int16_t *ptr; - int changed = 1; ident_buf = &softc->ident_data; for (ptr = (int16_t *)ident_buf; @@ -923,6 +973,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); @@ -935,6 +990,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; } @@ -1079,11 +1146,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); @@ -1187,6 +1252,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")); @@ -1611,10 +1718,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_SERIAL_NUM: + 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; - start_ccb->ccb_h.status = CAM_REQ_CMP; + 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) + return; cdai->provsiz = device->serial_num_len; if (device->serial_num_len == 0) break; @@ -1623,8 +1740,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); } } Modified: projects/zfsd/head/sys/cam/cam_ccb.h ============================================================================== --- projects/zfsd/head/sys/cam/cam_ccb.h Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/cam_ccb.h Sat Aug 20 09:31:52 2011 (r225024) @@ -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 { Modified: projects/zfsd/head/sys/cam/cam_xpt.c ============================================================================== --- projects/zfsd/head/sys/cam/cam_xpt.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/cam_xpt.c Sat Aug 20 09:31:52 2011 (r225024) @@ -1081,6 +1081,9 @@ xpt_announce_periph(struct cam_periph *p 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) { Modified: projects/zfsd/head/sys/cam/scsi/scsi_all.h ============================================================================== --- projects/zfsd/head/sys/cam/scsi/scsi_all.h Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/scsi/scsi_all.h Sat Aug 20 09:31:52 2011 (r225024) @@ -869,6 +869,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 Modified: projects/zfsd/head/sys/cam/scsi/scsi_enc.c ============================================================================== --- projects/zfsd/head/sys/cam/scsi/scsi_enc.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/scsi/scsi_enc.c Sat Aug 20 09:31:52 2011 (r225024) @@ -74,7 +74,7 @@ static periph_dtor_t enc_dtor; static periph_start_t enc_start; static void enc_async(void *, uint32_t, struct cam_path *, void *); -static enctyp enc_type(void *, int); +static enctyp enc_type(struct ccb_getdev *); static struct periph_driver encdriver = { enc_init, "enc", @@ -183,7 +183,6 @@ enc_async(void *callback_arg, uint32_t c { struct ccb_getdev *cgd; cam_status status; - int inq_len; path_id_t path_id; cgd = (struct ccb_getdev *)arg; @@ -191,23 +190,7 @@ enc_async(void *callback_arg, uint32_t c break; } - if (cgd->protocol != PROTO_SCSI) - break; - - inq_len = cgd->inq_data.additional_length + 4; - - /* - * PROBLEM: WE NEED TO LOOK AT BYTES 48-53 TO SEE IF THIS - * PROBLEM: IS A SAF-TE DEVICE. - */ - switch (enc_type(&cgd->inq_data, inq_len)) { - case ENC_SES: - case ENC_SES_SCSI2: - case ENC_SES_PASSTHROUGH: - case ENC_SEN: - case ENC_SAFT: - break; - default: + if (enc_type(cgd) == ENC_NONE) { /* * Schedule announcement of the ENC bindings for * this device if it is managed by a SEP. @@ -564,7 +547,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, int enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp) { - int error, dlen; + int error, dlen, tdlen; ccb_flags ddf; union ccb *ccb; @@ -587,9 +570,32 @@ enc_runcmd(struct enc_softc *enc, char * } ccb = cam_periph_getccb(enc->periph, 1); - cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG, dptr, - dlen, sizeof (struct scsi_sense_data), cdbl, 60 * 1000); - bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl); + if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) { + tdlen = min(dlen, 1020); + tdlen = (tdlen + 3) & ~3; + cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen, + 30 * 1000); + if (cdb[0] == RECEIVE_DIAGNOSTIC) + ata_28bit_cmd(&ccb->ataio, + ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4); + else if (cdb[0] == SEND_DIAGNOSTIC) + ata_28bit_cmd(&ccb->ataio, + ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0, + 0x82, tdlen / 4); + else if (cdb[0] == READ_BUFFER) + ata_28bit_cmd(&ccb->ataio, + ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4); + else + ata_28bit_cmd(&ccb->ataio, + ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0, + 0x80, tdlen / 4); + } else { + tdlen = dlen; + cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG, + dptr, dlen, sizeof (struct scsi_sense_data), cdbl, + 60 * 1000); + bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl); + } error = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL); if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) @@ -600,7 +606,11 @@ enc_runcmd(struct enc_softc *enc, char * } } else { if (dptr) { - *dlenp = ccb->csio.resid; + if (ccb->ccb_h.func_code == XPT_ATA_IO) + *dlenp = ccb->ataio.resid; + else + *dlenp = ccb->csio.resid; + *dlenp += tdlen - dlen; } } xpt_release_ccb(ccb); @@ -639,10 +649,25 @@ enc_log(struct enc_softc *enc, const cha #define SAFTE_LEN SAFTE_END-SAFTE_START static enctyp -enc_type(void *buf, int buflen) +enc_type(struct ccb_getdev *cgd) { - unsigned char *iqd = buf; + int buflen; + unsigned char *iqd; + if (cgd->protocol == PROTO_SEMB) { + iqd = (unsigned char *)&cgd->ident_data; + if (STRNCMP(iqd + 43, "S-E-S", 5) == 0) + return (ENC_SEMB_SES); + else if (STRNCMP(iqd + 43, "SAF-TE", 6) == 0) + return (ENC_SEMB_SAFT); + return (ENC_NONE); + + } else if (cgd->protocol != PROTO_SCSI) + return (ENC_NONE); + + iqd = (unsigned char *)&cgd->inq_data; + buflen = min(sizeof(cgd->inq_data), + SID_ADDITIONAL_LENGTH(&cgd->inq_data)); if (buflen < 8+SEN_ID_LEN) return (ENC_NONE); @@ -743,14 +768,18 @@ enc_fsm_step(enc_softc_t *enc) if (error == 0) { - uint32_t resid; + uint32_t len; - resid = 0; - if (ccb != NULL) - resid = ccb->csio.dxfer_len - ccb->csio.resid; + len = 0; + if (ccb != NULL) { + if (ccb->ccb_h.func_code == XPT_ATA_IO) + len = ccb->ataio.dxfer_len - ccb->ataio.resid; + else + len = ccb->csio.dxfer_len - ccb->csio.resid; + } cam_periph_unlock(enc->periph); - cur_state->done(enc, cur_state, ccb, &buf, resid); + cur_state->done(enc, cur_state, ccb, &buf, len); cam_periph_lock(enc->periph); } @@ -880,16 +909,18 @@ enc_ctor(struct cam_periph *periph, void enc->periph = periph; enc->current_action = ENC_UPDATE_NONE; - enc->enc_type = enc_type(&cgd->inq_data, sizeof (cgd->inq_data)); + enc->enc_type = enc_type(cgd); sx_init(&enc->enc_cache_lock, "enccache"); switch (enc->enc_type) { case ENC_SES: case ENC_SES_SCSI2: case ENC_SES_PASSTHROUGH: + case ENC_SEMB_SES: err = ses_softc_init(enc, 1); break; case ENC_SAFT: + case ENC_SEMB_SAFT: err = safte_softc_init(enc, 1); break; case ENC_SEN: @@ -963,6 +994,12 @@ enc_ctor(struct cam_periph *periph, void case ENC_SAFT: tname = "SAF-TE Compliant Device"; break; + case ENC_SEMB_SES: + tname = "SEMB SES Device"; + break; + case ENC_SEMB_SAFT: + tname = "SEMB SAF-TE Device"; + break; } xpt_announce_periph(periph, tname); status = CAM_REQ_CMP; Modified: projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h ============================================================================== --- projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h Sat Aug 20 09:31:52 2011 (r225024) @@ -55,7 +55,9 @@ typedef enum { ENC_SES, ENC_SES_PASSTHROUGH, ENC_SEN, - ENC_SAFT + ENC_SAFT, + ENC_SEMB_SES, + ENC_SEMB_SAFT } enctyp; /* Platform Independent Driver Internal Definitions for enclosure devices. */ Modified: projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c ============================================================================== --- projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c Sat Aug 20 09:31:52 2011 (r225024) @@ -251,7 +251,7 @@ static enc_softc_cleanup_t ses_softc_cle #define SCSZ 0x8000 -static fsm_fill_handler_t ses_fill_rcv_diag_csio; +static fsm_fill_handler_t ses_fill_rcv_diag_io; static fsm_fill_handler_t ses_fill_control_request; static fsm_done_handler_t ses_process_config; static fsm_done_handler_t ses_process_status; @@ -269,7 +269,7 @@ struct enc_fsm_state enc_fsm_states[SES_ SesConfigPage, SCSZ, 60 * 1000, - ses_fill_rcv_diag_csio, + ses_fill_rcv_diag_io, ses_process_config, enc_error }, @@ -278,7 +278,7 @@ struct enc_fsm_state enc_fsm_states[SES_ SesStatusPage, SCSZ, 60 * 1000, - ses_fill_rcv_diag_csio, + ses_fill_rcv_diag_io, ses_process_status, enc_error }, @@ -287,7 +287,7 @@ struct enc_fsm_state enc_fsm_states[SES_ SesElementDescriptor, SCSZ, 60 * 1000, - ses_fill_rcv_diag_csio, + ses_fill_rcv_diag_io, ses_process_elm_descs, enc_error }, @@ -296,7 +296,7 @@ struct enc_fsm_state enc_fsm_states[SES_ SesAddlElementStatus, SCSZ, 60 * 1000, - ses_fill_rcv_diag_csio, + ses_fill_rcv_diag_io, ses_process_elm_addlstatus, enc_error }, @@ -1898,13 +1898,21 @@ out: } static int -ses_fill_rcv_diag_csio(enc_softc_t *enc, struct enc_fsm_state *state, +ses_fill_rcv_diag_io(enc_softc_t *enc, struct enc_fsm_state *state, union ccb *ccb, uint8_t *buf) { - scsi_receive_diagnostic_results(&ccb->csio, /*retries*/5, + + if (enc->enc_type == ENC_SEMB_SES) { + semb_receive_diagnostic_results(&ccb->ataio, /*retries*/5, + enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1, + state->page_code, buf, state->buf_size, + state->timeout); + } else { + scsi_receive_diagnostic_results(&ccb->csio, /*retries*/5, enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1, state->page_code, buf, state->buf_size, SSD_FULL_SIZE, state->timeout); + } return (0); } @@ -2018,12 +2026,19 @@ ses_fill_control_request(enc_softc_t *en return (ENOENT); /* Fill out the ccb */ - scsi_send_diagnostic(&ccb->csio, /*retries*/5, enc_done, + if (enc->enc_type == ENC_SEMB_SES) { + semb_send_diagnostic(&ccb->ataio, /*retries*/5, enc_done, + MSG_SIMPLE_Q_TAG, + buf, ses_page_length(&ses_cache->status_page->hdr), + state->timeout); + } else { + scsi_send_diagnostic(&ccb->csio, /*retries*/5, enc_done, MSG_SIMPLE_Q_TAG, /*unit_offline*/0, /*device_offline*/0, /*self_test*/0, /*page_format*/1, /*self_test_code*/0, buf, ses_page_length(&ses_cache->status_page->hdr), SSD_FULL_SIZE, state->timeout); + } return (0); } Modified: projects/zfsd/head/sys/sys/ata.h ============================================================================== --- projects/zfsd/head/sys/sys/ata.h Sat Aug 20 08:20:10 2011 (r225023) +++ projects/zfsd/head/sys/sys/ata.h Sat Aug 20 09:31:52 2011 (r225024) @@ -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*/