diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index a0871ac7f3f5..0509ef7372c1 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -149,6 +149,7 @@ .Op generic args .Op Fl c .Op Fl D Ar enable|disable +.Op Fl M Ar mode .Op Fl O Ar offset .Op Fl q .Op Fl R Ar syncrate @@ -705,6 +706,8 @@ Show or set current negotiation settings. This is the default. .It Fl D Ar enable|disable Enable or disable disconnection. +.It Fl M Ar mode +Set ATA mode. .It Fl O Ar offset Set the command delay offset. .It Fl q diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 73bcd8fca05b..1e71ae0caae1 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -125,7 +125,7 @@ struct camcontrol_opts { #ifndef MINIMALISTIC static const char scsicmd_opts[] = "a:c:i:o:r"; static const char readdefect_opts[] = "f:GP"; -static const char negotiate_opts[] = "acD:O:qR:T:UW:"; +static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; #endif struct camcontrol_opts option_table[] = { @@ -3112,6 +3112,7 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, int user_settings = 0; int retval = 0; int disc_enable = -1, tag_enable = -1; + int mode = -1; int offset = -1; double syncrate = -1; int bus_width = -1; @@ -3120,12 +3121,10 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, struct ccb_pathinq cpi; ccb = cam_getccb(device); - if (ccb == NULL) { warnx("ratecontrol: error allocating ccb"); return(1); } - while ((c = getopt(argc, argv, combinedopt)) != -1) { switch(c){ case 'a': @@ -3146,6 +3145,15 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, } change_settings = 1; break; + case 'M': + mode = ata_string2mode(optarg); + if (mode < 0) { + warnx("unknown mode '%s'", optarg); + retval = 1; + goto ratecontrol_bailout; + } + change_settings = 1; + break; case 'O': offset = strtol(optarg, NULL, 0); if (offset < 0) { @@ -3160,7 +3168,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, break; case 'R': syncrate = atof(optarg); - if (syncrate < 0) { warnx("sync rate %f is < 0", syncrate); retval = 1; @@ -3196,17 +3203,14 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, break; } } - bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); - /* * Grab path inquiry information, so we can determine whether * or not the initiator is capable of the things that the user * requests. */ ccb->ccb_h.func_code = XPT_PATH_INQ; - if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_PATH_INQ CCB"); if (arglist & CAM_ARG_VERBOSE) { @@ -3216,7 +3220,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("XPT_PATH_INQ CCB failed"); if (arglist & CAM_ARG_VERBOSE) { @@ -3226,17 +3229,14 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq)); - bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr)); - - if (quiet == 0) - fprintf(stdout, "Current Parameters:\n"); - + if (quiet == 0) { + fprintf(stdout, "%s parameters:\n", + user_settings ? "User" : "Current"); + } retval = get_print_cts(device, user_settings, quiet, &ccb->cts); - if (retval != 0) goto ratecontrol_bailout; @@ -3246,16 +3246,20 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, if (change_settings) { int didsettings = 0; struct ccb_trans_settings_spi *spi = NULL; + struct ccb_trans_settings_ata *ata = NULL; + struct ccb_trans_settings_sata *sata = NULL; struct ccb_trans_settings_scsi *scsi = NULL; - if (ccb->cts.transport == XPORT_SPI) { + if (ccb->cts.transport == XPORT_SPI) spi = &ccb->cts.xport_specific.spi; - spi->valid = 0; - } - if (ccb->cts.protocol == PROTO_SCSI) { + if (ccb->cts.transport == XPORT_ATA) + ata = &ccb->cts.xport_specific.ata; + if (ccb->cts.transport == XPORT_SATA) + sata = &ccb->cts.xport_specific.sata; + if (ccb->cts.protocol == PROTO_SCSI) scsi = &ccb->cts.proto_specific.scsi; - scsi->valid = 0; - } + ccb->cts.xport_specific.valid = 0; + ccb->cts.proto_specific.valid = 0; if (spi && disc_enable != -1) { spi->valid |= CTS_SPI_VALID_DISC; if (disc_enable == 0) @@ -3263,7 +3267,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, else spi->flags |= CTS_SPI_FLAGS_DISC_ENB; } - if (scsi && tag_enable != -1) { if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) { warnx("HBA does not support tagged queueing, " @@ -3271,21 +3274,16 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - scsi->valid |= CTS_SCSI_VALID_TQ; - if (tag_enable == 0) scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; else scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; didsettings++; } - if (spi && offset != -1) { if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { - warnx("HBA at %s%d is not cable of changing " - "offset", cpi.dev_name, - cpi.unit_number); + warnx("HBA is not capable of changing offset"); retval = 1; goto ratecontrol_bailout; } @@ -3293,28 +3291,23 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, spi->sync_offset = offset; didsettings++; } - if (spi && syncrate != -1) { int prelim_sync_period; u_int freq; if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { - warnx("HBA at %s%d is not cable of changing " - "transfer rates", cpi.dev_name, - cpi.unit_number); + warnx("HBA is not capable of changing " + "transfer rates"); retval = 1; goto ratecontrol_bailout; } - spi->valid |= CTS_SPI_VALID_SYNC_RATE; - /* * The sync rate the user gives us is in MHz. * We need to translate it into KHz for this * calculation. */ syncrate *= 1000; - /* * Next, we calculate a "preliminary" sync period * in tenths of a nanosecond. @@ -3323,14 +3316,43 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, prelim_sync_period = 0; else prelim_sync_period = 10000000 / syncrate; - spi->sync_period = scsi_calc_syncparam(prelim_sync_period); - freq = scsi_calc_syncsrate(spi->sync_period); didsettings++; } - + if (sata && syncrate != -1) { + if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { + warnx("HBA is not capable of changing " + "transfer rates"); + retval = 1; + goto ratecontrol_bailout; + } + sata->revision = ata_speed2revision(syncrate * 100); + if (sata->revision < 0) { + warnx("Invalid rate %f", syncrate); + retval = 1; + goto ratecontrol_bailout; + } + sata->valid |= CTS_SATA_VALID_REVISION; + didsettings++; + } + if ((ata || sata) && mode != -1) { + if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { + warnx("HBA is not capable of changing " + "transfer rates"); + retval = 1; + goto ratecontrol_bailout; + } + if (ata) { + ata->mode = mode; + ata->valid |= CTS_ATA_VALID_MODE; + } else { + sata->mode = mode; + sata->valid |= CTS_SATA_VALID_MODE; + } + didsettings++; + } /* * The bus_width argument goes like this: * 0 == 8 bit @@ -3341,7 +3363,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, * number. */ if (spi && bus_width != -1) { - /* * We might as well validate things here with a * decipherable error message, rather than what @@ -3365,17 +3386,19 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - spi->valid |= CTS_SPI_VALID_BUS_WIDTH; spi->bus_width = bus_width >> 4; didsettings++; } - if (didsettings == 0) { goto ratecontrol_bailout; } + if (!user_settings && (ata || sata)) { + warnx("You can modify only user settings for ATA/SATA"); + retval = 1; + goto ratecontrol_bailout; + } ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; - if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_SET_TRAN_SETTINGS CCB"); if (arglist & CAM_ARG_VERBOSE) { @@ -3385,7 +3408,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("XPT_SET_TRANS_SETTINGS CCB failed"); if (arglist & CAM_ARG_VERBOSE) { @@ -3396,11 +3418,9 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, goto ratecontrol_bailout; } } - if (send_tur) { retval = testunitready(device, retry_count, timeout, (arglist & CAM_ARG_VERBOSE) ? 0 : 1); - /* * If the TUR didn't succeed, just bail. */ @@ -3409,7 +3429,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, fprintf(stderr, "Test Unit Ready failed\n"); goto ratecontrol_bailout; } - /* * If the user wants things quiet, there's no sense in * getting the transfer settings, if we're not going @@ -3417,13 +3436,11 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, */ if (quiet != 0) goto ratecontrol_bailout; - - fprintf(stdout, "New Parameters:\n"); + fprintf(stdout, "New parameters:\n"); retval = get_print_cts(device, user_settings, 0, NULL); } ratecontrol_bailout: - cam_freeccb(ccb); return(retval); } @@ -4310,8 +4327,8 @@ usage(int verbose) " \n" " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n" " camcontrol negotiate [dev_id][generic args] [-a][-c]\n" -" [-D ][-O offset][-q]\n" -" [-R syncrate][-v][-T ]\n" +" [-D ][-M mode][-O offset]\n" +" [-q][-R syncrate][-v][-T ]\n" " [-U][-W bus_width]\n" " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n" " camcontrol idle [dev_id][generic args][-t time]\n" @@ -4402,6 +4419,7 @@ usage(int verbose) "-a send a test unit ready after negotiation\n" "-c report/set current negotiation settings\n" "-D \"enable\" or \"disable\" disconnection\n" +"-M mode set ATA mode\n" "-O offset set command delay offset\n" "-q be quiet, don't report anything\n" "-R syncrate synchronization rate in MHz\n" diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index fb834bf9a48d..5c0c6d9670d7 100644 --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -532,6 +532,35 @@ ata_mode2string(int mode) } } +int +ata_string2mode(char *str) +{ + if (!strcasecmp(str, "PIO0")) return (ATA_PIO0); + if (!strcasecmp(str, "PIO1")) return (ATA_PIO1); + if (!strcasecmp(str, "PIO2")) return (ATA_PIO2); + if (!strcasecmp(str, "PIO3")) return (ATA_PIO3); + if (!strcasecmp(str, "PIO4")) return (ATA_PIO4); + if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0); + if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1); + if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2); + if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0); + if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0); + if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1); + if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1); + if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2); + if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2); + if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3); + if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3); + if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4); + if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4); + if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5); + if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5); + if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6); + if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6); + return (-1); +} + + u_int ata_mode2speed(int mode) { @@ -588,13 +617,16 @@ int ata_speed2revision(u_int speed) { switch (speed) { + case 0: + return (0); case 150000: - default: return (1); case 300000: return (2); case 600000: return (3); + default: + return (-1); } } diff --git a/sys/cam/ata/ata_all.h b/sys/cam/ata/ata_all.h index d286220345b7..e64e1a1d24c6 100644 --- a/sys/cam/ata/ata_all.h +++ b/sys/cam/ata/ata_all.h @@ -115,6 +115,7 @@ int ata_max_umode(struct ata_params *ap); int ata_max_mode(struct ata_params *ap, int maxmode); char * ata_mode2string(int mode); +int ata_string2mode(char *str); u_int ata_mode2speed(int mode); u_int ata_revision2speed(int revision); int ata_speed2revision(u_int speed); diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 5cae7d30dd0b..72de56467256 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -820,7 +820,7 @@ struct ccb_trans_settings_ata { u_int valid; /* Which fields to honor */ #define CTS_ATA_VALID_MODE 0x01 #define CTS_ATA_VALID_BYTECOUNT 0x02 - int mode; /* Mode */ + int mode; /* Mode */ u_int bytecount; /* Length of PIO transaction */ }; @@ -831,9 +831,9 @@ struct ccb_trans_settings_sata { #define CTS_SATA_VALID_REVISION 0x04 #define CTS_SATA_VALID_PM 0x08 #define CTS_SATA_VALID_TAGS 0x10 - int mode; /* Legacy PATA mode */ + int mode; /* Legacy PATA mode */ u_int bytecount; /* Length of PIO transaction */ - u_int revision; /* SATA revision */ + int revision; /* SATA revision */ u_int pm_present; /* PM is present (XPT->SIM) */ u_int tags; /* Number of allowed tags */ }; diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 0cb67f425dec..3f6c9fcdd886 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -72,7 +72,7 @@ static void ahci_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int er static void ahci_execute_transaction(struct ahci_slot *slot); static void ahci_timeout(struct ahci_slot *slot); static void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et); -static int ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag); +static int ahci_setup_fis(device_t dev, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag); static void ahci_dmainit(device_t dev); static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); static void ahci_dmafini(device_t dev); @@ -776,7 +776,7 @@ ahci_ch_attach(device_t dev) struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ahci_channel *ch = device_get_softc(dev); struct cam_devq *devq; - int rid, error, i; + int rid, error, i, sata_rev = 0; ch->dev = dev; ch->unit = (intptr_t)device_get_ivars(dev); @@ -789,22 +789,22 @@ ahci_ch_attach(device_t dev) device_get_unit(dev), "pm_level", &ch->pm_level); if (ch->pm_level > 3) callout_init_mtx(&ch->pm_timer, &ch->mtx, 0); - for (i = 0; i < 16; i++) { - ch->user[i].revision = 0; - ch->user[i].mode = 0; - ch->user[i].bytecount = 8192; - ch->user[i].tags = ch->numslots; - ch->curr[i] = ch->user[i]; - } /* Limit speed for my onboard JMicron external port. * It is not eSATA really. */ if (pci_get_devid(ctlr->dev) == 0x2363197b && pci_get_subvendor(ctlr->dev) == 0x1043 && pci_get_subdevice(ctlr->dev) == 0x81e4 && ch->unit == 0) - ch->sata_rev = 1; + sata_rev = 1; resource_int_value(device_get_name(dev), - device_get_unit(dev), "sata_rev", &ch->sata_rev); + device_get_unit(dev), "sata_rev", &sata_rev); + for (i = 0; i < 16; i++) { + ch->user[i].revision = sata_rev; + ch->user[i].mode = 0; + ch->user[i].bytecount = 8192; + ch->user[i].tags = ch->numslots; + ch->curr[i] = ch->user[i]; + } rid = ch->unit; if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE))) @@ -1410,7 +1410,7 @@ ahci_execute_transaction(struct ahci_slot *slot) ctp = (struct ahci_cmd_tab *) (ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot)); /* Setup the FIS for this request */ - if (!(fis_size = ahci_setup_fis(ctp, ccb, slot->slot))) { + if (!(fis_size = ahci_setup_fis(dev, ctp, ccb, slot->slot))) { device_printf(ch->dev, "Setting up SATA FIS failed\n"); ahci_end_transaction(slot, AHCI_ERR_INVALID); return; @@ -1983,8 +1983,9 @@ ahci_reset(device_t dev) } static int -ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag) +ahci_setup_fis(device_t dev, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag) { + struct ahci_channel *ch = device_get_softc(dev); u_int8_t *fis = &ctp->cfis[0]; bzero(ctp->cfis, 64); @@ -1993,7 +1994,8 @@ ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag) if (ccb->ccb_h.func_code == XPT_SCSI_IO) { fis[1] |= 0x80; fis[2] = ATA_PACKET_CMD; - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && + ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA) fis[3] = ATA_F_DMA; else { fis[5] = ccb->csio.dxfer_len; @@ -2073,6 +2075,7 @@ static int ahci_sata_phy_reset(device_t dev, int quick) { struct ahci_channel *ch = device_get_softc(dev); + int sata_rev; uint32_t val; if (quick) { @@ -2083,11 +2086,12 @@ ahci_sata_phy_reset(device_t dev, int quick) if (bootverbose) device_printf(dev, "hardware reset ...\n"); - if (ch->sata_rev == 1) + sata_rev = ch->user[ch->pm_present ? 15 : 0].revision; + if (sata_rev == 1) val = ATA_SC_SPD_SPEED_GEN1; - else if (ch->sata_rev == 2) + else if (sata_rev == 2) val = ATA_SC_SPD_SPEED_GEN2; - else if (ch->sata_rev == 3) + else if (sata_rev == 3) val = ATA_SC_SPD_SPEED_GEN3; else val = 0; diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h index e4ae23c1d1a2..e11f84f489d3 100644 --- a/sys/dev/ahci/ahci.h +++ b/sys/dev/ahci/ahci.h @@ -341,7 +341,7 @@ struct ahci_slot { }; struct ahci_device { - u_int revision; + int revision; int mode; u_int bytecount; u_int tags; @@ -362,7 +362,6 @@ struct ahci_channel { int quirks; int numslots; /* Number of present slots */ int pm_level; /* power management level */ - int sata_rev; /* Maximum allowed SATA generation */ struct ahci_slot slot[AHCI_MAX_SLOTS]; union ccb *hold[AHCI_MAX_SLOTS]; diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index 0ce8e01f0bbc..7ee6eb63d06c 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -69,7 +69,7 @@ static void siis_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int er static void siis_execute_transaction(struct siis_slot *slot); static void siis_timeout(struct siis_slot *slot); static void siis_end_transaction(struct siis_slot *slot, enum siis_err_type et); -static int siis_setup_fis(struct siis_cmd *ctp, union ccb *ccb, int tag); +static int siis_setup_fis(device_t dev, struct siis_cmd *ctp, union ccb *ccb, int tag); static void siis_dmainit(device_t dev); static void siis_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); static void siis_dmafini(device_t dev); @@ -415,21 +415,21 @@ siis_ch_attach(device_t dev) { struct siis_channel *ch = device_get_softc(dev); struct cam_devq *devq; - int rid, error, i; + int rid, error, i, sata_rev = 0; ch->dev = dev; ch->unit = (intptr_t)device_get_ivars(dev); resource_int_value(device_get_name(dev), device_get_unit(dev), "pm_level", &ch->pm_level); + resource_int_value(device_get_name(dev), + device_get_unit(dev), "sata_rev", &sata_rev); for (i = 0; i < 16; i++) { - ch->user[i].revision = 0; + ch->user[i].revision = sata_rev; ch->user[i].mode = 0; ch->user[i].bytecount = 8192; ch->user[i].tags = SIIS_MAX_SLOTS; ch->curr[i] = ch->user[i]; } - resource_int_value(device_get_name(dev), - device_get_unit(dev), "sata_rev", &ch->sata_rev); mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF); rid = ch->unit; if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, @@ -974,7 +974,7 @@ siis_execute_transaction(struct siis_slot *slot) ctp->control |= htole16(SIIS_PRB_PACKET_WRITE); } /* Setup the FIS for this request */ - if (!siis_setup_fis(ctp, ccb, slot->slot)) { + if (!siis_setup_fis(dev, ctp, ccb, slot->slot)) { device_printf(ch->dev, "Setting up SATA FIS failed\n"); if (!ch->readlog) xpt_freeze_simq(ch->sim, 1); @@ -1346,7 +1346,7 @@ static void siis_reset(device_t dev) { struct siis_channel *ch = device_get_softc(dev); - int i, retry = 0; + int i, retry = 0, sata_rev; uint32_t val; if (bootverbose) @@ -1390,11 +1390,12 @@ siis_reset(device_t dev) /* Disable port interrupts */ ATA_OUTL(ch->r_mem, SIIS_P_IECLR, 0x0000FFFF); /* Set speed limit. */ - if (ch->sata_rev == 1) + sata_rev = ch->user[ch->pm_present ? 15 : 0].revision; + if (sata_rev == 1) val = ATA_SC_SPD_SPEED_GEN1; - else if (ch->sata_rev == 2) + else if (sata_rev == 2) val = ATA_SC_SPD_SPEED_GEN2; - else if (ch->sata_rev == 3) + else if (sata_rev == 3) val = ATA_SC_SPD_SPEED_GEN3; else val = 0; @@ -1446,8 +1447,9 @@ retry: } static int -siis_setup_fis(struct siis_cmd *ctp, union ccb *ccb, int tag) +siis_setup_fis(device_t dev, struct siis_cmd *ctp, union ccb *ccb, int tag) { + struct siis_channel *ch = device_get_softc(dev); u_int8_t *fis = &ctp->fis[0]; bzero(fis, 24); @@ -1456,7 +1458,8 @@ siis_setup_fis(struct siis_cmd *ctp, union ccb *ccb, int tag) if (ccb->ccb_h.func_code == XPT_SCSI_IO) { fis[1] |= 0x80; fis[2] = ATA_PACKET_CMD; - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && + ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA) fis[3] = ATA_F_DMA; else { fis[5] = ccb->csio.dxfer_len; diff --git a/sys/dev/siis/siis.h b/sys/dev/siis/siis.h index 6bb28d95dd18..52332c5ad683 100644 --- a/sys/dev/siis/siis.h +++ b/sys/dev/siis/siis.h @@ -347,7 +347,7 @@ struct siis_slot { }; struct siis_device { - u_int revision; + int revision; int mode; u_int bytecount; u_int tags; @@ -364,7 +364,6 @@ struct siis_channel { struct cam_sim *sim; struct cam_path *path; int pm_level; /* power management level */ - int sata_rev; /* Maximum allowed SATA generation */ struct siis_slot slot[SIIS_MAX_SLOTS]; union ccb *hold[SIIS_MAX_SLOTS];