Пример #1
0
static int
adaclose(struct disk *dp)
{
	struct	cam_periph *periph;
	struct	ada_softc *softc;
	union ccb *ccb;
	int error;

	periph = (struct cam_periph *)dp->d_drv1;
	if (periph == NULL)
		return (ENXIO);	

	cam_periph_lock(periph);
	if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
		cam_periph_unlock(periph);
		cam_periph_release(periph);
		return (error);
	}

	softc = (struct ada_softc *)periph->softc;
	/* We only sync the cache if the drive is capable of it. */
	if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
	    (softc->flags & ADA_FLAG_PACK_INVALID) == 0) {

		ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
		cam_fill_ataio(&ccb->ataio,
				    1,
				    adadone,
				    CAM_DIR_NONE,
				    0,
				    NULL,
				    0,
				    ada_default_timeout*1000);

		if (softc->flags & ADA_FLAG_CAN_48BIT)
			ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0);
		else
			ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
		cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
		    /*sense_flags*/0, softc->disk->d_devstat);

		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
			xpt_print(periph->path, "Synchronize cache failed\n");

		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);
	}

	softc->flags &= ~ADA_FLAG_OPEN;
	cam_periph_unhold(periph);
	cam_periph_unlock(periph);
	cam_periph_release(periph);
	return (0);	
}
Пример #2
0
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);
}
Пример #3
0
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);
}
Пример #4
0
static void
pmpstart(struct cam_periph *periph, union ccb *start_ccb)
{
	struct ccb_trans_settings cts;
	struct ccb_ataio *ataio;
	struct pmp_softc *softc;
	struct cam_path *dpath;
	int revision = 0;

	softc = (struct pmp_softc *)periph->softc;
	ataio = &start_ccb->ataio;

	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("pmpstart\n"));

	if (softc->restart) {
		softc->restart = 0;
		softc->state = min(softc->state, PMP_STATE_PRECONFIG);
	}
	/* Fetch user wanted device speed. */
	if (softc->state == PMP_STATE_RESET ||
	    softc->state == PMP_STATE_CONNECT) {
		if (xpt_create_path(&dpath, periph,
		    xpt_path_path_id(periph->path),
		    softc->pm_step, 0) == CAM_REQ_CMP) {
			bzero(&cts, sizeof(cts));
			xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE);
			cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
			cts.type = CTS_TYPE_USER_SETTINGS;
			xpt_action((union ccb *)&cts);
			if (cts.xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
				revision = cts.xport_specific.sata.revision;
			xpt_free_path(dpath);
		}
	}
	switch (softc->state) {
	case PMP_STATE_PORTS:
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_read_cmd(ataio, 2, 15);
		break;
	case PMP_STATE_PRECONFIG:
		/* Get/update host SATA capabilities. */
		bzero(&cts, sizeof(cts));
		xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
		cts.type = CTS_TYPE_CURRENT_SETTINGS;
		xpt_action((union ccb *)&cts);
		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
			softc->caps = cts.xport_specific.sata.caps;
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_write_cmd(ataio, 0x60, 15, 0x0);
		break;
	case PMP_STATE_RESET:
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_write_cmd(ataio, 2, softc->pm_step,
		    (revision << 4) |
		    ((softc->found & (1 << softc->pm_step)) ? 0 : 1));
		break;
	case PMP_STATE_CONNECT:
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_write_cmd(ataio, 2, softc->pm_step,
		    (revision << 4));
		break;
	case PMP_STATE_CHECK:
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_read_cmd(ataio, 0, softc->pm_step);
		break;
	case PMP_STATE_CLEAR:
		softc->reset = 0;
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_write_cmd(ataio, 1, softc->pm_step, 0xFFFFFFFF);
		break;
	case PMP_STATE_CONFIG:
		cam_fill_ataio(ataio,
		      pmp_retry_count,
		      pmpdone,
		      /*flags*/CAM_DIR_NONE,
		      0,
		      /*data_ptr*/NULL,
		      /*dxfer_len*/0,
		      pmp_default_timeout * 1000);
		ata_pm_write_cmd(ataio, 0x60, 15, 0x07 |
		    ((softc->caps & CTS_SATA_CAPS_H_AN) ? 0x08 : 0));
		break;
	default:
		break;
	}
	xpt_action(start_ccb);
}
Пример #5
0
/* 
 * Download firmware stored in buf to cam_dev. If simulation mode
 * is enabled, only show what packet sizes would be sent to the 
 * device but do not sent any actual packets
 */
