Update the SATA support code to work more correctly with

real SATA disks now that I can test it.

Add support for the SiI 3112 SATA chip using memory mapped I/O.
Update the support for the SiI 0680 to use the memio interface as well.

Sponsored by:	David Leimbach <leimy2k@mac.com> (3112 based controller)
Sponsored by:	FreeBSD Systems (www.FreeBSDsystems.com) (SATA disks)
This commit is contained in:
Søren Schmidt 2003-07-02 10:50:44 +00:00
parent fedbfbbbc6
commit e158f2b820
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=117155
3 changed files with 122 additions and 58 deletions

View File

@ -93,6 +93,8 @@ static int ata_promise_mio_dmastop(struct ata_channel *);
static int ata_serverworks_chipinit(device_t); static int ata_serverworks_chipinit(device_t);
static void ata_serverworks_setmode(struct ata_device *, int); static void ata_serverworks_setmode(struct ata_device *, int);
static int ata_sii_chipinit(device_t); static int ata_sii_chipinit(device_t);
static int ata_sii_mio_allocate(device_t, struct ata_channel *);
static void ata_sii_intr(void *);
static void ata_cmd_intr(void *); static void ata_cmd_intr(void *);
static void ata_sii_setmode(struct ata_device *, int); static void ata_sii_setmode(struct ata_device *, int);
static void ata_cmd_setmode(struct ata_device *, int); static void ata_cmd_setmode(struct ata_device *, int);
@ -838,11 +840,6 @@ ata_intel_new_setmode(struct ata_device *atadev, int mode)
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
if (mode >= ATA_SA150) {
atadev->mode = mode;
return;
}
if (ctlr->chip->max_dma && mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { if (ctlr->chip->max_dma && mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) {
ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
mode = ATA_UDMA2; mode = ATA_UDMA2;
@ -854,7 +851,10 @@ ata_intel_new_setmode(struct ata_device *atadev, int mode)
ata_prtdev(atadev, "%s setting %s on %s chip\n", ata_prtdev(atadev, "%s setting %s on %s chip\n",
(error) ? "failed" : "success", (error) ? "failed" : "success",
ata_mode2str(mode), ctlr->chip->text); ata_mode2str(mode), ctlr->chip->text);
if (!error) { if (error)
return;
if (ctlr->chip->max_dma < ATA_SA150) {
if (mode >= ATA_UDMA0) { if (mode >= ATA_UDMA0) {
pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2); pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2);
pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno<<2))) | pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno<<2))) |
@ -894,8 +894,8 @@ ata_intel_new_setmode(struct ata_device *atadev, int mode)
} }
pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4); pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4);
pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1); pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1);
atadev->mode = mode;
} }
atadev->mode = mode;
} }
/* /*
@ -1244,11 +1244,6 @@ ata_promise_setmode(struct ata_device *atadev, int mode)
break; break;
} }
if (mode >= ATA_SA150) {
atadev->mode = mode;
return;
}
error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
ATA_C_F_SETXFER, ATA_WAIT_READY); ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose) if (bootverbose)
@ -1458,11 +1453,12 @@ ata_sii_ident(device_t dev)
struct ata_pci_controller *ctlr = device_get_softc(dev); struct ata_pci_controller *ctlr = device_get_softc(dev);
struct ata_chip_id *idx; struct ata_chip_id *idx;
static struct ata_chip_id ids[] = static struct ata_chip_id ids[] =
{{ ATA_SII0680, 0x00, 0, SII_SETCLK, ATA_UDMA6, "SiI 0680" }, {{ ATA_SII3112, 0x00, SIIMEMIO, 0, ATA_SA150, "SiI 3112" },
{ ATA_CMD649, 0x00, 0, SII_INTR|SII_ENINTR, ATA_UDMA5, "CMD 649" }, { ATA_SII0680, 0x00, SIIMEMIO, SIISETCLK, ATA_UDMA6, "SiI 0680" },
{ ATA_CMD648, 0x00, 0, SII_INTR|SII_ENINTR, ATA_UDMA4, "CMD 648" }, { ATA_CMD649, 0x00, 0, SIIINTR, ATA_UDMA5, "CMD 649" },
{ ATA_CMD646, 0x07, 0, SII_ENINTR, ATA_UDMA2, "CMD 646U2" }, { ATA_CMD648, 0x00, 0, SIIINTR, ATA_UDMA4, "CMD 648" },
{ ATA_CMD646, 0x00, 0, SII_ENINTR, ATA_WDMA2, "CMD 646" }, { ATA_CMD646, 0x07, 0, 0, ATA_UDMA2, "CMD 646U2" },
{ ATA_CMD646, 0x00, 0, 0, ATA_WDMA2, "CMD 646" },
{ 0, 0, 0, 0, 0, 0}}; { 0, 0, 0, 0, 0, 0}};
char buffer[64]; char buffer[64];
@ -1487,37 +1483,104 @@ ata_sii_chipinit(device_t dev)
device_printf(dev, "unable to map interrupt\n"); device_printf(dev, "unable to map interrupt\n");
return ENXIO; return ENXIO;
} }
if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
ctlr->chip->cfg2 & SII_INTR ?
ata_cmd_intr : ata_generic_intr,
ctlr, &ctlr->handle))) {
device_printf(dev, "unable to setup interrupt\n");
return ENXIO;
}
if (ctlr->chip->cfg2 & SII_ENINTR) if (ctlr->chip->cfg1 == SIIMEMIO) {
pci_write_config(dev, 0x71, 0x01, 1); if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
ata_sii_intr, ctlr, &ctlr->handle))) {
device_printf(dev, "unable to setup interrupt\n");
return ENXIO;
}
rid = 0x24;
if (!(ctlr->r_io2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
0, ~0, 1, RF_ACTIVE)))
return ENXIO;
if (ctlr->chip->cfg2 & SII_SETCLK) { if (ctlr->chip->cfg2 & SIISETCLK) {
if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
pci_write_config(dev, 0x8a, pci_write_config(dev, 0x8a,
(pci_read_config(dev, 0x8a, 1) & 0x0F) | 0x10, 1); (pci_read_config(dev, 0x8a, 1) & 0x0F)|0x10,1);
if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
device_printf(dev, "%s could not set ATA133 clock\n", device_printf(dev, "%s could not set ATA133 clock\n",
ctlr->chip->text); ctlr->chip->text);
}
ctlr->allocate = ata_sii_mio_allocate;
ctlr->setmode = ata_sii_setmode; ctlr->setmode = ata_sii_setmode;
} }
else else {
ctlr->setmode = ata_cmd_setmode; if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
ctlr->chip->cfg2 & SIIINTR ?
ata_cmd_intr : ata_generic_intr,
ctlr, &ctlr->handle))) {
device_printf(dev, "unable to setup interrupt\n");
return ENXIO;
}
if ((pci_read_config(dev, 0x51, 1) & 0x08) != 0x08) { if ((pci_read_config(dev, 0x51, 1) & 0x08) != 0x08) {
device_printf(dev, "secondary channel disabled\n"); device_printf(dev, "HW has secondary channel disabled\n");
ctlr->channels = 1; ctlr->channels = 1;
} }
/* enable interrupt as BIOS might not */
pci_write_config(dev, 0x71, 0x01, 1);
ctlr->setmode = ata_cmd_setmode;
}
return 0; return 0;
} }
static int
ata_sii_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 = 0x80 + i + (ch->unit << 6);
}
ch->r_io[ATA_ALTSTAT].res = ctlr->r_io2;
ch->r_io[ATA_ALTSTAT].offset = 0x8a + (ch->unit << 6);
ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_io2;
ch->r_io[ATA_BMCMD_PORT].offset = 0x00 + (ch->unit << 3);
ch->r_io[ATA_BMSTAT_PORT].res = ctlr->r_io2;
ch->r_io[ATA_BMSTAT_PORT].offset = 0x02 + (ch->unit << 3);
ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_io2;
ch->r_io[ATA_BMDTP_PORT].offset = 0x04 + (ch->unit << 3);
ch->r_io[ATA_BMDEVSPEC_0].res = ctlr->r_io2;
ch->r_io[ATA_BMDEVSPEC_0].offset = 0xa1 + (ch->unit << 6);
ch->r_io[ATA_IDX_ADDR].res = ctlr->r_io2;
if (ctlr->chip->max_dma >= ATA_SA150)
ch->flags |= ATA_NO_SLAVE;
ctlr->dmainit(ch);
return 0;
}
static void
ata_sii_intr(void *data)
{
struct ata_pci_controller *ctlr = data;
struct ata_channel *ch;
u_int8_t dmastat;
int unit;
/* implement this as a toggle instead to balance load XXX */
for (unit = 0; unit < 2; unit++) {
if (!(ch = ctlr->interrupt[unit].argument))
continue;
if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_0) & 0x08) {
if (ch->dma->flags & ATA_DMA_ACTIVE) {
if (!((dmastat = (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) &
ATA_BMSTAT_MASK)) & ATA_BMSTAT_INTERRUPT))
continue;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT);
DELAY(1);
}
ctlr->interrupt[unit].function(ch);
}
}
}
static void static void
ata_cmd_intr(void *data) ata_cmd_intr(void *data)
{ {
@ -1551,7 +1614,7 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
{ {
device_t parent = device_get_parent(atadev->channel->dev); device_t parent = device_get_parent(atadev->channel->dev);
struct ata_pci_controller *ctlr = device_get_softc(parent); struct ata_pci_controller *ctlr = device_get_softc(parent);
int devno = (atadev->channel->unit << 4) + (ATA_DEV(atadev->unit) << 1); int rego = (atadev->channel->unit << 4) + (ATA_DEV(atadev->unit) << 1);
int mreg = atadev->channel->unit ? 0x84 : 0x80; int mreg = atadev->channel->unit ? 0x84 : 0x80;
int mask = 0x03 << (ATA_DEV(atadev->unit) << 2); int mask = 0x03 << (ATA_DEV(atadev->unit) << 2);
int mval = pci_read_config(parent, mreg, 1) & ~mask; int mval = pci_read_config(parent, mreg, 1) & ~mask;
@ -1559,7 +1622,8 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
mode = ata_check_80pin(atadev, mode); if (ctlr->chip->max_dma < ATA_SA150)
mode = ata_check_80pin(atadev, mode);
error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
ATA_C_F_SETXFER, ATA_WAIT_READY); ATA_C_F_SETXFER, ATA_WAIT_READY);
@ -1567,20 +1631,24 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
ata_prtdev(atadev, "%s setting %s on %s chip\n", ata_prtdev(atadev, "%s setting %s on %s chip\n",
(error) ? "failed" : "success", (error) ? "failed" : "success",
ata_mode2str(mode), ctlr->chip->text); ata_mode2str(mode), ctlr->chip->text);
if (!error) {
if (error)
return;
if (ctlr->chip->max_dma < ATA_SA150) {
if (mode >= ATA_UDMA0) { if (mode >= ATA_UDMA0) {
u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 }; u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 };
u_int8_t ureg = 0xac + devno; u_int8_t ureg = 0xac + rego;
pci_write_config(parent, mreg, pci_write_config(parent, mreg,
mval | (0x03 << (ATA_DEV(atadev->unit) << 2)), 1); mval | (0x03 << (ATA_DEV(atadev->unit) << 2)), 1);
pci_write_config(parent, ureg, pci_write_config(parent, ureg,
(pci_read_config(parent, ureg, 1) & 0x3f) | (pci_read_config(parent, ureg, 1) & ~0x3f) |
udmatimings[mode & ATA_MODE_MASK], 1); udmatimings[mode & ATA_MODE_MASK], 1);
} }
else if (mode >= ATA_WDMA0) { else if (mode >= ATA_WDMA0) {
u_int8_t dreg = 0xa8 + devno; u_int8_t dreg = 0xa8 + rego;
u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 }; u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 };
pci_write_config(parent, mreg, pci_write_config(parent, mreg,
@ -1589,15 +1657,15 @@ ata_sii_setmode(struct ata_device *atadev, int mode)
} }
else { else {
u_int8_t preg = 0xa4 + devno; u_int8_t preg = 0xa4 + rego;
u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
pci_write_config(parent, mreg, pci_write_config(parent, mreg,
mval | (0x01 << (ATA_DEV(atadev->unit) << 2)), 1); mval | (0x01 << (ATA_DEV(atadev->unit) << 2)), 1);
pci_write_config(parent, preg, piotimings[mode & ATA_MODE_MASK], 2); pci_write_config(parent, preg, piotimings[mode & ATA_MODE_MASK], 2);
} }
atadev->mode = mode;
} }
atadev->mode = mode;
} }
static void static void

