summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-chipset.c151
-rw-r--r--sys/dev/ata/ata-pci.h19
2 files changed, 161 insertions, 9 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index dd71819..edcc905 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -79,12 +79,17 @@ static int ata_via_chipinit(device_t);
static void ata_via_family_setmode(struct ata_device *, int);
static void ata_via_southbridge_fixup(device_t);
static int ata_promise_chipinit(device_t);
+static int ata_promise_mio_allocate(device_t, struct ata_channel *);
static void ata_promise_old_intr(void *);
static void ata_promise_tx2_intr(void *);
+static void ata_promise_mio_intr(void *);
static void ata_promise_setmode(struct ata_device *, int);
static int ata_promise_old_dmainit(struct ata_channel *);
static int ata_promise_old_dmastart(struct ata_channel *, caddr_t, int32_t,int);
static int ata_promise_old_dmastop(struct ata_channel *);
+static int ata_promise_mio_dmainit(struct ata_channel *);
+static int ata_promise_mio_dmastart(struct ata_channel *, caddr_t, int32_t,int);
+static int ata_promise_mio_dmastop(struct ata_channel *);
static int ata_serverworks_chipinit(device_t);
static void ata_serverworks_setmode(struct ata_device *, int);
static int ata_sii_chipinit(device_t);
@@ -939,6 +944,18 @@ ata_promise_ident(device_t dev)
{ ATA_PDC20275, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20275" },
{ ATA_PDC20276, 0, PRTX, PRSX6K, ATA_UDMA6, "Promise PDC20276" },
{ ATA_PDC20277, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20277" },
+ { ATA_PDC20318, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20318" },
+ { ATA_PDC20319, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20319" },
+ { ATA_PDC20371, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20371" },
+ { ATA_PDC20375, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20375" },
+ { ATA_PDC20376, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20376" },
+ { ATA_PDC20377, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20377" },
+ { ATA_PDC20378, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20378" },
+ { ATA_PDC20379, 0, PRMIO, PRSATA, ATA_UDMA6, "Promise PDC20379" },
+ { ATA_PDC20617, 0, PRMIO, PRDUAL, ATA_UDMA6, "Promise PDC20617" },
+ { ATA_PDC20618, 0, PRMIO, PRDUAL, ATA_UDMA6, "Promise PDC20618" },
+ { ATA_PDC20619, 0, PRMIO, PRDUAL, ATA_UDMA6, "Promise PDC20619" },
+ { ATA_PDC20620, 0, PRMIO, PRDUAL, ATA_UDMA6, "Promise PDC20620" },
{ 0, 0, 0, 0, 0, 0}};
char *desc, buffer[64];
uintptr_t devid = 0;
@@ -1015,11 +1032,67 @@ ata_promise_chipinit(device_t dev)
return ENXIO;
}
break;
+
+ case PRMIO:
+ rid = 0x1c;
+ if (!(ctlr->r_io2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ 0, ~0, 1, RF_ACTIVE)))
+ return ENXIO;
+
+ ctlr->dmainit = ata_promise_mio_dmainit;
+ ctlr->allocate = ata_promise_mio_allocate;
+
+ if (ctlr->chip->cfg2 & PRDUAL) {
+ ctlr->channels = ((ATA_INL(ctlr->r_io2, 0x48) & 0x01) > 0) +
+ ((ATA_INL(ctlr->r_io2, 0x48) & 0x02) > 0) + 2;
+ }
+ else if (ctlr->chip->cfg2 & PRSATA) {
+ ATA_OUTL(ctlr->r_io2, 0x06c, 0x00ff0033);
+ ctlr->channels = ((ATA_INL(ctlr->r_io2, 0x48) & 0x02) > 0) + 3;
+ }
+ else
+ ctlr->channels = 4;
+
+ if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
+ ata_promise_mio_intr, ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ return ENXIO;
+ }
+ break;
}
ctlr->setmode = ata_promise_setmode;
return 0;
}
+static int
+ata_promise_mio_allocate(device_t dev, struct ata_channel *ch)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ int i;
+
+ for (i = ATA_DATA; i <= ATA_STATUS; i++) {
+ ch->r_io[i].res = ctlr->r_io2;
+ ch->r_io[i].offset = 0x200 + (i << 2) + (ch->unit << 7);
+ }
+ ch->r_io[ATA_ALTSTAT].res = ctlr->r_io2;
+ ch->r_io[ATA_ALTSTAT].offset = 0x238 + (ch->unit << 7);
+ ch->r_io[ATA_BMCTL_PORT].res = ctlr->r_io2;
+ ch->r_io[ATA_BMCTL_PORT].offset = 0x260 + (ch->unit << 7);
+ ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_io2;
+ ch->r_io[ATA_BMDTP_PORT].offset = 0x244 + (ch->unit << 7);
+ ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_io2;
+ ch->r_io[ATA_BMDEVSPEC_0].offset = (ch->unit << 2);
+ ch->r_io[ATA_IDX_ADDR].res = ctlr->r_io2;
+
+ ATA_IDX_OUTL(ch, ATA_BMCMD_PORT,
+ (ATA_IDX_INL(ch, ATA_BMCMD_PORT) & ~0x00000f8f) | ch->unit);
+ ATA_IDX_OUTL(ch, ATA_BMDEVSPEC_0, 0x00000001);
+
+ ch->flags |= ATA_NO_SLAVE;
+ ctlr->dmainit(ch);
+ return 0;
+}
+
static void
ata_promise_old_intr(void *data)
{
@@ -1072,6 +1145,24 @@ ata_promise_tx2_intr(void *data)
}
static void
+ata_promise_mio_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch;
+ u_int32_t irq_vector;
+ int unit;
+
+ irq_vector = ATA_INL(ctlr->r_io2, 0x0040);
+ for (unit = 0; unit < ctlr->channels; unit++) {
+ if (irq_vector & (1 << unit)) {
+ if ((ch = ctlr->interrupt[unit].argument))
+ ctlr->interrupt[unit].function(ch);
+ ATA_IDX_OUTL(ch, ATA_BMDEVSPEC_0, 0x00000001);
+ }
+ }
+}
+
+static void
ata_promise_setmode(struct ata_device *atadev, int mode)
{
device_t parent = device_get_parent(atadev->channel->dev);
@@ -1098,8 +1189,19 @@ ata_promise_setmode(struct ata_device *atadev, int mode)
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
- /* is this a TX2 or later chip ? */
switch (ctlr->chip->cfg1) {
+ case PROLD:
+ case PRNEW:
+ if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) &
+ (atadev->channel->unit ? 1 << 11 : 1 << 10))) {
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ if (ATAPI_DEVICE(atadev) && mode > ATA_PIO_MAX)
+ mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
+ break;
+
case PRTX:
ATA_IDX_OUTB(atadev->channel, ATA_BMDEVSPEC_0, 0x0b);
if (mode > ATA_UDMA2 &&
@@ -1110,16 +1212,14 @@ ata_promise_setmode(struct ata_device *atadev, int mode)
}
break;
- case PROLD:
- case PRNEW:
- if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) &
- (atadev->channel->unit ? 1 << 11 : 1 << 10))) {
+ case PRMIO:
+ if (mode > ATA_UDMA2 &&
+ (ATA_IDX_INL(atadev->channel, ATA_BMCTL_PORT) & 0x01000000)) {
ata_prtdev(atadev,
"DMA limited to UDMA33, non-ATA66 cable or device\n");
mode = ATA_UDMA2;
}
- if (ATAPI_DEVICE(atadev) && mode > ATA_PIO_MAX)
- mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
+ break;
}
error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
@@ -1196,6 +1296,43 @@ ata_promise_old_dmastop(struct ata_channel *ch)
return error;
}
+static int
+ata_promise_mio_dmainit(struct ata_channel *ch)
+{
+ int error;
+
+ if ((error = ata_dmainit(ch)))
+ return error;
+
+ ch->dma->start = ata_promise_mio_dmastart;
+ ch->dma->stop = ata_promise_mio_dmastop;
+ return 0;
+}
+
+static int
+ata_promise_mio_dmastart(struct ata_channel *ch,
+ caddr_t data, int32_t count, int dir)
+{
+ int error;
+
+ if ((error = ata_dmastart(ch, data, count, dir)))
+ return error;
+
+ ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab);
+ ATA_IDX_OUTL(ch, ATA_BMCTL_PORT,
+ (ATA_IDX_INL(ch, ATA_BMCTL_PORT) & ~0x000000c0) |
+ ((dir) ? 0x00000080 : 0x000000c0));
+ return error;
+}
+
+static int
+ata_promise_mio_dmastop(struct ata_channel *ch)
+{
+ ATA_IDX_OUTL(ch, ATA_BMCTL_PORT,
+ ATA_IDX_INL(ch, ATA_BMCTL_PORT) & ~0x00000080);
+ return ata_dmastop(ch);
+}
+
/*
* ServerWorks chipset support functions
*/
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 0e8b49b..ebaa280 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -129,7 +129,18 @@ struct ata_pci_controller {
#define ATA_PDC20275 0x1275105a
#define ATA_PDC20276 0x5275105a
#define ATA_PDC20277 0x7275105a
+#define ATA_PDC20318 0x3318105a
+#define ATA_PDC20319 0x3319105a
+#define ATA_PDC20371 0x3371105a
+#define ATA_PDC20375 0x3375105a
#define ATA_PDC20376 0x3376105a
+#define ATA_PDC20377 0x3377105a
+#define ATA_PDC20378 0x3373105a
+#define ATA_PDC20379 0x3372105a
+#define ATA_PDC20617 0x6617105a
+#define ATA_PDC20618 0x6626105a
+#define ATA_PDC20619 0x6629105a
+#define ATA_PDC20620 0x6620105a
#define ATA_PDC20621 0x6621105a
#define ATA_SERVERWORKS_ID 0x1166
@@ -216,9 +227,13 @@ struct ata_pci_controller {
#define PROLD 0
#define PRNEW 1
#define PRTX 2
-#define PRMEM 3
+#define PRMIO 3
+#define PRIDX 4
#define PRTX4 0x01
-#define PRSX6K 0x02
+#define PRSX4K 0x02
+#define PRSX6K 0x04
+#define PRSATA 0x08
+#define PRDUAL 0x10
#define SWKS33 0
#define SWKS66 1
OpenPOWER on IntegriCloud