Date: Sat, 4 Jul 2009 11:12:50 GMT From: Alexander Motin <mav@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 165588 for review Message-ID: <200907041112.n64BCoF8056027@repoman.freebsd.org>
index | next in thread | raw e-mail
http://perforce.freebsd.org/chv.cgi?CH=165588 Change 165588 by mav@mav_mavbook on 2009/07/04 11:12:37 Set device to use it's maximal supported transfer mode. It should not have much reason to do it for SATA, but some (at least ATAPI) devices aren't working without it. Change moments, when SIM reported PMP presence. Affected files ... .. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#11 edit .. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#11 edit .. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#25 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#11 (text+ko) ==== @@ -221,3 +221,80 @@ dst[j++] = 0x00; } +int +ata_max_pmode(struct ata_params *ap) +{ + if (ap->atavalid & ATA_FLAG_64_70) { + if (ap->apiomodes & 0x02) + return ATA_PIO4; + if (ap->apiomodes & 0x01) + return ATA_PIO3; + } + if (ap->mwdmamodes & 0x04) + return ATA_PIO4; + if (ap->mwdmamodes & 0x02) + return ATA_PIO3; + if (ap->mwdmamodes & 0x01) + return ATA_PIO2; + if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200) + return ATA_PIO2; + if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100) + return ATA_PIO1; + if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000) + return ATA_PIO0; + return ATA_PIO0; +} + +int +ata_max_wmode(struct ata_params *ap) +{ + if (ap->mwdmamodes & 0x04) + return ATA_WDMA2; + if (ap->mwdmamodes & 0x02) + return ATA_WDMA1; + if (ap->mwdmamodes & 0x01) + return ATA_WDMA0; + return -1; +} + +int +ata_max_umode(struct ata_params *ap) +{ + if (ap->atavalid & ATA_FLAG_88) { + if (ap->udmamodes & 0x40) + return ATA_UDMA6; + if (ap->udmamodes & 0x20) + return ATA_UDMA5; + if (ap->udmamodes & 0x10) + return ATA_UDMA4; + if (ap->udmamodes & 0x08) + return ATA_UDMA3; + if (ap->udmamodes & 0x04) + return ATA_UDMA2; + if (ap->udmamodes & 0x02) + return ATA_UDMA1; + if (ap->udmamodes & 0x01) + return ATA_UDMA0; + } + return -1; +} + +int +ata_max_mode(struct ata_params *ap, int mode, int maxmode) +{ + + if (maxmode && mode > maxmode) + mode = maxmode; + + if (mode >= ATA_UDMA0 && ata_max_umode(ap) > 0) + return (min(mode, ata_max_umode(ap))); + + if (mode >= ATA_WDMA0 && ata_max_wmode(ap) > 0) + return (min(mode, ata_max_wmode(ap))); + + if (mode > ata_max_pmode(ap)) + return (min(mode, ata_max_pmode(ap))); + + return (mode); +} + ==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#11 (text+ko) ==== @@ -95,4 +95,9 @@ void ata_btrim(int8_t *buf, int len); void ata_bpack(int8_t *src, int8_t *dst, int len); +int ata_max_pmode(struct ata_params *ap); +int ata_max_wmode(struct ata_params *ap); +int ata_max_umode(struct ata_params *ap); +int ata_max_mode(struct ata_params *ap, int mode, int maxmode); + #endif ==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#25 (text+ko) ==== @@ -93,6 +93,7 @@ typedef enum { PROBE_RESET, PROBE_IDENTIFY, + PROBE_SETMODE, PROBE_INQUIRY, PROBE_FULL_INQUIRY, PROBE_PM_PID, @@ -108,6 +109,7 @@ static char *probe_action_text[] = { "PROBE_RESET", "PROBE_IDENTIFY", + "PROBE_SETMODE", "PROBE_INQUIRY", "PROBE_FULL_INQUIRY", "PROBE_PM_PID", @@ -277,7 +279,7 @@ if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) PROBE_SET_ACTION(softc, PROBE_RESET); else if (periph->path->device->protocol == PROTO_SATAPM) - PROBE_SET_ACTION(softc, PROBE_RESET); + PROBE_SET_ACTION(softc, PROBE_PM_PID); else PROBE_SET_ACTION(softc, PROBE_IDENTIFY); @@ -295,6 +297,7 @@ /* Probe the device that our peripheral driver points to */ struct ccb_ataio *ataio; struct ccb_scsiio *csio; + struct ccb_trans_settings cts; probe_softc *softc; CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); @@ -305,6 +308,16 @@ switch (softc->action) { case PROBE_RESET: + if (start_ccb->ccb_h.target_id == 15) { + /* Report SIM that we have no knowledge about PM presence. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, start_ccb->ccb_h.path, 1); + cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.xport_specific.sata.pm_present = 0; + cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; + xpt_action((union ccb *)&cts); + } cam_fill_ataio(ataio, 0, probedone, @@ -350,6 +363,23 @@ ata_36bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); break; } + case PROBE_SETMODE: + { + struct ata_params *ident_buf = + &periph->path->device->ident_data; + + cam_fill_ataio(ataio, + 1, + probedone, + /*flags*/CAM_DIR_IN, + MSG_SIMPLE_Q_TAG, + /*data_ptr*/(u_int8_t *)ident_buf, + /*dxfer_len*/sizeof(struct ata_params), + 30 * 1000); + ata_36bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, + ata_max_mode(ident_buf, ATA_UDMA6, ATA_UDMA6)); + break; + } case PROBE_INQUIRY: case PROBE_FULL_INQUIRY: { @@ -369,7 +399,7 @@ */ inquiry_len = roundup2(inquiry_len, 2); scsi_inquiry(csio, - /*retries*/4, + /*retries*/1, probedone, MSG_SIMPLE_Q_TAG, (u_int8_t *)inq_buf, @@ -623,6 +653,16 @@ PROBE_SET_ACTION(softc, PROBE_IDENTIFY); } else if (sign == 0x9669 && done_ccb->ccb_h.target_id == 15) { + struct ccb_trans_settings cts; + + /* Report SIM that PM is present. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, 1); + cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.xport_specific.sata.pm_present = 1; + cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; + xpt_action((union ccb *)&cts); path->device->protocol = PROTO_SATAPM; PROBE_SET_ACTION(softc, PROBE_PM_PID); } else if (sign == 0xeb14 && @@ -721,21 +761,10 @@ scsi_find_quirk(path->device); ata_device_transport(path); -// if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) { - if (path->device->protocol == PROTO_ATA) { - path->device->flags &= ~CAM_DEV_UNCONFIGURED; - 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); - xpt_release_ccb(done_ccb); - break; - } else { - PROBE_SET_ACTION(softc, PROBE_INQUIRY); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } + PROBE_SET_ACTION(softc, PROBE_SETMODE); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; } else if (cam_periph_error(done_ccb, 0, 0, &softc->saved_ccb) == ERESTART) { return; @@ -762,6 +791,33 @@ xpt_release_ccb(done_ccb); break; } + case PROBE_SETMODE: + { + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + if (path->device->protocol == PROTO_ATA) { + path->device->flags &= ~CAM_DEV_UNCONFIGURED; + 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); + xpt_release_ccb(done_ccb); + break; + } else { + PROBE_SET_ACTION(softc, PROBE_INQUIRY); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + } else if (cam_periph_error(done_ccb, 0, 0, + &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); + } + goto device_fail; + } case PROBE_INQUIRY: case PROBE_FULL_INQUIRY: { @@ -1081,7 +1137,6 @@ struct cam_path *path; ata_scan_bus_info *scan_info; union ccb *work_ccb; - struct ccb_trans_settings cts; cam_status status; CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE, @@ -1118,14 +1173,6 @@ scan_info->cpi = &work_ccb->cpi; scan_info->found = 0x8001; scan_info->counter = 0; - /* Report SIM that we have no knowledge about PM presence. */ - bzero(&cts, sizeof(cts)); - xpt_setup_ccb(&cts.ccb_h, scan_info->request_ccb->ccb_h.path, 1); - cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; - cts.type = CTS_TYPE_CURRENT_SETTINGS; - cts.xport_specific.sata.pm_present = 0; - cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; - xpt_action((union ccb *)&cts); /* If PM supported, probe it first. */ if (scan_info->cpi->hba_inquiry & PI_SATAPM) scan_info->counter = 15; @@ -1145,18 +1192,23 @@ /* Free the current request path- we're done with it. */ xpt_free_path(work_ccb->ccb_h.path); /* If there is PM... */ - if (scan_info->counter == 15 && - work_ccb->ccb_h.ppriv_field1 != 0) { - /* Save PM probe result. */ - scan_info->found = work_ccb->ccb_h.ppriv_field1; - /* Report SIM that PM is present. */ - bzero(&cts, sizeof(cts)); - xpt_setup_ccb(&cts.ccb_h, scan_info->request_ccb->ccb_h.path, 1); - cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; - cts.type = CTS_TYPE_CURRENT_SETTINGS; - cts.xport_specific.sata.pm_present = 1; - cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; - xpt_action((union ccb *)&cts); + if (scan_info->counter == 15) { + if (work_ccb->ccb_h.ppriv_field1 != 0) { + /* Save PM probe result. */ + scan_info->found = work_ccb->ccb_h.ppriv_field1; + } else { + struct ccb_trans_settings cts; + + /* Report SIM that PM is absent. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, + scan_info->request_ccb->ccb_h.path, 1); + cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.xport_specific.sata.pm_present = 1; + cts.xport_specific.sata.valid = CTS_SATA_VALID_PM; + xpt_action((union ccb *)&cts); + } } take_next: /* Take next device. Wrap from 15 (PM) to 0. */help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907041112.n64BCoF8056027>