View File

@ -152,18 +152,13 @@ ata_pci_attach(device_t dev)
cmd = pci_read_config(dev, PCIR_COMMAND, 2); cmd = pci_read_config(dev, PCIR_COMMAND, 2);
} }
#endif #endif
/* is busmastering supported and configured ? */ /* if busmastering configured get the I/O resource */
if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
int rid = ATA_BMADDR_RID; int rid = ATA_BMADDR_RID;
if (!ctlr->r_io2) { ctlr->r_io1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
if (!(ctlr->r_io1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
0, ~0, 1, RF_ACTIVE)))
device_printf(dev, "Busmastering DMA not configured\n");
}
} }
else
device_printf(dev, "Busmastering DMA not supported\n");
ctlr->chipinit(dev); ctlr->chipinit(dev);

View File

@ -154,6 +154,7 @@ struct ata_pci_controller {
#define ATA_SILICON_IMAGE_ID 0x1095 #define ATA_SILICON_IMAGE_ID 0x1095
#define ATA_SII0680 0x06801095 #define ATA_SII0680 0x06801095
#define ATA_SII3112 0x31121095
#define ATA_CMD646 0x06461095 #define ATA_CMD646 0x06461095
#define ATA_CMD648 0x06481095 #define ATA_CMD648 0x06481095
#define ATA_CMD649 0x06491095 #define ATA_CMD649 0x06491095
@ -242,9 +243,9 @@ struct ata_pci_controller {
#define SWKS66 1 #define SWKS66 1
#define SWKS100 2 #define SWKS100 2
#define SII_INTR 0x01 #define SIIMEMIO 1
#define SII_SETCLK 0x02 #define SIIINTR 0x01
#define SII_ENINTR 0x04 #define SIISETCLK 0x02
#define SIS_SOUTH 1 #define SIS_SOUTH 1
#define SIS133NEW 2 #define SIS133NEW 2