summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/pciide.c123
-rw-r--r--sys/dev/pci/pciide_cmd_reg.h62
2 files changed, 128 insertions, 57 deletions
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index f5044b67ede..bfdebbef635 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.24 2000/06/13 03:56:41 chris Exp $ */
+/* $OpenBSD: pciide.c,v 1.25 2000/06/26 17:51:16 chris Exp $ */
/* $NetBSD: pciide.c,v 1.48 1999/11/28 20:05:18 bouyer Exp $ */
/*
@@ -210,8 +210,8 @@ void apollo_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
void apollo_setup_channel __P((struct channel_softc*));
void cmd_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
-void cmd0643_6_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
-void cmd0643_6_setup_channel __P((struct channel_softc*));
+void cmd0643_9_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
+void cmd0643_9_setup_channel __P((struct channel_softc*));
void cmd_channel_map __P((struct pci_attach_args *,
struct pciide_softc *, int));
int cmd_pci_intr __P((void *));
@@ -314,11 +314,19 @@ const struct pciide_product_desc pciide_cmd_products[] = {
},
{ PCI_PRODUCT_CMDTECH_643, /* CMD Technology PCI0643 */
0,
- cmd0643_6_chip_map
+ cmd0643_9_chip_map
},
{ PCI_PRODUCT_CMDTECH_646, /* CMD Technology PCI0646 */
0,
- cmd0643_6_chip_map
+ cmd0643_9_chip_map
+ },
+ { PCI_PRODUCT_CMDTECH_648, /* CMD Technology PCI0648 */
+ IDE_PCI_CLASS_OVERRIDE,
+ cmd0643_9_chip_map
+ },
+ { PCI_PRODUCT_CMDTECH_649, /* CMD Technology PCI0649 */
+ IDE_PCI_CLASS_OVERRIDE,
+ cmd0643_9_chip_map
}
};
@@ -2024,8 +2032,22 @@ cmd_channel_map(pa, sc, channel)
struct pciide_channel *cp = &sc->pciide_channels[channel];
bus_size_t cmdsize, ctlsize;
u_int8_t ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CTRL);
- pcireg_t interface =
- PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG));
+ int interface;
+
+ /*
+ * The 0648/0649 can be told to identify as a RAID controller.
+ * In this case, we have to fake interface
+ */
+ if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_IDE) {
+ interface = PCIIDE_INTERFACE_SETTABLE(0) |
+ PCIIDE_INTERFACE_SETTABLE(1);
+ if (pciide_pci_read(pa->pa_pc, pa->pa_tag, CMD_CONF) &
+ CMD_CONF_DSA1)
+ interface |= PCIIDE_INTERFACE_PCI(0) |
+ PCIIDE_INTERFACE_PCI(1);
+ } else {
+ interface = PCI_INTERFACE(pa->pa_class);
+ }
sc->wdc_chanarray[channel] = &cp->wdc_channel;
cp->name = PCIIDE_CHANNEL_NAME(channel);
@@ -2142,14 +2164,13 @@ cmd_chip_map(sc, pa)
}
void
-cmd0643_6_chip_map(sc, pa)
+cmd0643_9_chip_map(sc, pa)
struct pciide_softc *sc;
struct pci_attach_args *pa;
{
struct pciide_channel *cp;
int channel;
- pcireg_t interface =
- PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG));
+ pcireg_t interface = PCI_INTERFACE(pa->pa_class);
/*
* For a CMD PCI064x, the use of PCI_COMMAND_IO_ENABLE
@@ -2167,20 +2188,27 @@ cmd0643_6_chip_map(sc, pa)
#endif
printf(": DMA");
pciide_mapreg_dma(sc, pa);
- if (sc->sc_dma_ok)
+ sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
+ WDC_CAPABILITY_MODE;
+ if (sc->sc_dma_ok) {
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
+ switch (sc->sc_pp->ide_product) {
+ case PCI_PRODUCT_CMDTECH_649:
+ case PCI_PRODUCT_CMDTECH_648:
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
+ sc->sc_wdcdev.UDMA_cap = 4;
+ }
+ }
sc->sc_wdcdev.channels = sc->wdc_chanarray;
sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
- sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
- WDC_CAPABILITY_MODE;
sc->sc_wdcdev.PIO_cap = 4;
sc->sc_wdcdev.DMA_cap = 2;
- sc->sc_wdcdev.set_modes = cmd0643_6_setup_channel;
+ sc->sc_wdcdev.set_modes = cmd0643_9_setup_channel;
pciide_print_channels(sc->sc_wdcdev.nchannels, interface);
- WDCDEBUG_PRINT(("cmd0643_6_chip_map: old timings reg 0x%x 0x%x\n",
+ WDCDEBUG_PRINT(("cmd0643_9_chip_map: old timings reg 0x%x 0x%x\n",
pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54),
pci_conf_read(sc->sc_pc, sc->sc_tag, 0x58)),
DEBUG_PROBE);
@@ -2189,22 +2217,22 @@ cmd0643_6_chip_map(sc, pa)
cmd_channel_map(pa, sc, channel);
if (cp->hw_ok == 0)
continue;
- cmd0643_6_setup_channel(&cp->wdc_channel);
+ cmd0643_9_setup_channel(&cp->wdc_channel);
}
pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_DMA_MODE, CMD_DMA_MULTIPLE);
- WDCDEBUG_PRINT(("cmd0643_6_chip_map: timings reg now 0x%x 0x%x\n",
+ WDCDEBUG_PRINT(("cmd0643_9_chip_map: timings reg now 0x%x 0x%x\n",
pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54),
pci_conf_read(sc->sc_pc, sc->sc_tag, 0x58)),
DEBUG_PROBE);
}
void
-cmd0643_6_setup_channel(chp)
+cmd0643_9_setup_channel(chp)
struct channel_softc *chp;
{
struct ata_drive_datas *drvp;
u_int8_t tim;
- u_int32_t idedma_ctl;
+ u_int32_t idedma_ctl, udma_reg;
int drive;
struct pciide_channel *cp = (struct pciide_channel*)chp;
struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
@@ -2219,18 +2247,51 @@ cmd0643_6_setup_channel(chp)
if ((drvp->drive_flags & DRIVE) == 0)
continue;
/* add timing values, setup DMA if needed */
- tim = cmd0643_6_data_tim_pio[drvp->PIO_mode];
- if (drvp->drive_flags & DRIVE_DMA) {
- /*
- * use Multiword DMA.
- * Timings will be used for both PIO and DMA, so adjust
- * DMA mode if needed
- */
- if (drvp->PIO_mode >= 3 &&
- (drvp->DMA_mode + 2) > drvp->PIO_mode) {
- drvp->DMA_mode = drvp->PIO_mode - 2;
+ tim = cmd0643_9_data_tim_pio[drvp->PIO_mode];
+ if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
+ if (drvp->drive_flags & DRIVE_UDMA) {
+ /* UltraDMA on a 0648 or 0649 */
+ udma_reg = pciide_pci_read(sc->sc_pc,
+ sc->sc_tag, CMD_UDMATIM(chp->channel));
+ if (drvp->UDMA_mode > 2 &&
+ (pciide_pci_read(sc->sc_pc, sc->sc_tag,
+ CMD_BICSR) &
+ CMD_BICSR_80(chp->channel)) == 0)
+ drvp->UDMA_mode = 2;
+ if (drvp->UDMA_mode > 2)
+ udma_reg &= ~CMD_UDMATIM_UDMA33(drive);
+ else
+ udma_reg |= CMD_UDMATIM_UDMA33(drive);
+ udma_reg |= CMD_UDMATIM_UDMA(drive);
+ udma_reg &= ~(CMD_UDMATIM_TIM_MASK <<
+ CMD_UDMATIM_TIM_OFF(drive));
+ udma_reg |=
+ (cmd0648_9_tim_udma[drvp->UDMA_mode] <<
+ CMD_UDMATIM_TIM_OFF(drive));
+ pciide_pci_write(sc->sc_pc, sc->sc_tag,
+ CMD_UDMATIM(chp->channel), udma_reg);
+ } else {
+ /*
+ * use Multiword DMA.
+ * Timings will be used for both PIO and DMA,
+ * so adjust DMA mode if needed
+ * if we have a 0648/9, turn off UDMA
+ */
+ if (sc->sc_wdcdev.cap & WDC_CAPABILITY_UDMA) {
+ udma_reg = pciide_pci_read(sc->sc_pc,
+ sc->sc_tag,
+ CMD_UDMATIM(chp->channel));
+ udma_reg &= ~CMD_UDMATIM_UDMA(drive);
+ pciide_pci_write(sc->sc_pc, sc->sc_tag,
+ CMD_UDMATIM(chp->channel),
+ udma_reg);
+ }
+ if (drvp->PIO_mode >= 3 &&
+ (drvp->DMA_mode + 2) > drvp->PIO_mode) {
+ drvp->DMA_mode = drvp->PIO_mode - 2;
+ }
+ tim = cmd0643_9_data_tim_dma[drvp->DMA_mode];
}
- tim = cmd0643_6_data_tim_dma[drvp->DMA_mode];
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
}
pciide_pci_write(sc->sc_pc, sc->sc_tag,
@@ -3079,7 +3140,7 @@ pdc202xx_setup_channel(chp)
PDC262_U66);
st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE);
/* Trim UDMA mode */
- if ((st & PDC262_STATE_80P(channel)) == 0 ||
+ if ((st & PDC262_STATE_80P(channel)) != 0 ||
(chp->ch_drive[0].drive_flags & DRIVE_UDMA &&
chp->ch_drive[0].UDMA_mode <= 2) ||
(chp->ch_drive[1].drive_flags & DRIVE_UDMA &&
diff --git a/sys/dev/pci/pciide_cmd_reg.h b/sys/dev/pci/pciide_cmd_reg.h
index e792e9f277f..62410cbeba3 100644
--- a/sys/dev/pci/pciide_cmd_reg.h
+++ b/sys/dev/pci/pciide_cmd_reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pciide_cmd_reg.h,v 1.2 1999/10/04 22:54:18 deraadt Exp $ */
-/* $NetBSD: pciide_cmd_reg.h,v 1.4 1998/12/02 10:52:25 bouyer Exp $ */
+/* $OpenBSD: pciide_cmd_reg.h,v 1.3 2000/06/26 17:51:17 chris Exp $ */
+/* $NetBSD: pciide_cmd_reg.h,v 1.7 2000/06/26 10:07:52 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -20,17 +20,16 @@
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
@@ -41,21 +40,21 @@
/* Configuration (RO) */
#define CMD_CONF 0x50
-#define CMD_CONF_REV_MASK 0x03
+#define CMD_CONF_REV_MASK 0x03 /* 0640/3/6 only */
#define CMD_CONF_DRV0_INTR 0x04
-#define CMD_CONF_DEVID 0x18
-#define CMD_CONF_VESAPRT 0x20
+#define CMD_CONF_DEVID 0x18 /* 0640/3/6 only */
+#define CMD_CONF_VESAPRT 0x20 /* 0640/3/6 only */
#define CMD_CONF_DSA1 0x40
-#define CMD_CONF_DSA0 0x80
+#define CMD_CONF_DSA0 0x80 /* 0640/3/6 only */
/* Control register (RW) */
#define CMD_CTRL 0x51
-#define CMD_CTRL_HR_FIFO 0x01
-#define CMD_CTRL_HW_FIFO 0x02
+#define CMD_CTRL_HR_FIFO 0x01 /* 0640/3/6 only */
+#define CMD_CTRL_HW_FIFO 0x02 /* 0640/3/6 only */
#define CMD_CTRL_DEVSEL 0x04
#define CMD_CTRL_2PORT 0x08
-#define CMD_CTRL_PAR 0x10
-#define CMD_CTRL_HW_HLD 0x20
+#define CMD_CTRL_PAR 0x10 /* 0640/3/6 only */
+#define CMD_CTRL_HW_HLD 0x20 /* 0640/3/6 only */
#define CMD_CTRL_DRV0_RAHEAD 0x40
#define CMD_CTRL_DRV1_RAHEAD 0x80
@@ -70,7 +69,7 @@
((drive) == 0) ? 0x58 : 0x5b)
/* secondary channel status and addr timings */
-#define CMD_ARTTIM23 0x57
+#define CMD_ARTTIM23 0x57
#define CMD_ARTTIM23_IRQ 0x10
#define CMD_ARTTIM23_RHAEAD(d) ((0x4) << (d))
@@ -79,12 +78,23 @@
#define CMD_DMA 0x00
#define CMD_DMA_MULTIPLE 0x01
#define CMD_DMA_LINE 0x10
-
+
+/* the followings are only for 0648/9 */
+/* busmaster control/status register */
+#define CMD_BICSR 0x79
+#define CMD_BICSR_80(chan) (0x01 << (chan))
+/* Ultra/DMA timings reg */
+#define CMD_UDMATIM(channel) (0x73 + (8 * (channel)))
+#define CMD_UDMATIM_UDMA(drive) (0x01 << (drive))
+#define CMD_UDMATIM_UDMA33(drive) (0x04 << (drive))
+#define CMD_UDMATIM_TIM_MASK 0x3
+#define CMD_UDMATIM_TIM_OFF(drive) (4 + ((drive) * 2))
+static int8_t cmd0648_9_tim_udma[] = {0x03, 0x02, 0x01, 0x02, 0x01};
/*
- * timings values for the 0643 and 0x646
+ * timings values for the 0643/6/8/9
* for all dma_mode we have to have
* DMA_timings(dma_mode) >= PIO_timings(dma_mode + 2)
*/
-static int8_t cmd0643_6_data_tim_pio[] = {0xA9, 0x57, 0x44, 0x32, 0x3F};
-static int8_t cmd0643_6_data_tim_dma[] = {0x87, 0x32, 0x3F};
+static int8_t cmd0643_9_data_tim_pio[] = {0xA9, 0x57, 0x44, 0x32, 0x3F};
+static int8_t cmd0643_9_data_tim_dma[] = {0x87, 0x32, 0x3F};