static int
fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp,
    char *buf, int img_size, int sim_mode, int printerrors, int retry_count,
    int timeout, const char *imgname, const char *type)
{
	struct scsi_write_buffer cdb;
	progress_t progress;
	int size;
	union ccb *ccb;
	int pkt_count = 0;
	int max_pkt_size;
	u_int32_t pkt_size = 0;
	char *pkt_ptr = buf;
	u_int32_t offset;
	int last_pkt = 0;
	int16_t *ptr;

	if ((ccb = cam_getccb(cam_dev)) == NULL) {
		warnx("Could not allocate CCB");
		return (1);
	}
	if (strcmp(type, "scsi") == 0) {
		scsi_test_unit_ready(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG,
		    SSD_FULL_SIZE, 5000);
	} else if (strcmp(type, "ata") == 0) {
		/* cam_getccb cleans up the header, caller has to zero the payload */
		bzero(&(&ccb->ccb_h)[1],
		      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));

		ptr = (uint16_t *)malloc(sizeof(struct ata_params));

		if (ptr == NULL) {
			cam_freeccb(ccb);
			warnx("can't malloc memory for identify\n");
			return(1);
		}
		bzero(ptr, sizeof(struct ata_params));
		cam_fill_ataio(&ccb->ataio,
                      1,
                      NULL,
                      /*flags*/CAM_DIR_IN,
                      MSG_SIMPLE_Q_TAG,
                      /*data_ptr*/(uint8_t *)ptr,
                      /*dxfer_len*/sizeof(struct ata_params),
                      timeout ? timeout : 30 * 1000);
		ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
	} else {
		warnx("weird disk type '%s'", type);
		return 1;
	}
	/* Disable freezing the device queue. */
	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
	if (cam_send_ccb(cam_dev, ccb) < 0) {
		warnx("Error sending identify/test unit ready");
		if (printerrors)
			cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
			    CAM_EPF_ALL, stderr);
		cam_freeccb(ccb);
		return(1);
	}
	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
		warnx("Device is not ready");
		if (printerrors)
			cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
			    CAM_EPF_ALL, stderr);
		cam_freeccb(ccb);
		return (1);
	}
	max_pkt_size = vp->max_pkt_size;
	if (vp->max_pkt_size == 0 && strcmp(type, "ata") == 0) {
		max_pkt_size = UNKNOWN_MAX_PKT_SIZE;
	}
	pkt_size = vp->max_pkt_size;
	progress_init(&progress, imgname, size = img_size);
	/* Download single fw packets. */
	do {
		if (img_size <= max_pkt_size) {
			last_pkt = 1;
			pkt_size = img_size;
		}
		progress_update(&progress, size - img_size);
		progress_draw(&progress);
		bzero(&cdb, sizeof(cdb));
		if (strcmp(type, "scsi") == 0) {
			cdb.opcode  = WRITE_BUFFER;
			cdb.control = 0;
			/* Parameter list length. */
			scsi_ulto3b(pkt_size, &cdb.length[0]);
			offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0;
			scsi_ulto3b(offset, &cdb.offset[0]);
			cdb.byte2 = last_pkt ? vp->cdb_byte2_last : vp->cdb_byte2;
			cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0;
			/* Zero out payload of ccb union after ccb header. */
			bzero((u_char *)ccb + sizeof(struct ccb_hdr),
			    sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
			/* Copy previously constructed cdb into ccb_scsiio struct. */
			bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0],
			    sizeof(struct scsi_write_buffer));
			/* Fill rest of ccb_scsiio struct. */
			if (!sim_mode) {
				cam_fill_csio(&ccb->csio,		/* ccb_scsiio	*/
				    retry_count,			/* retries	*/
				    NULL,				/* cbfcnp	*/
				    CAM_DIR_OUT | CAM_DEV_QFRZDIS,	/* flags	*/
				    CAM_TAG_ACTION_NONE,		/* tag_action	*/
				    (u_char *)pkt_ptr,			/* data_ptr	*/
				    pkt_size,				/* dxfer_len	*/
				    SSD_FULL_SIZE,			/* sense_len	*/
				    sizeof(struct scsi_write_buffer),	/* cdb_len	*/
				    timeout ? timeout : CMD_TIMEOUT);	/* timeout	*/
			}
		} else if (strcmp(type, "ata") == 0) {
			bzero(&(&ccb->ccb_h)[1],
			      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
			if (!sim_mode) {
				uint32_t	off;

				cam_fill_ataio(&ccb->ataio,
					(last_pkt) ? 256 : retry_count,
					NULL,
					/*flags*/CAM_DIR_OUT | CAM_DEV_QFRZDIS,
					CAM_TAG_ACTION_NONE,
					/*data_ptr*/(uint8_t *)pkt_ptr,
					/*dxfer_len*/pkt_size,
					timeout ? timeout : 30 * 1000);
				off = (uint32_t)(pkt_ptr - buf);
				ata_28bit_cmd(&ccb->ataio, ATA_DOWNLOAD_MICROCODE,
					USE_OFFSETS_FEATURE,
					ATA_MAKE_LBA(off, pkt_size),
					ATA_MAKE_SECTORS(pkt_size));
			}
		}
		if (!sim_mode) {
			/* Execute the command. */
			if (cam_send_ccb(cam_dev, ccb) < 0 ||
			    (ccb->ccb_h.status & CAM_STATUS_MASK) !=
			    CAM_REQ_CMP) {
				warnx("Error writing image to device");
				if (printerrors)
					cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
						   CAM_EPF_ALL, stderr);
				goto bailout;
			}
		}
		/* Prepare next round. */
		pkt_count++;
		pkt_ptr += pkt_size;
		img_size -= pkt_size;
	} while(!last_pkt);
	progress_complete(&progress, size - img_size);
	cam_freeccb(ccb);
	return (0);
bailout:
	progress_complete(&progress, size - img_size);
	cam_freeccb(ccb);
	return (1);
}