==== //depot/FreeBSD-ken/src/sys/cam/cam_ccb.h#10 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/cam_ccb.h ==== *** /tmp/tmp.268.0 Sun Apr 27 18:37:50 2003 --- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/cam_ccb.h Sat Apr 26 18:01:57 2003 *************** *** 488,494 **** /* * Definitions for the path inquiry CCB fields. */ ! #define CAM_VERSION 0x14 /* Hex value for current version */ typedef enum { PI_MDP_ABLE = 0x80, /* Supports MDP message */ --- 488,494 ---- /* * Definitions for the path inquiry CCB fields. */ ! #define CAM_VERSION 0x15 /* Hex value for current version */ typedef enum { PI_MDP_ABLE = 0x80, /* Supports MDP message */ *************** *** 789,796 **** struct ccb_calc_geometry { struct ccb_hdr ccb_h; u_int32_t block_size; ! u_int32_t volume_size; ! u_int16_t cylinders; u_int8_t heads; u_int8_t secs_per_track; }; --- 789,796 ---- struct ccb_calc_geometry { struct ccb_hdr ccb_h; u_int32_t block_size; ! u_int64_t volume_size; ! u_int32_t cylinders; u_int8_t heads; u_int8_t secs_per_track; }; ==== //depot/FreeBSD-ken/src/sys/cam/scsi/scsi_all.c#23 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_all.c ==== *** /tmp/tmp.268.1 Sun Apr 27 18:37:50 2003 --- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_all.c Sat Apr 26 17:42:22 2003 *************** *** 2,8 **** * Implementation of Utility functions for all SCSI device types. * * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. ! * Copyright (c) 1997, 1998 Kenneth D. Merry. * All rights reserved. * * Redistribution and use in source and binary forms, with or without --- 2,8 ---- * Implementation of Utility functions for all SCSI device types. * * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. ! * Copyright (c) 1997, 1998, 2003 Kenneth D. Merry. * All rights reserved. * * Redistribution and use in source and binary forms, with or without *************** *** 507,515 **** /* 85 */ /* 86 */ /* 87 */ ! /* 88 */ /* 89 */ ! /* 8A */ /* 8B */ /* 8C */ /* 8D */ --- 507,517 ---- /* 85 */ /* 86 */ /* 87 */ ! /* 88 MM OO O O READ(16) */ ! {0x88, D|T|W|R|O, "READ(16)"}, /* 89 */ ! /* 8A OM O O O WRITE(16) */ ! {0x8A, D|T|W|R|O, "WRITE(16)"}, /* 8B */ /* 8C */ /* 8D */ *************** *** 529,536 **** /* 9B */ /* 9C */ /* 9D */ ! /* 9E */ ! /* 9F */ /* A0 OOOOOOOOOOO REPORT LUNS */ {0xA0, ALL & ~(E), "REPORT LUNS"}, --- 531,541 ---- /* 9B */ /* 9C */ /* 9D */ ! /* XXX KDM ALL for these? op-num.txt defines them for none.. */ ! /* 9E SERVICE ACTION IN(16) */ ! {0x9E, ALL, "SERVICE ACTION IN(16)"}, ! /* 9F SERVICE ACTION OUT(16) */ ! {0x9F, ALL, "SERVICE ACTION OUT(16)"}, /* A0 OOOOOOOOOOO REPORT LUNS */ {0xA0, ALL & ~(E), "REPORT LUNS"}, *************** *** 560,575 **** /* A7 OO OO OO MOVE MEDIUM ATTACHED */ {0xA7, D|T|W|R|O|M, "MOVE MEDIUM ATTACHED"}, ! /* A8 OM O READ(12) */ ! {0xA8, W|R|O, "READ(12)"}, /* A8 O GET MESSAGE(12) */ {0xA8, C, "GET MESSAGE(12)"}, /* A9 O PLAY TRACK RELATIVE(12) */ {0xA9, R, "PLAY TRACK RELATIVE(12)"}, ! /* AA O O WRITE(12) */ ! {0xAA, W|O, "WRITE(12)"}, /* AA O WRITE CD(12) {MMC Proposed} */ {0xAA, R, "WRITE CD(12) {MMC Proposed}"}, /* AA O SEND MESSAGE(12) */ --- 565,580 ---- /* A7 OO OO OO MOVE MEDIUM ATTACHED */ {0xA7, D|T|W|R|O|M, "MOVE MEDIUM ATTACHED"}, ! /* A8 O OM O READ(12) */ ! {0xA8,D|W|R|O, "READ(12)"}, /* A8 O GET MESSAGE(12) */ {0xA8, C, "GET MESSAGE(12)"}, /* A9 O PLAY TRACK RELATIVE(12) */ {0xA9, R, "PLAY TRACK RELATIVE(12)"}, ! /* AA O O O WRITE(12) */ ! {0xAA,D|W|O, "WRITE(12)"}, /* AA O WRITE CD(12) {MMC Proposed} */ {0xAA, R, "WRITE CD(12) {MMC Proposed}"}, /* AA O SEND MESSAGE(12) */ *************** *** 2699,2704 **** --- 2704,2741 ---- } void + scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + uint8_t tag_action, uint64_t lba, int reladr, int pmi, + struct scsi_read_capacity_data_long *rcap_buf, + uint8_t sense_len, uint32_t timeout) + { + struct scsi_read_capacity_16 *scsi_cmd; + + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_IN, + tag_action, + /*data_ptr*/(u_int8_t *)rcap_buf, + /*dxfer_len*/sizeof(*rcap_buf), + sense_len, + sizeof(*scsi_cmd), + timeout); + scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; + bzero(scsi_cmd, sizeof(*scsi_cmd)); + scsi_cmd->opcode = SERVICE_ACTION_IN; + scsi_cmd->service_action = SRC16_SERVICE_ACTION; + scsi_u64to8b(lba, scsi_cmd->addr); + scsi_ulto4b(sizeof(*rcap_buf), scsi_cmd->alloc_len); + if (pmi) + reladr |= SRC16_PMI; + if (reladr) + reladr |= SRC16_RELADR; + } + + void scsi_report_luns(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, struct scsi_report_luns_data *rpl_buf, *************** *** 2758,2764 **** 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, ! int minimum_cmd_size, u_int32_t lba, u_int32_t block_count, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) { --- 2795,2801 ---- 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, ! int minimum_cmd_size, u_int64_t lba, u_int32_t block_count, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) { *************** *** 2790,2796 **** scsi_cmd->addr[1], scsi_cmd->addr[2], scsi_cmd->length, dxfer_len)); } else if ((minimum_cmd_size < 12) ! && ((block_count & 0xffff) == block_count)) { /* * Need a 10 byte cdb. */ --- 2827,2834 ---- scsi_cmd->addr[1], scsi_cmd->addr[2], scsi_cmd->length, dxfer_len)); } else if ((minimum_cmd_size < 12) ! && ((block_count & 0xffff) == block_count) ! && ((lba & 0xffffffff) == lba)) { /* * Need a 10 byte cdb. */ *************** *** 2810,2820 **** scsi_cmd->addr[1], scsi_cmd->addr[2], scsi_cmd->addr[3], scsi_cmd->length[0], scsi_cmd->length[1], dxfer_len)); ! } else { /* * The block count is too big for a 10 byte CDB, use a 12 ! * byte CDB. READ/WRITE(12) are currently only defined for ! * optical devices. */ struct scsi_rw_12 *scsi_cmd; --- 2848,2859 ---- scsi_cmd->addr[1], scsi_cmd->addr[2], scsi_cmd->addr[3], scsi_cmd->length[0], scsi_cmd->length[1], dxfer_len)); ! } else if ((minimum_cmd_size < 16) ! && ((block_count & 0xffffffff) == block_count) ! && ((lba & 0xffffffff) == lba)) { /* * The block count is too big for a 10 byte CDB, use a 12 ! * byte CDB. */ struct scsi_rw_12 *scsi_cmd; *************** *** 2833,2838 **** --- 2872,2892 ---- scsi_cmd->addr[3], scsi_cmd->length[0], scsi_cmd->length[1], scsi_cmd->length[2], scsi_cmd->length[3], dxfer_len)); + } else { + /* + * 16 byte CDB. We'll only get here if the LBA is larger + * than 2^32, or if the user asks for a 16 byte command. + */ + struct scsi_rw_16 *scsi_cmd; + + scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes; + scsi_cmd->opcode = readop ? READ_16 : WRITE_16; + scsi_cmd->byte2 = byte2; + scsi_u64to8b(lba, scsi_cmd->addr); + scsi_cmd->reserved = 0; + scsi_ulto4b(block_count, scsi_cmd->length); + scsi_cmd->control = 0; + cdb_len = sizeof(*scsi_cmd); } cam_fill_csio(csio, retries, ==== //depot/FreeBSD-ken/src/sys/cam/scsi/scsi_all.h#12 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_all.h ==== *** /tmp/tmp.268.2 Sun Apr 27 18:37:50 2003 --- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_all.h Sat Apr 26 17:41:57 2003 *************** *** 419,425 **** { u_int8_t opcode; #define SRW10_RELADDR 0x01 ! #define SRW10_FUA 0x08 #define SRW10_DPO 0x10 u_int8_t byte2; u_int8_t addr[4]; --- 419,427 ---- { u_int8_t opcode; #define SRW10_RELADDR 0x01 ! /* EBP defined for WRITE(10) only */ ! #define SRW10_EBP 0x04 ! #define SRW10_FUA 0x08 #define SRW10_DPO 0x10 u_int8_t byte2; u_int8_t addr[4]; *************** *** 441,446 **** --- 443,461 ---- u_int8_t control; }; + struct scsi_rw_16 + { + u_int8_t opcode; + #define SRW16_RELADDR 0x01 + #define SRW16_FUA 0x08 + #define SRW16_DPO 0x10 + u_int8_t byte2; + u_int8_t addr[8]; + u_int8_t length[4]; + u_int8_t reserved; + u_int8_t control; + }; + struct scsi_start_stop_unit { u_int8_t opcode; *************** *** 486,496 **** #define LOG_SENSE 0x4d #define MODE_SELECT_10 0x55 #define MODE_SENSE_10 0x5A #define REPORT_LUNS 0xA0 ! #define MOVE_MEDIUM 0xa5 ! #define READ_12 0xa8 ! #define WRITE_12 0xaa ! #define READ_ELEMENT_STATUS 0xb8 /* --- 501,514 ---- #define LOG_SENSE 0x4d #define MODE_SELECT_10 0x55 #define MODE_SENSE_10 0x5A + #define READ_16 0x88 + #define WRITE_16 0x8a + #define SERVICE_ACTION_IN 0x9e #define REPORT_LUNS 0xA0 ! #define MOVE_MEDIUM 0xa5 ! #define READ_12 0xa8 ! #define WRITE_12 0xaa ! #define READ_ELEMENT_STATUS 0xb8 /* *************** *** 651,662 **** --- 669,699 ---- u_int8_t control; }; + struct scsi_read_capacity_16 + { + uint8_t opcode; + #define SRC16_SERVICE_ACTION 0x10 + uint8_t service_action; + uint8_t addr[8]; + uint8_t alloc_len[4]; + #define SRC16_PMI 0x01 + #define SRC16_RELADR 0x02 + uint8_t reladr; + uint8_t control; + }; + struct scsi_read_capacity_data { u_int8_t addr[4]; u_int8_t length[4]; }; + struct scsi_read_capacity_data_long + { + uint8_t addr[8]; + uint8_t length[4]; + }; + struct scsi_report_luns { u_int8_t opcode; *************** *** 977,982 **** --- 1014,1026 ---- union ccb *), u_int8_t tag_action, struct scsi_read_capacity_data *, u_int8_t sense_len, u_int32_t timeout); + void scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, + union ccb *), uint8_t tag_action, + uint64_t lba, int reladr, int pmi, + struct scsi_read_capacity_data_long + *rcap_buf, uint8_t sense_len, + uint32_t timeout); void scsi_report_luns(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, *************** *** 995,1001 **** 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, ! int minimum_cmd_size, u_int32_t lba, u_int32_t block_count, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout); --- 1039,1045 ---- 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, ! int minimum_cmd_size, u_int64_t lba, u_int32_t block_count, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout); *************** *** 1015,1024 **** --- 1059,1070 ---- static __inline void scsi_ulto2b(u_int32_t val, u_int8_t *bytes); static __inline void scsi_ulto3b(u_int32_t val, u_int8_t *bytes); static __inline void scsi_ulto4b(u_int32_t val, u_int8_t *bytes); + static __inline void scsi_u64to8b(u_int64_t val, u_int8_t *bytes); static __inline u_int32_t scsi_2btoul(u_int8_t *bytes); static __inline u_int32_t scsi_3btoul(u_int8_t *bytes); static __inline int32_t scsi_3btol(u_int8_t *bytes); static __inline u_int32_t scsi_4btoul(u_int8_t *bytes); + static __inline u_int64_t scsi_8btou64(u_int8_t *bytes); static __inline void *find_mode_page_6(struct scsi_mode_header_6 *mode_header); static __inline void *find_mode_page_10(struct scsi_mode_header_10 *mode_header); *************** *** 1059,1064 **** --- 1105,1124 ---- bytes[3] = val & 0xff; } + static __inline void + scsi_u64to8b(u_int64_t val, u_int8_t *bytes) + { + + bytes[0] = (val >> 56) & 0xff; + bytes[1] = (val >> 48) & 0xff; + bytes[2] = (val >> 40) & 0xff; + bytes[3] = (val >> 32) & 0xff; + bytes[4] = (val >> 24) & 0xff; + bytes[5] = (val >> 16) & 0xff; + bytes[6] = (val >> 8) & 0xff; + bytes[7] = val & 0xff; + } + static __inline u_int32_t scsi_2btoul(u_int8_t *bytes) { *************** *** 1100,1105 **** --- 1160,1181 ---- (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; + return (rv); + } + + static __inline uint64_t + scsi_8btou64(uint8_t *bytes) + { + uint64_t rv; + + rv = (((uint64_t)bytes[0]) << 56) | + (((uint64_t)bytes[1]) << 48) | + (((uint64_t)bytes[2]) << 40) | + (((uint64_t)bytes[3]) << 32) | + (((uint64_t)bytes[4]) << 24) | + (((uint64_t)bytes[5]) << 16) | + (((uint64_t)bytes[6]) << 8) | + bytes[7]; return (rv); } ==== //depot/FreeBSD-ken/src/sys/cam/scsi/scsi_da.c#51 - /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_da.c ==== *** /tmp/tmp.268.3 Sun Apr 27 18:37:50 2003 --- /usr/home/ken/perforce2/FreeBSD-ken/src/sys/cam/scsi/scsi_da.c Sun Apr 27 18:31:17 2003 *************** *** 73,78 **** --- 73,79 ---- #ifdef _KERNEL typedef enum { DA_STATE_PROBE, + DA_STATE_PROBE2, DA_STATE_NORMAL } da_state; *************** *** 96,104 **** typedef enum { DA_CCB_PROBE = 0x01, ! DA_CCB_BUFFER_IO = 0x02, ! DA_CCB_WAITING = 0x03, ! DA_CCB_DUMP = 0x04, DA_CCB_TYPE_MASK = 0x0F, DA_CCB_RETRY_UA = 0x10 } da_ccb_state; --- 97,106 ---- typedef enum { DA_CCB_PROBE = 0x01, ! DA_CCB_PROBE2 = 0x02, ! DA_CCB_BUFFER_IO = 0x03, ! DA_CCB_WAITING = 0x04, ! DA_CCB_DUMP = 0x05, DA_CCB_TYPE_MASK = 0x0F, DA_CCB_RETRY_UA = 0x10 } da_ccb_state; *************** *** 109,118 **** struct disk_params { u_int8_t heads; ! u_int16_t cylinders; u_int8_t secs_per_track; u_int32_t secsize; /* Number of bytes/sector */ ! u_int32_t sectors; /* total number sectors */ }; struct da_softc { --- 111,120 ---- struct disk_params { u_int8_t heads; ! u_int32_t cylinders; u_int8_t secs_per_track; u_int32_t secsize; /* Number of bytes/sector */ ! u_int64_t sectors; /* total number sectors */ }; struct da_softc { *************** *** 471,476 **** --- 473,479 ---- static periph_init_t dainit; static void daasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); + static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS); static periph_ctor_t daregister; static periph_dtor_t dacleanup; static periph_start_t dastart; *************** *** 480,487 **** static int daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags); static void daprevent(struct cam_periph *periph, int action); ! static void dasetgeom(struct cam_periph *periph, ! struct scsi_read_capacity_data * rdcap); static timeout_t dasendorderedtag; static void dashutdown(void *arg, int howto); --- 483,491 ---- static int daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags); static void daprevent(struct cam_periph *periph, int action); ! static int dagetcapacity(struct cam_periph *periph); ! static void dasetgeom(struct cam_periph *periph, uint32_t block_len, ! uint64_t maxsector); static timeout_t dasendorderedtag; static void dashutdown(void *arg, int howto); *************** *** 536,543 **** { struct cam_periph *periph; struct da_softc *softc; - struct scsi_read_capacity_data *rcap; - union ccb *ccb; int unit; int error; int s; --- 540,545 ---- *************** *** 569,606 **** } splx(s); ! /* Do a read capacity */ ! rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), ! M_TEMP, ! M_WAITOK); ! ! ccb = cam_periph_getccb(periph, /*priority*/1); ! scsi_read_capacity(&ccb->csio, ! /*retries*/4, ! /*cbfncp*/dadone, ! MSG_SIMPLE_Q_TAG, ! rcap, ! SSD_FULL_SIZE, ! /*timeout*/60000); ! ccb->ccb_h.ccb_bp = NULL; ! ! error = cam_periph_runccb(ccb, daerror, ! /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA, ! softc->disk.d_devstat); ! ! if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) ! cam_release_devq(ccb->ccb_h.path, ! /*relsim_flags*/0, ! /*reduction*/0, ! /*timeout*/0, ! /*getcount_only*/0); ! xpt_release_ccb(ccb); ! ! if (error == 0) ! dasetgeom(periph, rcap); ! ! free(rcap, M_TEMP); if (error == 0) { --- 571,577 ---- } splx(s); ! error = dagetcapacity(periph); if (error == 0) { *************** *** 1041,1058 **** return (error); /* ! * Acceptable values here are 6, 10 or 12. It's possible we may ! * support a 16 byte minimum command size in the future, since ! * there are now READ(16) and WRITE(16) commands defined in the ! * SBC-2 spec. */ if (value < 6) value = 6; else if ((value > 6) && (value <= 10)) value = 10; ! else if (value > 10) value = 12; *(int *)arg1 = value; --- 1012,1029 ---- return (error); /* ! * Acceptable values here are 6, 10, 12 or 16. */ if (value < 6) value = 6; else if ((value > 6) && (value <= 10)) value = 10; ! else if ((value > 10) ! && (value <= 12)) value = 12; + else if (value > 12) + value = 16; *(int *)arg1 = value; *************** *** 1140,1154 **** TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size); /* ! * 6, 10 and 12 are the currently permissible values. */ if (softc->minimum_cmd_size < 6) softc->minimum_cmd_size = 6; else if ((softc->minimum_cmd_size > 6) && (softc->minimum_cmd_size <= 10)) softc->minimum_cmd_size = 10; ! else if (softc->minimum_cmd_size > 12) softc->minimum_cmd_size = 12; /* * Now register the sysctl handler, so the user can the value on --- 1111,1128 ---- TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size); /* ! * 6, 10, 12 and 16 are the currently permissible values. */ if (softc->minimum_cmd_size < 6) softc->minimum_cmd_size = 6; else if ((softc->minimum_cmd_size > 6) && (softc->minimum_cmd_size <= 10)) softc->minimum_cmd_size = 10; ! else if ((softc->minimum_cmd_size > 10) ! && (softc->minimum_cmd_size <= 12)) softc->minimum_cmd_size = 12; + else if (softc->minimum_cmd_size > 12) + softc->minimum_cmd_size = 16; /* * Now register the sysctl handler, so the user can the value on *************** *** 1251,1267 **** } scsi_read_write(&start_ccb->csio, /*retries*/da_retry_count, ! dadone, ! tag_code, ! bp->bio_cmd == BIO_READ, /*byte2*/0, softc->minimum_cmd_size, ! bp->bio_pblkno, ! bp->bio_bcount / softc->params.secsize, ! bp->bio_data, ! bp->bio_bcount, /*sense_len*/SSD_FULL_SIZE, ! da_default_timeout * 1000); start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO; /* --- 1225,1242 ---- } scsi_read_write(&start_ccb->csio, /*retries*/da_retry_count, ! /*cbfcnp*/dadone, ! /*tag_action*/tag_code, ! /*read_op*/bp->bio_cmd == BIO_READ, /*byte2*/0, softc->minimum_cmd_size, ! /*lba*/bp->bio_pblkno, ! /*block_count*/bp->bio_bcount / ! softc->params.secsize, ! /*data_ptr*/ bp->bio_data, ! /*dxfer_len*/ bp->bio_bcount, /*sense_len*/SSD_FULL_SIZE, ! /*timeout*/da_default_timeout*1000); start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO; /* *************** *** 1319,1324 **** --- 1294,1327 ---- xpt_action(start_ccb); break; } + case DA_STATE_PROBE2: + { + struct ccb_scsiio *csio; + struct scsi_read_capacity_data_long *rcaplong; + + rcaplong = (struct scsi_read_capacity_data_long *) + malloc(sizeof(*rcaplong), M_TEMP, M_NOWAIT); + if (rcaplong == NULL) { + printf("dastart: Couldn't malloc read_capacity data\n"); + /* da_free_periph??? */ + break; + } + csio = &start_ccb->csio; + scsi_read_capacity_16(csio, + /*retries*/ 4, + /*cbfcnp*/ dadone, + /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*lba*/ 0, + /*reladr*/ 0, + /*pmi*/ 0, + rcaplong, + /*sense_len*/ SSD_FULL_SIZE, + /*timeout*/ 60000); + start_ccb->ccb_h.ccb_bp = NULL; + start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2; + xpt_action(start_ccb); + break; + } } } *************** *** 1476,1495 **** break; } case DA_CCB_PROBE: { struct scsi_read_capacity_data *rdcap; char announce_buf[80]; ! rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; ! if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { struct disk_params *dp; ! dasetgeom(periph, rdcap); dp = &softc->params; snprintf(announce_buf, sizeof(announce_buf), ! "%luMB (%u %u byte sectors: %dH %dS/T %dC)", ! (unsigned long) (((u_int64_t)dp->secsize * dp->sectors) / (1024*1024)), dp->sectors, dp->secsize, dp->heads, dp->secs_per_track, dp->cylinders); --- 1479,1531 ---- break; } case DA_CCB_PROBE: + case DA_CCB_PROBE2: { struct scsi_read_capacity_data *rdcap; + struct scsi_read_capacity_data_long *rcaplong; char announce_buf[80]; ! rdcap = NULL; ! rcaplong = NULL; ! if (softc->state == DA_STATE_PROBE) ! rdcap =(struct scsi_read_capacity_data *)csio->data_ptr; ! else ! rcaplong = (struct scsi_read_capacity_data_long *) ! csio->data_ptr; ! if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { struct disk_params *dp; + uint32_t block_size; + uint64_t maxsector; ! if (softc->state == DA_STATE_PROBE) { ! block_size = scsi_4btoul(rdcap->length); ! maxsector = scsi_4btoul(rdcap->addr); ! ! /* ! * According to SBC-2, if the standard 10 ! * byte READ CAPACITY command returns 2^32, ! * we should issue the 16 byte version of ! * the command, since the device in question ! * has more sectors than can be represented ! * with the short version of the command. ! */ ! if (maxsector == 0xffffffff) { ! softc->state = DA_STATE_PROBE2; ! free(rdcap, M_TEMP); ! xpt_release_ccb(done_ccb); ! cam_periph_unlock(periph); ! break; ! } ! } else { ! block_size = scsi_4btoul(rcaplong->length); ! maxsector = scsi_8btou64(rcaplong->addr); ! } ! dasetgeom(periph, block_size, maxsector); dp = &softc->params; snprintf(announce_buf, sizeof(announce_buf), ! "%quMB (%qu %u byte sectors: %dH %dS/T %dC)", ! (uint64_t) (((u_int64_t)dp->secsize * dp->sectors) / (1024*1024)), dp->sectors, dp->secsize, dp->heads, dp->secs_per_track, dp->cylinders); *************** *** 1589,1595 **** } } } ! free(rdcap, M_TEMP); if (announce_buf[0] != '\0') xpt_announce_periph(periph, announce_buf); softc->state = DA_STATE_NORMAL; --- 1625,1631 ---- } } } ! free(csio->data_ptr, M_TEMP); if (announce_buf[0] != '\0') xpt_announce_periph(periph, announce_buf); softc->state = DA_STATE_NORMAL; *************** *** 1702,1709 **** xpt_release_ccb(ccb); } static void ! dasetgeom(struct cam_periph *periph, struct scsi_read_capacity_data * rdcap) { struct ccb_calc_geometry ccg; struct da_softc *softc; --- 1738,1838 ---- xpt_release_ccb(ccb); } + static int + dagetcapacity(struct cam_periph *periph) + { + struct da_softc *softc; + union ccb *ccb; + struct scsi_read_capacity_data *rcap; + struct scsi_read_capacity_data_long *rcaplong; + uint32_t block_len; + uint64_t maxsector; + int error; + + softc = (struct da_softc *)periph->softc; + error = 0; + + /* Do a read capacity */ + rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong), + M_TEMP, + M_WAITOK); + + ccb = cam_periph_getccb(periph, /*priority*/1); + scsi_read_capacity(&ccb->csio, + /*retries*/4, + /*cbfncp*/dadone, + MSG_SIMPLE_Q_TAG, + rcap, + SSD_FULL_SIZE, + /*timeout*/60000); + ccb->ccb_h.ccb_bp = NULL; + + error = cam_periph_runccb(ccb, daerror, + /*cam_flags*/CAM_RETRY_SELTO, + /*sense_flags*/SF_RETRY_UA, + softc->disk.d_devstat); + + if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + + if (error == 0) { + block_len = scsi_4btoul(rcap->length); + maxsector = scsi_4btoul(rcap->addr); + + if (maxsector != 0xffffffff) + goto done; + } else + goto done; + + rcaplong = (struct scsi_read_capacity_data_long *)rcap; + + scsi_read_capacity_16(&ccb->csio, + /*retries*/ 4, + /*cbfcnp*/ dadone, + /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*lba*/ 0, + /*reladr*/ 0, + /*pmi*/ 0, + rcaplong, + /*sense_len*/ SSD_FULL_SIZE, + /*timeout*/ 60000); + ccb->ccb_h.ccb_bp = NULL; + + error = cam_periph_runccb(ccb, daerror, + /*cam_flags*/CAM_RETRY_SELTO, + /*sense_flags*/SF_RETRY_UA, + softc->disk.d_devstat); + + if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + + if (error == 0) { + block_len = scsi_4btoul(rcaplong->length); + maxsector = scsi_8btou64(rcaplong->addr); + } + + done: + + if (error == 0) + dasetgeom(periph, block_len, maxsector); + + xpt_release_ccb(ccb); + + free(rcap, M_TEMP); + + return (error); + } + static void ! dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector) { struct ccb_calc_geometry ccg; struct da_softc *softc; *************** *** 1712,1719 **** softc = (struct da_softc *)periph->softc; dp = &softc->params; ! dp->secsize = scsi_4btoul(rdcap->length); ! dp->sectors = scsi_4btoul(rdcap->addr) + 1; /* * Have the controller provide us with a geometry * for this disk. The only time the geometry --- 1841,1848 ---- softc = (struct da_softc *)periph->softc; dp = &softc->params; ! dp->secsize = block_len; ! dp->sectors = maxsector + 1; /* * Have the controller provide us with a geometry * for this disk. The only time the geometry