Index: usr.sbin/camdd/camdd.c =================================================================== --- usr.sbin/camdd/camdd.c +++ usr.sbin/camdd/camdd.c @@ -84,6 +84,8 @@ #include #include #include +#include +#include typedef enum { CAMDD_CMD_NONE = 0x00000000, @@ -105,6 +107,25 @@ CAMDD_ARG_RETRIES = 0x00000100 } camdd_argmask; + +typedef enum { + ADA_FLAG_CAN_48BIT = 0x0002, + ADA_FLAG_CAN_FLUSHCACHE = 0x0004, + ADA_FLAG_CAN_NCQ = 0x0008, + ADA_FLAG_CAN_DMA = 0x0010, + ADA_FLAG_NEED_OTAG = 0x0020, + ADA_FLAG_WAS_OTAG = 0x0040, + ADA_FLAG_CAN_TRIM = 0x0080, + ADA_FLAG_OPEN = 0x0100, + ADA_FLAG_SCTX_INIT = 0x0200, + ADA_FLAG_CAN_CFA = 0x0400, + ADA_FLAG_CAN_POWERMGT = 0x0800, + ADA_FLAG_CAN_DMA48 = 0x1000, + ADA_FLAG_DIRTY = 0x2000, + ADA_FLAG_CAN_NCQ_TRIM = 0x4000, /* CAN_TRIM also set */ + ADA_FLAG_PIM_CAN_NCQ_TRIM = 0x8000 +} ada_flags; + typedef enum { CAMDD_DEV_NONE = 0x00, CAMDD_DEV_PASS = 0x01, @@ -259,7 +280,9 @@ #define NUM_DEV_TYPES 2 struct camdd_dev_pass { - int scsi_dev_type; + int scsi_dev_type; + int protocol; + ada_flags ada_flags; struct cam_device *dev; uint64_t max_sector; uint32_t block_len; @@ -467,7 +490,7 @@ struct kevent *new_ke, int num_ke, int retry_count, int timeout); static struct camdd_buf *camdd_alloc_buf(struct camdd_dev *dev, - camdd_buf_type buf_type); + camdd_buf_type buf_type); void camdd_release_buf(struct camdd_buf *buf); struct camdd_buf *camdd_get_buf(struct camdd_dev *dev, camdd_buf_type buf_type); int camdd_buf_sg_create(struct camdd_buf *buf, int iovec, @@ -477,6 +500,20 @@ void camdd_buf_add_child(struct camdd_buf *buf, struct camdd_buf *child_buf); int camdd_probe_tape(int fd, char *filename, uint64_t *max_iosize, uint64_t *max_blk, uint64_t *min_blk, uint64_t *blk_gran); +uint64_t max_sector(int is48bit, struct ata_params *parm); +int camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, + int probe_retry_count, camdd_argmask arglist, + int probe_timeout, uint64_t *maxsector, uint32_t *block_len); +int camdd_probe_pass_ata(struct cam_device *cam_dev, union ccb *ccb, + camdd_argmask arglist, int probe_retry_count, + int probe_timeout, uint8_t command, ada_flags ada_flags, + uint64_t *maxsector, uint32_t *block_len); +void set_flags(ada_flags *flags, struct ccb_getdev *cgd); +int ata_do_cmd(union ccb *ccb, int retries, + u_int32_t flags, u_int8_t tag_action, + u_int8_t command, u_int8_t features, u_int32_t lba, + u_int16_t sector_count, u_int8_t *data_ptr, size_t dxfer_len, + int timeout, ada_flags ada_flags); struct camdd_dev *camdd_probe_file(int fd, struct camdd_io_opts *io_opts, int retry_count, int timeout); struct camdd_dev *camdd_probe_pass(struct cam_device *cam_dev, @@ -485,7 +522,8 @@ int probe_timeout, int io_retry_count, int io_timeout); void *camdd_file_worker(void *arg); -camdd_buf_status camdd_ccb_status(union ccb *ccb); +camdd_buf_status camdd_ccb_status(union ccb *ccb, int protocol); +int get_cgd(struct cam_device *device, struct ccb_getdev *cgd); int camdd_queue_peer_buf(struct camdd_dev *dev, struct camdd_buf *buf); int camdd_complete_peer_buf(struct camdd_dev *dev, struct camdd_buf *peer_buf); void camdd_peer_done(struct camdd_buf *buf); @@ -1252,59 +1290,125 @@ return (NULL); } + /* - * Need to implement this. Do a basic probe: - * - Check the inquiry data, make sure we're talking to a device that we - * can reasonably expect to talk to -- direct, RBC, CD, WORM. - * - Send a test unit ready, make sure the device is available. - * - Get the capacity and block size. - */ -struct camdd_dev * -camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, - camdd_argmask arglist, int probe_retry_count, - int probe_timeout, int io_retry_count, int io_timeout) + * * Get a get device CCB for the specified device. + * */ +int +get_cgd(struct cam_device *device, struct ccb_getdev *cgd) { union ccb *ccb; - uint64_t maxsector; - uint32_t cpi_maxio, max_iosize, pass_numblocks; - uint32_t block_len; - struct scsi_read_capacity_data rcap; - struct scsi_read_capacity_data_long rcaplong; - struct camdd_dev *dev; - struct camdd_dev_pass *pass_dev; - struct kevent ke; - int scsi_dev_type; + int retval = 0; - dev = NULL; + ccb = cam_getccb(device); - scsi_dev_type = SID_TYPE(&cam_dev->inq_data); - maxsector = 0; - block_len = 0; + if (ccb == NULL) { + warnx("get_cgd: couldn't allocate CCB"); + return 1; + } + bzero(&(&ccb->ccb_h)[1], + sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); + ccb->ccb_h.func_code = XPT_GDEV_TYPE; - /* - * For devices that support READ CAPACITY, we'll attempt to get the - * capacity. Otherwise, we really don't support tape or other - * devices via SCSI passthrough, so just return an error in that case. - */ - switch (scsi_dev_type) { - case T_DIRECT: - case T_WORM: - case T_CDROM: - case T_OPTICAL: - case T_RBC: - case T_ZBC_HM: - break; - default: - errx(1, "Unsupported SCSI device type %d", scsi_dev_type); - break; /*NOTREACHED*/ + if (cam_send_ccb(device, ccb) < 0) { + warn("get_cgd: error sending Path Inquiry CCB"); + cam_error_print(device, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + retval = 1; + goto get_cgd_bailout; } + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + cam_error_print(device, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + retval = 1; + goto get_cgd_bailout; + } + bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev)); +get_cgd_bailout: - ccb = cam_getccb(cam_dev); + cam_freeccb(ccb); - if (ccb == NULL) { - warnx("%s: error allocating ccb", __func__); - goto bailout; + return retval; +} + +void +set_flags(ada_flags *flags, struct ccb_getdev *cgd) +{ + if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) && + (cgd->inq_flags & SID_DMA)) + *flags |= ADA_FLAG_CAN_DMA; + else + *flags &= ~ADA_FLAG_CAN_DMA; + + if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) { + *flags |= ADA_FLAG_CAN_48BIT; + if (cgd->inq_flags & SID_DMA48) + *flags |= ADA_FLAG_CAN_DMA48; + else + *flags &= ~ADA_FLAG_CAN_DMA48; + } else + *flags &= ~(ADA_FLAG_CAN_48BIT | ADA_FLAG_CAN_DMA48); + + if ((cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ) && + (cgd->inq_flags & SID_DMA) && (cgd->inq_flags & SID_CmdQue)) + *flags |= ADA_FLAG_CAN_NCQ; + else + *flags &= ~ADA_FLAG_CAN_NCQ; +} + +int +ata_do_cmd(union ccb *ccb, int retries, + u_int32_t flags, u_int8_t tag_action, + u_int8_t command, u_int8_t features, u_int32_t lba, + u_int16_t sector_count, u_int8_t *data_ptr, size_t dxfer_len, + int timeout, ada_flags ada_flags) +{ + + cam_fill_ataio(&ccb->ataio, + /*retries*/ retries, + /*cbfcnp*/ NULL, + /*flags*/ flags, + /*tag_action*/ tag_action, + /*data_ptr*/ data_ptr, + /*dxfer_len*/ dxfer_len, + /*timeout*/ timeout); + + if (ada_flags & ADA_FLAG_CAN_48BIT && lba + sector_count >= ATA_MAX_28BIT_LBA) { + ata_48bit_cmd(&ccb->ataio, command, features, lba, + sector_count); + + } + else if (ada_flags & ATA_SUPPORT_NCQ) { + ata_ncq_cmd(&ccb->ataio, command, lba, + sector_count); } + else { + ata_28bit_cmd(&ccb->ataio, command, features, lba, + sector_count); + } + return 0; +} + +uint64_t +max_sector(int is48bit, struct ata_params *parm) +{ + if (is48bit) + return ((u_int64_t)parm->lba_size48_1 | + ((u_int64_t)parm->lba_size48_2 << 16) | + ((u_int64_t)parm->lba_size48_3 << 32) | + ((u_int64_t)parm->lba_size48_4 << 48)); + else + return ((u_int32_t)parm->lba_size_1 | + ((u_int32_t)parm->lba_size_2 << 16)); +} + +int +camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, int probe_retry_count, + camdd_argmask arglist, int probe_timeout, + uint64_t *maxsector, uint32_t *block_len) +{ + struct scsi_read_capacity_data rcap; + struct scsi_read_capacity_data_long rcaplong; CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); @@ -1327,7 +1431,6 @@ cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); - goto bailout; } @@ -1336,28 +1439,28 @@ goto bailout; } - maxsector = scsi_4btoul(rcap.addr); - block_len = scsi_4btoul(rcap.length); + *maxsector = scsi_4btoul(rcap.addr); + *block_len = scsi_4btoul(rcap.length); /* * A last block of 2^32-1 means that the true capacity is over 2TB, * and we need to issue the long READ CAPACITY to get the real * capacity. Otherwise, we're all set. */ - if (maxsector != 0xffffffff) - goto rcap_done; + if (*maxsector != 0xffffffff) + return 0; scsi_read_capacity_16(&ccb->csio, - /*retries*/ probe_retry_count, - /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, - /*lba*/ 0, - /*reladdr*/ 0, - /*pmi*/ 0, - (uint8_t *)&rcaplong, - sizeof(rcaplong), - /*sense_len*/ SSD_FULL_SIZE, - /*timeout*/ probe_timeout ? probe_timeout : 5000); + /*retries*/ probe_retry_count, + /*cbfcnp*/ NULL, + /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*lba*/ 0, + /*reladdr*/ 0, + /*pmi*/ 0, + (uint8_t *)&rcaplong, + sizeof(rcaplong), + /*sense_len*/ SSD_FULL_SIZE, + /*timeout*/ probe_timeout ? probe_timeout : 5000); /* Disable freezing the device queue */ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; @@ -1377,14 +1480,156 @@ goto bailout; } - maxsector = scsi_8btou64(rcaplong.addr); - block_len = scsi_4btoul(rcaplong.length); + *maxsector = scsi_8btou64(rcaplong.addr); + *block_len = scsi_4btoul(rcaplong.length); + return 0; +bailout: + return -1; +} + +int +camdd_probe_pass_ata(struct cam_device *cam_dev, union ccb *ccb, + camdd_argmask arglist, int probe_retry_count, + int probe_timeout, uint8_t command, ada_flags ada_flags, + uint64_t *maxsector, uint32_t *block_len) +{ + int16_t *ptr = NULL; + size_t dxfer_len = 0; + int retval; + struct ata_params *parm; + + dxfer_len = sizeof(struct ata_params); + ptr = (uint16_t *)malloc(dxfer_len); + if (ptr == NULL) { + warnx("can't malloc memory for identify"); + retval = -1; + goto bailout; + } + bzero(ptr, dxfer_len); + + /* Use the ATA CMDS directly instead of ATA_SCSI Passthrough.*/ + bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) - + sizeof(struct ccb_hdr)); + ata_do_cmd(ccb, + /*retries*/probe_retry_count, + /*flags*/CAM_DIR_IN, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/command, + /*features*/0, + /*lba*/0, + /*sector_count*/sizeof(struct ata_params), + /*data_ptr*/(u_int8_t *)ptr, + /*dxfer_len*/dxfer_len, + /*timeout*/probe_timeout ? probe_timeout : 5000, + /*ada_flags*/ada_flags); + + if (arglist & CAMDD_ARG_ERR_RECOVER) + ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; + + ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; + retval = cam_send_ccb(cam_dev, ccb); + + if (retval != 0) { + warn("error sending ATA_IDENTIFY CCB"); + retval = -1; + goto bailout; + } + + parm = (struct ata_params *)(ptr); + *block_len = (unsigned long)ata_physical_sector_size(parm); + *maxsector = max_sector(ada_flags & ADA_FLAG_CAN_48BIT, parm); + retval = 0; +bailout: + return retval; +} + + +/* + * Need to implement this. Do a basic probe: + * - Check the inquiry data, make sure we're talking to a device that we + * can reasonably expect to talk to -- direct, RBC, CD, WORM. + * - Send a test unit ready, make sure the device is available. + * - Get the capacity and block size. + */ +struct camdd_dev * +camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, + camdd_argmask arglist, int probe_retry_count, + int probe_timeout, int io_retry_count, int io_timeout) +{ + union ccb *ccb; + uint64_t maxsector = 0; + uint32_t cpi_maxio, max_iosize, pass_numblocks; + uint32_t block_len = 0; + struct camdd_dev *dev = NULL; + struct camdd_dev_pass *pass_dev; + struct kevent ke; + struct ccb_getdev cgd; + int retval; + ada_flags ada_flags = 0; + uint8_t command; + int scsi_dev_type; + + if ((retval = get_cgd(cam_dev, &cgd)) != 0) { + warnx("couldn't get CGD"); + return (NULL); + } + + if ((ccb = cam_getccb(cam_dev)) == NULL) { + warnx("Could not allocate CCB"); + retval = -1; + goto bailout_error; + } + + switch(cgd.protocol) { + case PROTO_SCSI: + scsi_dev_type = SID_TYPE(&cam_dev->inq_data); + + /* + * For devices that support READ CAPACITY, we'll attempt to get the + * capacity. Otherwise, we really don't support tape or other + * devices via SCSI passthrough, so just return an error in that case. + */ + switch (scsi_dev_type) { + case T_DIRECT: + case T_WORM: + case T_CDROM: + case T_OPTICAL: + case T_RBC: + break; + + default: + errx(1, "Unsupported SCSI device type %d", scsi_dev_type); + break; /*NOTREACHED*/ + } /*SWitch scsi_dev_type*/ + + + if ((retval = camdd_probe_pass_scsi(cam_dev, ccb, probe_retry_count, + arglist, probe_timeout, &maxsector, &block_len))) { + goto bailout; + } + break; + case PROTO_ATA: + case PROTO_ATAPI: + + command = (cgd.protocol == PROTO_ATA) ? + ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY; + + set_flags(&ada_flags, &cgd); + + if ((retval = camdd_probe_pass_ata(cam_dev, ccb, arglist, probe_retry_count, + probe_timeout, command, ada_flags, &maxsector, &block_len))) { + goto bailout; + } + break; /* switch ATA */ + default: + errx(1, "Unsupported PROTO type %d", cgd.protocol); + break; /*NOTREACHED*/ + } /*switch cgd.protocol */ -rcap_done: if (block_len == 0) { warnx("Sector size for %s%u is 0, cannot continue", - cam_dev->device_name, cam_dev->dev_unit_num); - goto bailout_error; + cam_dev->device_name, cam_dev->dev_unit_num); + goto bailout; } CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi); @@ -1392,7 +1637,7 @@ ccb->ccb_h.func_code = XPT_PATH_INQ; ccb->ccb_h.flags = CAM_DIR_NONE; ccb->ccb_h.retry_count = 1; - + if (cam_send_ccb(cam_dev, ccb) < 0) { warn("error sending XPT_PATH_INQ CCB"); @@ -1410,12 +1655,14 @@ pass_dev = &dev->dev_spec.pass; pass_dev->scsi_dev_type = scsi_dev_type; + pass_dev->protocol = cgd.protocol; + pass_dev->ada_flags = ada_flags; pass_dev->dev = cam_dev; pass_dev->max_sector = maxsector; pass_dev->block_len = block_len; pass_dev->cpi_maxio = ccb->cpi.maxio; snprintf(dev->device_name, sizeof(dev->device_name), "%s%u", - pass_dev->dev->device_name, pass_dev->dev->dev_unit_num); + pass_dev->dev->device_name, pass_dev->dev->dev_unit_num); dev->sector_size = block_len; dev->max_sector = maxsector; @@ -1720,46 +1967,68 @@ * Simplistic translation of CCB status to our local status. */ camdd_buf_status -camdd_ccb_status(union ccb *ccb) +camdd_ccb_status(union ccb *ccb, int protocol) { camdd_buf_status status = CAMDD_STATUS_NONE; cam_status ccb_status; ccb_status = ccb->ccb_h.status & CAM_STATUS_MASK; - switch (ccb_status) { - case CAM_REQ_CMP: { - if (ccb->csio.resid == 0) { - status = CAMDD_STATUS_OK; - } else if (ccb->csio.dxfer_len > ccb->csio.resid) { - status = CAMDD_STATUS_SHORT_IO; - } else { - status = CAMDD_STATUS_EOF; + if (protocol == PROTO_SCSI) { + switch (ccb_status) { + case CAM_REQ_CMP: { + + if (ccb->csio.resid == 0) { + status = CAMDD_STATUS_OK; + } else if (ccb->csio.dxfer_len > ccb->csio.resid) { + status = CAMDD_STATUS_SHORT_IO; + } else { + status = CAMDD_STATUS_EOF; + } + break; + } + case CAM_SCSI_STATUS_ERROR: { + switch (ccb->csio.scsi_status) { + case SCSI_STATUS_OK: + case SCSI_STATUS_COND_MET: + case SCSI_STATUS_INTERMED: + case SCSI_STATUS_INTERMED_COND_MET: + status = CAMDD_STATUS_OK; + break; + case SCSI_STATUS_CMD_TERMINATED: + case SCSI_STATUS_CHECK_COND: + case SCSI_STATUS_QUEUE_FULL: + case SCSI_STATUS_BUSY: + case SCSI_STATUS_RESERV_CONFLICT: + default: + status = CAMDD_STATUS_ERROR; + break; + } + break; + } + default: + status = CAMDD_STATUS_ERROR; + break; } - break; } - case CAM_SCSI_STATUS_ERROR: { - switch (ccb->csio.scsi_status) { - case SCSI_STATUS_OK: - case SCSI_STATUS_COND_MET: - case SCSI_STATUS_INTERMED: - case SCSI_STATUS_INTERMED_COND_MET: - status = CAMDD_STATUS_OK; - break; - case SCSI_STATUS_CMD_TERMINATED: - case SCSI_STATUS_CHECK_COND: - case SCSI_STATUS_QUEUE_FULL: - case SCSI_STATUS_BUSY: - case SCSI_STATUS_RESERV_CONFLICT: - default: - status = CAMDD_STATUS_ERROR; - break; + else { + + switch(ccb_status) { + case CAM_REQ_CMP: { + + if (ccb->ataio.resid == 0) { + status = CAMDD_STATUS_OK; + } else if (ccb->ataio.dxfer_len > ccb->ataio.resid) { + status = CAMDD_STATUS_SHORT_IO; + } else { + status = CAMDD_STATUS_EOF; + } + break; + } + default: + status = CAMDD_STATUS_ERROR; + break; } - break; - } - default: - status = CAMDD_STATUS_ERROR; - break; } return (status); @@ -2154,11 +2423,17 @@ CAM_EPF_ALL, stderr); } - data->resid = ccb.csio.resid; - dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid); + if (pass_dev->protocol == PROTO_SCSI) { + data->resid = ccb.csio.resid; + dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid); + } + else { + data->resid = ccb.ataio.resid; + dev->bytes_transferred += (ccb.ataio.dxfer_len - ccb.ataio.resid); + } if (buf->status == CAMDD_STATUS_NONE) - buf->status = camdd_ccb_status(&ccb); + buf->status = camdd_ccb_status(&ccb, pass_dev->protocol); if (buf->status == CAMDD_STATUS_ERROR) error_count++; else if (buf->status == CAMDD_STATUS_EOF) { @@ -2220,7 +2495,7 @@ */ if (write_dev != 0) { retval = camdd_buf_sg_create(buf, /*iovec*/ 1, - dev->sector_size, &num_sectors, &double_buf_needed); + dev->sector_size, &num_sectors, &double_buf_needed); if (retval != 0) { no_resources = 1; goto bailout; @@ -2412,6 +2687,7 @@ union ccb *ccb; int retval = 0, is_write = dev->write_dev; int double_buf_needed = 0; + uint8_t command; buf = STAILQ_FIRST(&dev->run_queue); if (buf == NULL) { @@ -2438,7 +2714,6 @@ data = &buf->buf_type_spec.data; ccb = &data->ccb; - CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); /* * In almost every case the number of blocks should be the device @@ -2450,33 +2725,100 @@ else num_blocks = data->fill_len / pass_dev->block_len; - scsi_read_write(&ccb->csio, + if(data->fill_len == 0 ) { + retval = -1; + goto bailout; + } + + if (pass_dev->protocol == PROTO_SCSI) { + CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); + + scsi_read_write(&ccb->csio, /*retries*/ dev->retry_count, /*cbfcnp*/ NULL, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*readop*/ (dev->write_dev == 0) ? SCSI_RW_READ : - SCSI_RW_WRITE, + SCSI_RW_WRITE, /*byte2*/ 0, /*minimum_cmd_size*/ dev->min_cmd_size, /*lba*/ buf->lba, /*block_count*/ num_blocks, /*data_ptr*/ (data->sg_count != 0) ? - (uint8_t *)data->segs : data->buf, + (uint8_t *)data->segs : data->buf, /*dxfer_len*/ (num_blocks * pass_dev->block_len), /*sense_len*/ SSD_FULL_SIZE, /*timeout*/ dev->io_timeout); + if (data->sg_count != 0) { + ccb->ccb_h.flags |= CAM_DATA_SG; + ccb->csio.sglist_cnt = data->sg_count; + } + } + else { + + bzero(&(&ccb->ccb_h)[1], + sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr)); + + if (pass_dev->ada_flags & ATA_SUPPORT_NCQ) { + if (is_write == 0) { + command = ATA_READ_FPDMA_QUEUED; + } else { + command = ATA_WRITE_FPDMA_QUEUED; + } + } else if ((pass_dev->ada_flags & ADA_FLAG_CAN_48BIT) && + (buf->lba + num_blocks >= ATA_MAX_28BIT_LBA || + num_blocks > 256)) { + if (pass_dev->ada_flags & ADA_FLAG_CAN_DMA48) { + if (is_write == 0) { + command = ATA_READ_DMA48; + } else { + command = ATA_WRITE_DMA48; + } + } else { + if (is_write == 0) { + command = ATA_READ_MUL48; + } else { + command = ATA_WRITE_MUL48; + } + } + } + else { + if (pass_dev->ada_flags & ADA_FLAG_CAN_DMA) { + if (is_write == 0) { + command = ATA_READ_DMA; + } else { + command = ATA_WRITE_DMA; + } + } else { + if (is_write == 0) { + command = ATA_READ_MUL; + } else { + command = ATA_WRITE_MUL; + } + } + } + + ata_do_cmd(ccb, + /*retries*/dev->retry_count, + /*flags*/(is_write == 0) ? CAM_DIR_IN : CAM_DIR_OUT, + /*tag_action*/CAM_TAG_ACTION_NONE, + /*command*/command, + /*features*/0, + /*lba*/buf->lba, + /*sector_count*/num_blocks, + /*data_ptr*/(data->sg_count != 0) ? + (uint8_t *)data->segs : data->buf, + /*dxfer_len*/num_blocks * pass_dev->block_len, + /*timeout*/dev->io_timeout, + /*adaflags*/pass_dev->ada_flags); + } + /* Disable freezing the device queue */ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; if (dev->retry_count != 0) ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; - if (data->sg_count != 0) { - ccb->csio.sglist_cnt = data->sg_count; - ccb->ccb_h.flags |= CAM_DATA_SG; - } - /* * Store a pointer to the buffer in the CCB. The kernel will * restore this when we get it back, and we'll use it to identify @@ -2495,7 +2837,7 @@ pthread_mutex_lock(&dev->mutex); warn("%s: error sending CAMIOQUEUE ioctl to %s%u", __func__, - pass_dev->dev->device_name, pass_dev->dev->dev_unit_num); + pass_dev->dev->device_name, pass_dev->dev->dev_unit_num); warn("%s: CCB address is %p", __func__, ccb); retval = -1; @@ -3049,12 +3391,12 @@ } devs[i] = camdd_probe_pass(new_cam_dev, - /*io_opts*/ &io_opts[i], - CAMDD_ARG_ERR_RECOVER, - /*probe_retry_count*/ 3, - /*probe_timeout*/ 5000, - /*io_retry_count*/ retry_count, - /*io_timeout*/ timeout); + /*io_opts*/ &io_opts[i], + CAMDD_ARG_ERR_RECOVER, + /*probe_retry_count*/ 3, + /*probe_timeout*/ 5000, + /*io_retry_count*/ retry_count, + /*io_timeout*/ timeout); if (devs[i] == NULL) { warn("Unable to probe device %s%u", new_cam_dev->device_name, @@ -3089,7 +3431,7 @@ } devs[i] = camdd_probe_file(fd, &io_opts[i], - retry_count, timeout); + retry_count, timeout); if (devs[i] == NULL) { error = 1; goto bailout; @@ -3114,10 +3456,6 @@ (devs[i]->start_offset_bytes / devs[i]->sector_size) + (max_io / devs[i]->sector_size) - 1; - devs[i]->sector_io_limit = - (devs[i]->start_offset_bytes / - devs[i]->sector_size) + - (max_io / devs[i]->sector_size) - 1; } devs[i]->next_io_pos_bytes = devs[i]->start_offset_bytes;