summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryt160523 <none@none>2008-04-10 21:52:34 -0700
committeryt160523 <none@none>2008-04-10 21:52:34 -0700
commitc8531848467a8747b65b91ab83c4b57f4c000848 (patch)
treec95c6bfde4cb2c8086841865f40f2bbb9e4181b4
parentfb91fd8a302dfb13e250bbefb6a3970c2edc3ae3 (diff)
downloadillumos-gate-c8531848467a8747b65b91ab83c4b57f4c000848.tar.gz
6681215 DVD is not being recognized in IDE mode on a Intel Prototype SDV
-rw-r--r--usr/src/uts/intel/io/dktp/controller/ata/ata_common.c54
-rw-r--r--usr/src/uts/intel/io/dktp/controller/ata/ata_common.h10
-rw-r--r--usr/src/uts/intel/io/dktp/controller/ata/atapi.c27
3 files changed, 86 insertions, 5 deletions
diff --git a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c
index 20f4dac44d..e7d6387357 100644
--- a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c
+++ b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -3755,3 +3755,55 @@ ata_disable_DMA(ata_drv_t *ata_drvp)
buf, ata_drvp->ad_targ, ata_drvp->ad_lun);
cmn_err(CE_CONT, "?most likely due to the CF-to-IDE adapter.");
}
+
+/*
+ * Check and select DMA mode
+ *
+ * TRUE is returned when set feature is called successfully,
+ * otherwise return FALSE
+ */
+int
+ata_set_dma_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp)
+{
+ struct ata_id *aidp;
+ int mode, rval = FALSE;
+ uint8_t subcmd;
+
+ aidp = &ata_drvp->ad_id;
+
+ /* Return directly if DMA is not supported */
+ if (!(aidp->ai_cap & ATAC_DMA_SUPPORT))
+ return (rval);
+
+ /* Return if DMA mode is already selected */
+ if (((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
+ (aidp->ai_ultradma & ATAC_UDMA_SEL_MASK)) ||
+ (aidp->ai_dworddma & ATAC_MDMA_SEL_MASK))
+ return (rval);
+
+ /* First check Ultra DMA mode if no DMA is selected */
+ if ((aidp->ai_validinfo & ATAC_VALIDINFO_83) &&
+ (aidp->ai_ultradma & ATAC_UDMA_SUP_MASK)) {
+ for (mode = 6; mode >= 0; --mode) {
+ if (aidp->ai_ultradma & (1 << mode))
+ break;
+ }
+ subcmd = ATF_XFRMOD_UDMA;
+
+ } else if (aidp->ai_dworddma & ATAC_MDMA_SUP_MASK) {
+ /* Then check multi-word DMA mode */
+ for (mode = 2; mode >= 0; --mode) {
+ if (aidp->ai_dworddma & (1 << mode))
+ break;
+ }
+ subcmd = ATF_XFRMOD_MDMA;
+
+ } else {
+ return (rval);
+ }
+
+ rval = ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD,
+ subcmd|mode);
+
+ return (rval);
+}
diff --git a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h
index 1eac4c44e1..6ed2c16498 100644
--- a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h
+++ b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -177,6 +177,7 @@ extern "C" {
* Feature register bits
*/
#define ATF_ATAPI_DMA 0x01 /* ATAPI DMA enable bit */
+#define ATF_XFRMOD_MDMA 0x20 /* Multi-Word DMA mode */
#define ATF_XFRMOD_UDMA 0x40 /* Ultra DMA mode */
#define ATACM_UDMA_SEL(id) (((id)->ai_ultradma >> 8) & 0x7f)
@@ -415,6 +416,7 @@ struct ata_id {
/* Identify Drive: ai_dworddma (word 63) */
+#define ATAC_MDMA_SUP_MASK 0x0007 /* Multiword DMA supported */
#define ATAC_MDMA_SEL_MASK 0x0700 /* Multiword DMA selected */
#define ATAC_MDMA_2_SEL 0x0400 /* Multiword DMA mode 2 selected */
#define ATAC_MDMA_1_SEL 0x0200 /* Multiword DMA mode 1 selected */
@@ -442,6 +444,11 @@ struct ata_id {
/* Identify Drive: ai_features85 (word 85) */
#define ATAC_FEATURES85_WCE 0x0020 /* write cache enabled */
+/* Identify Drive: ai_ultradma (word 88) */
+#define ATAC_UDMA_SUP_MASK 0x007f /* UDMA modes supported */
+#define ATAC_UDMA_SEL_MASK 0x7f00 /* UDMA modes selected */
+
+
/* per-drive data struct */
typedef struct ata_drv {
@@ -667,6 +674,7 @@ int ata_wait3(ddi_acc_handle_t io_hdl, caddr_t ioaddr, uchar_t onbits1,
uchar_t failure_offbits3, uint_t timeout_usec);
int ata_test_lba_support(struct ata_id *aidp);
void ata_nsecwait(clock_t count);
+int ata_set_dma_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp);
/*
diff --git a/usr/src/uts/intel/io/dktp/controller/ata/atapi.c b/usr/src/uts/intel/io/dktp/controller/ata/atapi.c
index d714e53d98..c06e3aac75 100644
--- a/usr/src/uts/intel/io/dktp/controller/ata/atapi.c
+++ b/usr/src/uts/intel/io/dktp/controller/ata/atapi.c
@@ -183,6 +183,8 @@ int
atapi_init_drive(
ata_drv_t *ata_drvp)
{
+ ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp;
+
ADBG_TRACE(("atapi_init_drive entered\n"));
/* Determine ATAPI CDB size */
@@ -206,6 +208,16 @@ atapi_init_drive(
ATAPI_ID_CFG_DRQ_INTR)
ata_drvp->ad_flags |= AD_NO_CDB_INTR;
+ /*
+ * Some devices may have no DMA mode enabled (UDMA or MWDMA)
+ * by default, so here we need check and enable DMA if none
+ * mode is selected.
+ */
+ if (ata_set_dma_mode(ata_ctlp, ata_drvp) == TRUE) {
+ /* Update the IDENTIFY PACKET DEVICE data */
+ (void) atapi_id_update(ata_ctlp, ata_drvp, NULL);
+ }
+
return (TRUE);
}
@@ -1119,6 +1131,7 @@ atapi_id_update(
caddr_t ioaddr1 = ata_ctlp->ac_ioaddr1;
ddi_acc_handle_t io_hdl2 = ata_ctlp->ac_iohandle2;
caddr_t ioaddr2 = ata_ctlp->ac_ioaddr2;
+ struct ata_id *aidp;
int rc;
/*
@@ -1133,13 +1146,21 @@ atapi_id_update(
*/
if (!ata_wait(io_hdl2, ioaddr2, ATS_DRDY, ATS_BSY, 5 * 1000000)) {
ADBG_ERROR(("atapi_id_update: select failed\n"));
- ata_pktp->ap_flags |= AP_ERROR;
+ if (ata_pktp != NULL)
+ ata_pktp->ap_flags |= AP_ERROR;
return (ATA_FSM_RC_FINI);
}
+ if (ata_pktp != NULL)
+ aidp = (struct ata_id *)ata_pktp->ap_v_addr;
+ else
+ aidp = &ata_drvp->ad_id;
+
rc = atapi_id(ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1,
- ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2,
- (struct ata_id *)ata_pktp->ap_v_addr);
+ ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2, aidp);
+
+ if (ata_pktp == NULL)
+ return (ATA_FSM_RC_FINI);
if (!rc) {
ata_pktp->ap_flags |= AP_ERROR;