summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2009-11-26 08:49:46 +0000
committermav <mav@FreeBSD.org>2009-11-26 08:49:46 +0000
commit7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f (patch)
tree580d695f05aa2ddcdc2101f3114e9dd4e0dd13d7 /sys
parent2d9252d6c71a08629a451a1966338c6e119912d1 (diff)
downloadFreeBSD-src-7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f.zip
FreeBSD-src-7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f.tar.gz
MFp4:
Improve ATA mode/SATA revision control.
Diffstat (limited to 'sys')
-rw-r--r--sys/cam/ata/ata_all.c34
-rw-r--r--sys/cam/ata/ata_all.h1
-rw-r--r--sys/cam/cam_ccb.h6
-rw-r--r--sys/dev/ahci/ahci.c38
-rw-r--r--sys/dev/ahci/ahci.h3
-rw-r--r--sys/dev/siis/siis.c27
-rw-r--r--sys/dev/siis/siis.h3
7 files changed, 75 insertions, 37 deletions
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index fb834bf..5c0c6d9 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 d286220..e64e1a1 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 5cae7d3..72de564 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 0cb67f4..3f6c9fc 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 e4ae23c..e11f84f 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 0ce8e01..7ee6eb6 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 6bb28d9..52332c5 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];
OpenPOWER on IntegriCloud