Date: Sat, 27 Mar 2004 00:30:35 -0800 (PST) From: Scott Long <scottl@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 49774 for review Message-ID: <200403270830.i2R8UZiC064017@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=49774 Change 49774 by scottl@scottl-junior-camlock on 2004/03/27 00:30:33 Mechanical split of the lun probe and probe periph code into it's own file. The XPT is still painfully SCSI-aware and will require a lot of work, but this is a first step. Affected files ... .. //depot/projects/scottl-camlock/src/sys/cam/cam_probe.c#1 add .. //depot/projects/scottl-camlock/src/sys/cam/cam_probe.h#1 add .. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#2 edit .. //depot/projects/scottl-camlock/src/sys/modules/cam/Makefile#2 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#2 (text+ko) ==== @@ -55,28 +55,13 @@ #include <cam/cam_xpt_sim.h> #include <cam/cam_xpt_periph.h> #include <cam/cam_debug.h> +#include <cam/cam_probe.h> #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_message.h> #include <cam/scsi/scsi_pass.h> #include "opt_cam.h" -/* Datastructures internal to the xpt layer */ - -/* - * Definition of an async handler callback block. These are used to add - * SIMs and peripherals to the async callback lists. - */ -struct async_node { - SLIST_ENTRY(async_node) links; - u_int32_t event_enable; /* Async Event enables */ - void (*callback)(void *arg, u_int32_t code, - struct cam_path *path, void *args); - void *callback_arg; -}; - -SLIST_HEAD(async_list, async_node); -SLIST_HEAD(periph_list, cam_periph); static STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq; /* @@ -90,120 +75,6 @@ /* number of high powered commands that can go through right now */ static int num_highpower = CAM_MAX_HIGHPOWER; -/* - * Structure for queueing a device in a run queue. - * There is one run queue for allocating new ccbs, - * and another for sending ccbs to the controller. - */ -struct cam_ed_qinfo { - cam_pinfo pinfo; - struct cam_ed *device; -}; - -/* - * The CAM EDT (Existing Device Table) contains the device information for - * all devices for all busses in the system. The table contains a - * cam_ed structure for each device on the bus. - */ -struct cam_ed { - TAILQ_ENTRY(cam_ed) links; - struct cam_ed_qinfo alloc_ccb_entry; - struct cam_ed_qinfo send_ccb_entry; - struct cam_et *target; - lun_id_t lun_id; - struct camq drvq; /* - * Queue of type drivers wanting to do - * work on this device. - */ - struct cam_ccbq ccbq; /* Queue of pending ccbs */ - struct async_list asyncs; /* Async callback info for this B/T/L */ - struct periph_list periphs; /* All attached devices */ - u_int generation; /* Generation number */ - struct cam_periph *owner; /* Peripheral driver's ownership tag */ - struct xpt_quirk_entry *quirk; /* Oddities about this device */ - /* Storage for the inquiry data */ -#ifdef CAM_NEW_TRAN_CODE - cam_proto protocol; - u_int protocol_version; - cam_xport transport; - u_int transport_version; -#endif /* CAM_NEW_TRAN_CODE */ - struct scsi_inquiry_data inq_data; - u_int8_t inq_flags; /* - * Current settings for inquiry flags. - * This allows us to override settings - * like disconnection and tagged - * queuing for a device. - */ - u_int8_t queue_flags; /* Queue flags from the control page */ - u_int8_t serial_num_len; - u_int8_t *serial_num; - u_int32_t qfrozen_cnt; - u_int32_t flags; -#define CAM_DEV_UNCONFIGURED 0x01 -#define CAM_DEV_REL_TIMEOUT_PENDING 0x02 -#define CAM_DEV_REL_ON_COMPLETE 0x04 -#define CAM_DEV_REL_ON_QUEUE_EMPTY 0x08 -#define CAM_DEV_RESIZE_QUEUE_NEEDED 0x10 -#define CAM_DEV_TAG_AFTER_COUNT 0x20 -#define CAM_DEV_INQUIRY_DATA_VALID 0x40 - u_int32_t tag_delay_count; -#define CAM_TAG_DELAY_COUNT 5 - u_int32_t refcount; - struct callout_handle c_handle; -}; - -/* - * Each target is represented by an ET (Existing Target). These - * entries are created when a target is successfully probed with an - * identify, and removed when a device fails to respond after a number - * of retries, or a bus rescan finds the device missing. - */ -struct cam_et { - TAILQ_HEAD(, cam_ed) ed_entries; - TAILQ_ENTRY(cam_et) links; - struct cam_eb *bus; - target_id_t target_id; - u_int32_t refcount; - u_int generation; - struct timeval last_reset; -}; - -/* - * Each bus is represented by an EB (Existing Bus). These entries - * are created by calls to xpt_bus_register and deleted by calls to - * xpt_bus_deregister. - */ -struct cam_eb { - TAILQ_HEAD(, cam_et) et_entries; - TAILQ_ENTRY(cam_eb) links; - path_id_t path_id; - struct cam_sim *sim; - struct timeval last_reset; - u_int32_t flags; -#define CAM_EB_RUNQ_SCHEDULED 0x01 - u_int32_t refcount; - u_int generation; -}; - -struct cam_path { - struct cam_periph *periph; - struct cam_eb *bus; - struct cam_et *target; - struct cam_ed *device; -}; - -struct xpt_quirk_entry { - struct scsi_inquiry_pattern inq_pat; - u_int8_t quirks; -#define CAM_QUIRK_NOLUNS 0x01 -#define CAM_QUIRK_NOSERIAL 0x02 -#define CAM_QUIRK_HILUNS 0x04 - u_int mintags; - u_int maxtags; -}; -#define CAM_SCSI2_MAXLUN 8 - typedef enum { XPT_FLAG_OPEN = 0x01 } xpt_flags; @@ -613,22 +484,13 @@ static periph_init_t xpt_periph_init; -static periph_init_t probe_periph_init; - static struct periph_driver xpt_driver = { xpt_periph_init, "xpt", TAILQ_HEAD_INITIALIZER(xpt_driver.units) }; -static struct periph_driver probe_driver = -{ - probe_periph_init, "probe", - TAILQ_HEAD_INITIALIZER(probe_driver.units) -}; - PERIPHDRIVER_DECLARE(xpt, xpt_driver); -PERIPHDRIVER_DECLARE(probe, probe_driver); static d_open_t xptopen; @@ -697,15 +559,6 @@ DECLARE_MODULE(cam, cam_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND); MODULE_VERSION(cam, 1); - -static cam_status xpt_compile_path(struct cam_path *new_path, - struct cam_periph *perph, - path_id_t path_id, - target_id_t target_id, - lun_id_t lun_id); - -static void xpt_release_path(struct cam_path *path); - static void xpt_async_bcast(struct async_list *async_head, u_int32_t async_code, struct cam_path *path, @@ -743,10 +596,6 @@ static struct cam_ed* xpt_find_device(struct cam_et *target, lun_id_t lun_id); static void xpt_scan_bus(struct cam_periph *periph, union ccb *ccb); -static void xpt_scan_lun(struct cam_periph *periph, - struct cam_path *path, cam_flags flags, - union ccb *ccb); -static void xptscandone(struct cam_periph *periph, union ccb *done_ccb); static xpt_busfunc_t xptconfigbuscountfunc; static xpt_busfunc_t xptconfigfunc; static void xpt_config(void *arg); @@ -812,14 +661,6 @@ static xpt_busfunc_t xptsetasyncbusfunc; static cam_status xptregister(struct cam_periph *periph, void *arg); -static cam_status proberegister(struct cam_periph *periph, - void *arg); -static void probeschedule(struct cam_periph *probe_periph); -static void probestart(struct cam_periph *periph, union ccb *start_ccb); -static void proberequestdefaultnegotiation(struct cam_periph *periph); -static void probedone(struct cam_periph *periph, union ccb *done_ccb); -static void probecleanup(struct cam_periph *periph); -static void xpt_find_quirk(struct cam_ed *device); #ifdef CAM_NEW_TRAN_CODE static void xpt_devise_transport(struct cam_path *path); #endif /* CAM_NEW_TRAN_CODE */ @@ -923,12 +764,6 @@ } static void -probe_periph_init() -{ -} - - -static void xptdone(struct cam_periph *periph, union ccb *done_ccb) { /* Caller will release the CCB */ @@ -4012,7 +3847,7 @@ return (status); } -static cam_status +cam_status xpt_compile_path(struct cam_path *new_path, struct cam_periph *perph, path_id_t path_id, target_id_t target_id, lun_id_t lun_id) { @@ -4086,7 +3921,7 @@ return (status); } -static void +void xpt_release_path(struct cam_path *path) { CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_release_path\n")); @@ -5379,682 +5214,7 @@ } } -typedef enum { - PROBE_TUR, - PROBE_INQUIRY, - PROBE_FULL_INQUIRY, - PROBE_MODE_SENSE, - PROBE_SERIAL_NUM, - PROBE_TUR_FOR_NEGOTIATION -} probe_action; - -typedef enum { - PROBE_INQUIRY_CKSUM = 0x01, - PROBE_SERIAL_CKSUM = 0x02, - PROBE_NO_ANNOUNCE = 0x04 -} probe_flags; - -typedef struct { - TAILQ_HEAD(, ccb_hdr) request_ccbs; - probe_action action; - union ccb saved_ccb; - probe_flags flags; - MD5_CTX context; - u_int8_t digest[16]; -} probe_softc; - -static void -xpt_scan_lun(struct cam_periph *periph, struct cam_path *path, - cam_flags flags, union ccb *request_ccb) -{ - struct ccb_pathinq cpi; - cam_status status; - struct cam_path *new_path; - struct cam_periph *old_periph; - int s; - - CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, - ("xpt_scan_lun\n")); - - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); - cpi.ccb_h.func_code = XPT_PATH_INQ; - xpt_action((union ccb *)&cpi); - - if (cpi.ccb_h.status != CAM_REQ_CMP) { - if (request_ccb != NULL) { - request_ccb->ccb_h.status = cpi.ccb_h.status; - xpt_done(request_ccb); - } - return; - } - - if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) { - /* - * Can't scan the bus on an adapter that - * cannot perform the initiator role. - */ - if (request_ccb != NULL) { - request_ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(request_ccb); - } - return; - } - - if (request_ccb == NULL) { - request_ccb = malloc(sizeof(union ccb), M_TEMP, M_NOWAIT); - if (request_ccb == NULL) { - xpt_print_path(path); - printf("xpt_scan_lun: can't allocate CCB, can't " - "continue\n"); - return; - } - new_path = malloc(sizeof(*new_path), M_TEMP, M_NOWAIT); - if (new_path == NULL) { - xpt_print_path(path); - printf("xpt_scan_lun: can't allocate path, can't " - "continue\n"); - free(request_ccb, M_TEMP); - return; - } - status = xpt_compile_path(new_path, xpt_periph, - path->bus->path_id, - path->target->target_id, - path->device->lun_id); - - if (status != CAM_REQ_CMP) { - xpt_print_path(path); - printf("xpt_scan_lun: can't compile path, can't " - "continue\n"); - free(request_ccb, M_TEMP); - free(new_path, M_TEMP); - return; - } - xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1); - request_ccb->ccb_h.cbfcnp = xptscandone; - request_ccb->ccb_h.func_code = XPT_SCAN_LUN; - request_ccb->crcn.flags = flags; - } - - s = splsoftcam(); - if ((old_periph = cam_periph_find(path, "probe")) != NULL) { - probe_softc *softc; - - softc = (probe_softc *)old_periph->softc; - TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, - periph_links.tqe); - } else { - status = cam_periph_alloc(proberegister, NULL, probecleanup, - probestart, "probe", - CAM_PERIPH_BIO, - request_ccb->ccb_h.path, NULL, 0, - request_ccb); - - if (status != CAM_REQ_CMP) { - xpt_print_path(path); - printf("xpt_scan_lun: cam_alloc_periph returned an " - "error, can't continue probe\n"); - request_ccb->ccb_h.status = status; - xpt_done(request_ccb); - } - } - splx(s); -} - -static void -xptscandone(struct cam_periph *periph, union ccb *done_ccb) -{ - xpt_release_path(done_ccb->ccb_h.path); - free(done_ccb->ccb_h.path, M_TEMP); - free(done_ccb, M_TEMP); -} - -static cam_status -proberegister(struct cam_periph *periph, void *arg) -{ - union ccb *request_ccb; /* CCB representing the probe request */ - probe_softc *softc; - - request_ccb = (union ccb *)arg; - if (periph == NULL) { - printf("proberegister: periph was NULL!!\n"); - return(CAM_REQ_CMP_ERR); - } - - if (request_ccb == NULL) { - printf("proberegister: no probe CCB, " - "can't register device\n"); - return(CAM_REQ_CMP_ERR); - } - - softc = (probe_softc *)malloc(sizeof(*softc), M_TEMP, M_NOWAIT); - - if (softc == NULL) { - printf("proberegister: Unable to probe new device. " - "Unable to allocate softc\n"); - return(CAM_REQ_CMP_ERR); - } - TAILQ_INIT(&softc->request_ccbs); - TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, - periph_links.tqe); - softc->flags = 0; - periph->softc = softc; - cam_periph_acquire(periph); - /* - * Ensure we've waited at least a bus settle - * delay before attempting to probe the device. - * For HBAs that don't do bus resets, this won't make a difference. - */ - cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, - scsi_delay); - probeschedule(periph); - return(CAM_REQ_CMP); -} - -static void -probeschedule(struct cam_periph *periph) -{ - struct ccb_pathinq cpi; - union ccb *ccb; - probe_softc *softc; - - softc = (probe_softc *)periph->softc; - ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); - - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); - cpi.ccb_h.func_code = XPT_PATH_INQ; - xpt_action((union ccb *)&cpi); - - /* - * If a device has gone away and another device, or the same one, - * is back in the same place, it should have a unit attention - * condition pending. It will not report the unit attention in - * response to an inquiry, which may leave invalid transfer - * negotiations in effect. The TUR will reveal the unit attention - * condition. Only send the TUR for lun 0, since some devices - * will get confused by commands other than inquiry to non-existent - * luns. If you think a device has gone away start your scan from - * lun 0. This will insure that any bogus transfer settings are - * invalidated. - * - * If we haven't seen the device before and the controller supports - * some kind of transfer negotiation, negotiate with the first - * sent command if no bus reset was performed at startup. This - * ensures that the device is not confused by transfer negotiation - * settings left over by loader or BIOS action. - */ - if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) - && (ccb->ccb_h.target_lun == 0)) { - softc->action = PROBE_TUR; - } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 - && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { - proberequestdefaultnegotiation(periph); - softc->action = PROBE_INQUIRY; - } else { - softc->action = PROBE_INQUIRY; - } - - if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) - softc->flags |= PROBE_NO_ANNOUNCE; - else - softc->flags &= ~PROBE_NO_ANNOUNCE; - - xpt_schedule(periph, ccb->ccb_h.pinfo.priority); -} - -static void -probestart(struct cam_periph *periph, union ccb *start_ccb) -{ - /* Probe the device that our peripheral driver points to */ - struct ccb_scsiio *csio; - probe_softc *softc; - - CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); - - softc = (probe_softc *)periph->softc; - csio = &start_ccb->csio; - - switch (softc->action) { - case PROBE_TUR: - case PROBE_TUR_FOR_NEGOTIATION: - { - scsi_test_unit_ready(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - SSD_FULL_SIZE, - /*timeout*/60000); - break; - } - case PROBE_INQUIRY: - case PROBE_FULL_INQUIRY: - { - u_int inquiry_len; - struct scsi_inquiry_data *inq_buf; - - inq_buf = &periph->path->device->inq_data; - /* - * If the device is currently configured, we calculate an - * MD5 checksum of the inquiry data, and if the serial number - * length is greater than 0, add the serial number data - * into the checksum as well. Once the inquiry and the - * serial number check finish, we attempt to figure out - * whether we still have the same device. - */ - if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { - - MD5Init(&softc->context); - MD5Update(&softc->context, (unsigned char *)inq_buf, - sizeof(struct scsi_inquiry_data)); - softc->flags |= PROBE_INQUIRY_CKSUM; - if (periph->path->device->serial_num_len > 0) { - MD5Update(&softc->context, - periph->path->device->serial_num, - periph->path->device->serial_num_len); - softc->flags |= PROBE_SERIAL_CKSUM; - } - MD5Final(softc->digest, &softc->context); - } - - if (softc->action == PROBE_INQUIRY) - inquiry_len = SHORT_INQUIRY_LENGTH; - else - inquiry_len = inq_buf->additional_length + 4; - - scsi_inquiry(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - (u_int8_t *)inq_buf, - inquiry_len, - /*evpd*/FALSE, - /*page_code*/0, - SSD_MIN_SIZE, - /*timeout*/60 * 1000); - break; - } - case PROBE_MODE_SENSE: - { - void *mode_buf; - int mode_buf_len; - - mode_buf_len = sizeof(struct scsi_mode_header_6) - + sizeof(struct scsi_mode_blk_desc) - + sizeof(struct scsi_control_page); - mode_buf = malloc(mode_buf_len, M_TEMP, M_NOWAIT); - if (mode_buf != NULL) { - scsi_mode_sense(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - /*dbd*/FALSE, - SMS_PAGE_CTRL_CURRENT, - SMS_CONTROL_MODE_PAGE, - mode_buf, - mode_buf_len, - SSD_FULL_SIZE, - /*timeout*/60000); - break; - } - xpt_print_path(periph->path); - printf("Unable to mode sense control page - malloc failure\n"); - softc->action = PROBE_SERIAL_NUM; - } - /* FALLTHROUGH */ - case PROBE_SERIAL_NUM: - { - struct scsi_vpd_unit_serial_number *serial_buf; - struct cam_ed* device; - - serial_buf = NULL; - device = periph->path->device; - device->serial_num = NULL; - device->serial_num_len = 0; - - if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0) - serial_buf = (struct scsi_vpd_unit_serial_number *) - malloc(sizeof(*serial_buf), M_TEMP, - M_NOWAIT | M_ZERO); - - if (serial_buf != NULL) { - scsi_inquiry(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - (u_int8_t *)serial_buf, - sizeof(*serial_buf), - /*evpd*/TRUE, - SVPD_UNIT_SERIAL_NUMBER, - SSD_MIN_SIZE, - /*timeout*/60 * 1000); - break; - } - /* - * We'll have to do without, let our probedone - * routine finish up for us. - */ - start_ccb->csio.data_ptr = NULL; - probedone(periph, start_ccb); - return; - } - } - xpt_action(start_ccb); -} - -static void -proberequestdefaultnegotiation(struct cam_periph *periph) -{ - struct ccb_trans_settings cts; - - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); - cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; -#ifdef CAM_NEW_TRAN_CODE - cts.type = CTS_TYPE_USER_SETTINGS; -#else /* CAM_NEW_TRAN_CODE */ - cts.flags = CCB_TRANS_USER_SETTINGS; -#endif /* CAM_NEW_TRAN_CODE */ - xpt_action((union ccb *)&cts); - cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; -#ifdef CAM_NEW_TRAN_CODE - cts.type = CTS_TYPE_CURRENT_SETTINGS; -#else /* CAM_NEW_TRAN_CODE */ - cts.flags &= ~CCB_TRANS_USER_SETTINGS; - cts.flags |= CCB_TRANS_CURRENT_SETTINGS; -#endif /* CAM_NEW_TRAN_CODE */ - xpt_action((union ccb *)&cts); -} - -static void -probedone(struct cam_periph *periph, union ccb *done_ccb) -{ - probe_softc *softc; - struct cam_path *path; - u_int32_t priority; - - CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); - - softc = (probe_softc *)periph->softc; - path = done_ccb->ccb_h.path; - priority = done_ccb->ccb_h.pinfo.priority; - - switch (softc->action) { - case PROBE_TUR: - { - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - - if (cam_periph_error(done_ccb, 0, - SF_NO_PRINT, NULL) == ERESTART) - return; - else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, - /*count*/1, - /*run_queue*/TRUE); - } - softc->action = PROBE_INQUIRY; - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - case PROBE_INQUIRY: - case PROBE_FULL_INQUIRY: - { - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - struct scsi_inquiry_data *inq_buf; - u_int8_t periph_qual; - - path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; - inq_buf = &path->device->inq_data; - - periph_qual = SID_QUAL(inq_buf); - - switch(periph_qual) { - case SID_QUAL_LU_CONNECTED: - { - u_int8_t alen; - - /* - * We conservatively request only - * SHORT_INQUIRY_LEN bytes of inquiry - * information during our first try - * at sending an INQUIRY. If the device - * has more information to give, - * perform a second request specifying - * the amount of information the device - * is willing to give. - */ - alen = inq_buf->additional_length; - if (softc->action == PROBE_INQUIRY - && alen > (SHORT_INQUIRY_LENGTH - 4)) { - softc->action = PROBE_FULL_INQUIRY; - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - - xpt_find_quirk(path->device); - -#ifdef CAM_NEW_TRAN_CODE - xpt_devise_transport(path); -#endif /* CAM_NEW_TRAN_CODE */ - if ((inq_buf->flags & SID_CmdQue) != 0) - softc->action = PROBE_MODE_SENSE; - else - softc->action = PROBE_SERIAL_NUM; - - path->device->flags &= ~CAM_DEV_UNCONFIGURED; - - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } - default: - break; - } - } else if (cam_periph_error(done_ccb, 0, - done_ccb->ccb_h.target_lun > 0 - ? SF_RETRY_UA|SF_QUIET_IR - : SF_RETRY_UA, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - /* - * If we get to this point, we got an error status back - * from the inquiry and the error status doesn't require - * automatically retrying the command. Therefore, the - * inquiry failed. If we had inquiry information before - * for this device, but this latest inquiry command failed, - * the device has probably gone away. If this device isn't - * already marked unconfigured, notify the peripheral - * drivers that this device is no more. - */ - if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0) - /* Send the async notification. */ - xpt_async(AC_LOST_DEVICE, path, NULL); - - xpt_release_ccb(done_ccb); - break; - } - case PROBE_MODE_SENSE: - { - struct ccb_scsiio *csio; - struct scsi_mode_header_6 *mode_hdr; - - csio = &done_ccb->csio; - mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; - if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - struct scsi_control_page *page; - u_int8_t *offset; - - offset = ((u_int8_t *)&mode_hdr[1]) - + mode_hdr->blk_desc_len; - page = (struct scsi_control_page *)offset; - path->device->queue_flags = page->queue_flags; - } else if (cam_periph_error(done_ccb, 0, - SF_RETRY_UA|SF_NO_PRINT, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, - /*count*/1, /*run_queue*/TRUE); - } - xpt_release_ccb(done_ccb); - free(mode_hdr, M_TEMP); - softc->action = PROBE_SERIAL_NUM; - xpt_schedule(periph, priority); - return; - } - case PROBE_SERIAL_NUM: - { - struct ccb_scsiio *csio; - struct scsi_vpd_unit_serial_number *serial_buf; - u_int32_t priority; - int changed; - int have_serialnum; - - changed = 1; - have_serialnum = 0; - csio = &done_ccb->csio; - priority = done_ccb->ccb_h.pinfo.priority; - serial_buf = - (struct scsi_vpd_unit_serial_number *)csio->data_ptr; - - /* Clean up from previous instance of this device */ - if (path->device->serial_num != NULL) { - free(path->device->serial_num, M_DEVBUF); - path->device->serial_num = NULL; - path->device->serial_num_len = 0; - } - - if (serial_buf == NULL) { - /* - * Don't process the command as it was never sent - */ - } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP - && (serial_buf->length > 0)) { - - have_serialnum = 1; - path->device->serial_num = - (u_int8_t *)malloc((serial_buf->length + 1), - M_DEVBUF, M_NOWAIT); - if (path->device->serial_num != NULL) { - bcopy(serial_buf->serial_num, - path->device->serial_num, - serial_buf->length); - path->device->serial_num_len = - serial_buf->length; - path->device->serial_num[serial_buf->length] - = '\0'; - } - } else if (cam_periph_error(done_ccb, 0, - SF_RETRY_UA|SF_NO_PRINT, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - - /* - * Let's see if we have seen this device before. - */ - if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { - MD5_CTX context; - u_int8_t digest[16]; - - MD5Init(&context); - - MD5Update(&context, - (unsigned char *)&path->device->inq_data, - sizeof(struct scsi_inquiry_data)); - - if (have_serialnum) - MD5Update(&context, serial_buf->serial_num, - serial_buf->length); - - MD5Final(digest, &context); - if (bcmp(softc->digest, digest, 16) == 0) - changed = 0; - - /* - * XXX Do we need to do a TUR in order to ensure - * that the device really hasn't changed??? - */ - if ((changed != 0) - && ((softc->flags & PROBE_NO_ANNOUNCE) == 0)) - xpt_async(AC_LOST_DEVICE, path, NULL); - } - if (serial_buf != NULL) - free(serial_buf, M_TEMP); - - if (changed != 0) { - /* - * Now that we have all the necessary - * information to safely perform transfer - * negotiations... Controllers don't perform - * any negotiation or tagged queuing until - * after the first XPT_SET_TRAN_SETTINGS ccb is - * received. So, on a new device, just retreive - * the user settings, and set them as the current - * settings to set the device up. - */ - proberequestdefaultnegotiation(periph); - xpt_release_ccb(done_ccb); - - /* - * Perform a TUR to allow the controller to - * perform any necessary transfer negotiation. - */ - softc->action = PROBE_TUR_FOR_NEGOTIATION; - xpt_schedule(periph, priority); - return; - } - xpt_release_ccb(done_ccb); - break; - } - case PROBE_TUR_FOR_NEGOTIATION: - if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } - - path->device->flags &= ~CAM_DEV_UNCONFIGURED; - - if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { - /* Inform the XPT that a new device has been found */ - done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action(done_ccb); - - xpt_async(AC_FOUND_DEVICE, xpt_periph->path, done_ccb); - } - xpt_release_ccb(done_ccb); - break; - } - done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); - TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); - done_ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(done_ccb); - if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { - cam_periph_invalidate(periph); - cam_periph_release(periph); - } else { - probeschedule(periph); - } -} - -static void -probecleanup(struct cam_periph *periph) -{ - free(periph->softc, M_TEMP); -} - -static void +void xpt_find_quirk(struct cam_ed *device) { caddr_t match; ==== //depot/projects/scottl-camlock/src/sys/modules/cam/Makefile#2 (text+ko) ==== @@ -19,6 +19,7 @@ SRCS+= device_if.h bus_if.h vnode_if.h SRCS+= cam.c cam_periph.c cam_queue.c SRCS+= cam_sim.c cam_xpt.c +SRCS+= scsi_probe.c SRCS+= scsi_all.c scsi_cd.c scsi_ch.c SRCS+= scsi_da.c SRCS+= scsi_pass.c
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403270830.i2R8UZiC064017>