Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Rework SiS support: more controller supported (u...
details: https://anonhg.NetBSD.org/src/rev/670c317d9ec4
branches: trunk
changeset: 544220:670c317d9ec4
user: bouyer <bouyer%NetBSD.org@localhost>
date: Fri Mar 14 22:46:05 2003 +0000
description:
Rework SiS support: more controller supported (up to Ultra/133) and better
support for the older ones.
Information for this work extracted from Soeren Schmidt's FreeBSD driver.
diffstat:
sys/dev/pci/pciide.c | 307 ++++++++++++++++++++++++++++++++++++------
sys/dev/pci/pciide_sis_reg.h | 73 +++++++--
sys/dev/pci/pciidevar.h | 5 +-
3 files changed, 322 insertions(+), 63 deletions(-)
diffs (truncated from 511 to 300 lines):
diff -r 0b0e06ae873c -r 670c317d9ec4 sys/dev/pci/pciide.c
--- a/sys/dev/pci/pciide.c Fri Mar 14 22:27:34 2003 +0000
+++ b/sys/dev/pci/pciide.c Fri Mar 14 22:46:05 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pciide.c,v 1.181 2003/02/28 22:07:05 enami Exp $ */
+/* $NetBSD: pciide.c,v 1.182 2003/03/14 22:46:05 bouyer Exp $ */
/*
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pciide.c,v 1.181 2003/02/28 22:07:05 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pciide.c,v 1.182 2003/03/14 22:46:05 bouyer Exp $");
#ifndef WDCDEBUG
#define WDCDEBUG
@@ -187,7 +187,9 @@
void sis_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
void sis_setup_channel __P((struct channel_softc*));
+void sis96x_setup_channel __P((struct channel_softc*));
static int sis_hostbr_match __P(( struct pci_attach_args *));
+static int sis_south_match __P(( struct pci_attach_args *));
void acer_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
void acer_setup_channel __P((struct channel_softc*));
@@ -431,7 +433,7 @@
const struct pciide_product_desc pciide_sis_products[] = {
{ PCI_PRODUCT_SIS_5597_IDE,
0,
- "Silicon Integrated System 5597/5598 IDE controller",
+ NULL,
sis_chip_map,
},
{ 0,
@@ -3130,16 +3132,90 @@
}
}
+static struct sis_hostbr_type {
+ u_int16_t id;
+ u_int8_t rev;
+ u_int8_t udma_mode;
+ char *name;
+ u_int8_t type;
+#define SIS_TYPE_NOUDMA 0
+#define SIS_TYPE_66 1
+#define SIS_TYPE_100OLD 2
+#define SIS_TYPE_100NEW 3
+#define SIS_TYPE_133OLD 4
+#define SIS_TYPE_133NEW 5
+#define SIS_TYPE_SOUTH 6
+} sis_hostbr_type[] = {
+ /* Most infos here are from sos%freebsd.org@localhost */
+ {PCI_PRODUCT_SIS_530HB, 0x00, 4, "530", SIS_TYPE_66},
+#if 0
+ /*
+ * controllers associated to a rev 0x2 530 Host to PCI Bridge
+ * have problems with UDMA (info provided by Christos)
+ */
+ {PCI_PRODUCT_SIS_530HB, 0x02, 0, "530 (buggy)", SIS_TYPE_NOUDMA},
+#endif
+ {PCI_PRODUCT_SIS_540HB, 0x00, 4, "540", SIS_TYPE_66},
+ {PCI_PRODUCT_SIS_550HB, 0x00, 4, "550", SIS_TYPE_66},
+ {PCI_PRODUCT_SIS_620, 0x00, 4, "620", SIS_TYPE_66},
+ {PCI_PRODUCT_SIS_630, 0x00, 4, "630", SIS_TYPE_66},
+ {PCI_PRODUCT_SIS_630, 0x30, 5, "630S", SIS_TYPE_100NEW},
+ {PCI_PRODUCT_SIS_633, 0x00, 5, "633", SIS_TYPE_100NEW},
+ {PCI_PRODUCT_SIS_635, 0x00, 5, "635", SIS_TYPE_100NEW},
+ {PCI_PRODUCT_SIS_640, 0x00, 4, "640", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_645, 0x00, 6, "645", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_646, 0x00, 6, "645DX", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_648, 0x00, 6, "648", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_650, 0x00, 6, "650", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_651, 0x00, 6, "651", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_652, 0x00, 6, "652", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_655, 0x00, 6, "655", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_658, 0x00, 6, "658", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_730, 0x00, 5, "730", SIS_TYPE_100OLD},
+ {PCI_PRODUCT_SIS_733, 0x00, 5, "733", SIS_TYPE_100NEW},
+ {PCI_PRODUCT_SIS_735, 0x00, 5, "735", SIS_TYPE_100NEW},
+ {PCI_PRODUCT_SIS_740, 0x00, 5, "740", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_745, 0x00, 5, "745", SIS_TYPE_100NEW},
+ {PCI_PRODUCT_SIS_746, 0x00, 6, "746", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_748, 0x00, 6, "748", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_750, 0x00, 6, "750", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_751, 0x00, 6, "751", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_752, 0x00, 6, "752", SIS_TYPE_SOUTH},
+ {PCI_PRODUCT_SIS_755, 0x00, 6, "755", SIS_TYPE_SOUTH},
+ /*
+ * From sos%freebsd.org@localhost: the 0x961 ID will never be found in real world
+ * {PCI_PRODUCT_SIS_961, 0x00, 6, "961", SIS_TYPE_133NEW},
+ */
+ {PCI_PRODUCT_SIS_962, 0x00, 6, "962", SIS_TYPE_133NEW},
+ {PCI_PRODUCT_SIS_963, 0x00, 6, "963", SIS_TYPE_133NEW},
+};
+
+static struct sis_hostbr_type *sis_hostbr_type_match;
+
static int
sis_hostbr_match(pa)
struct pci_attach_args *pa;
{
- return ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS) &&
- ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_645) ||
- (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_650) ||
- (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_730) ||
- (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_735) ||
- (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_745)));
+ int i;
+ if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_SIS)
+ return 0;
+ sis_hostbr_type_match = NULL;
+ for (i = 0;
+ i < sizeof(sis_hostbr_type) / sizeof(sis_hostbr_type[0]);
+ i++) {
+ if (PCI_PRODUCT(pa->pa_id) == sis_hostbr_type[i].id &&
+ PCI_REVISION(pa->pa_class) >= sis_hostbr_type[i].rev)
+ sis_hostbr_type_match = &sis_hostbr_type[i];
+ }
+ return (sis_hostbr_type_match != NULL);
+}
+
+static int sis_south_match(pa)
+ struct pci_attach_args *pa;
+{
+ return(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_85C503 &&
+ PCI_REVISION(pa->pa_class) >= 0x10);
}
void
@@ -3153,54 +3229,94 @@
pcireg_t interface = PCI_INTERFACE(pa->pa_class);
pcireg_t rev = PCI_REVISION(pa->pa_class);
bus_size_t cmdsize, ctlsize;
- pcitag_t pchb_tag;
- pcireg_t pchb_id, pchb_class;
if (pciide_chipen(sc, pa) == 0)
return;
+ printf("Silicon Integrated System ");
+ pci_find_device(pa, sis_hostbr_match);
+ if (sis_hostbr_type_match) {
+ if (sis_hostbr_type_match->type == SIS_TYPE_SOUTH) {
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_57,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag,
+ SIS_REG_57) & 0x7f);
+ if (PCI_PRODUCT(pci_conf_read(sc->sc_pc, sc->sc_tag,
+ PCI_ID_REG)) == SIS_PRODUCT_5518) {
+ printf("96X UDMA%d",
+ sis_hostbr_type_match->udma_mode);
+ sc->sis_type = SIS_TYPE_133NEW;
+ sc->sc_wdcdev.UDMA_cap =
+ sis_hostbr_type_match->udma_mode;
+ } else {
+ if (pci_find_device(pa, sis_south_match)) {
+ sc->sis_type = SIS_TYPE_133OLD;
+ sc->sc_wdcdev.UDMA_cap =
+ sis_hostbr_type_match->udma_mode;
+ } else {
+ sc->sis_type = SIS_TYPE_100NEW;
+ sc->sc_wdcdev.UDMA_cap =
+ sis_hostbr_type_match->udma_mode;
+ }
+ }
+ } else {
+ printf(sis_hostbr_type_match->name);
+ sc->sis_type = sis_hostbr_type_match->type;
+ sc->sc_wdcdev.UDMA_cap =
+ sis_hostbr_type_match->udma_mode;
+ }
+ } else {
+ printf("5597/5598");
+ sc->sis_type = 0;
+ if (rev >= 0xd0) {
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
+ sc->sc_wdcdev.UDMA_cap = 2;
+ } else {
+ sc->sc_wdcdev.UDMA_cap = 0;
+ }
+ }
+ printf(" IDE controller (rev. 0x%02x)\n", PCI_REVISION(pa->pa_class));
printf("%s: bus-master DMA support present",
sc->sc_wdcdev.sc_dev.dv_xname);
pciide_mapreg_dma(sc, pa);
printf("\n");
- /* get a PCI tag for the host bridge (function 0 of the same device) */
- pchb_tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 0);
- /* and read ID and rev of the ISA bridge */
- pchb_id = pci_conf_read(sc->sc_pc, pchb_tag, PCI_ID_REG);
- pchb_class = pci_conf_read(sc->sc_pc, pchb_tag, PCI_CLASS_REG);
-
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 | WDC_CAPABILITY_IRQACK;
sc->sc_wdcdev.irqack = pciide_irqack;
- /*
- * controllers associated to a rev 0x2 530 Host to PCI Bridge
- * have problems with UDMA (info provided by Christos)
- */
- if (rev >= 0xd0 &&
- (PCI_PRODUCT(pchb_id) != PCI_PRODUCT_SIS_530HB ||
- PCI_REVISION(pchb_class) >= 0x03))
+ if (sc->sis_type >= SIS_TYPE_66)
sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
}
sc->sc_wdcdev.PIO_cap = 4;
sc->sc_wdcdev.DMA_cap = 2;
- if (sc->sc_wdcdev.cap & WDC_CAPABILITY_UDMA)
- /*
- * Use UDMA/100 on SiS 735 chipset and UDMA/33 on other
- * chipsets.
- */
- sc->sc_wdcdev.UDMA_cap =
- pci_find_device(pa, sis_hostbr_match) ? 5 : 2;
- sc->sc_wdcdev.set_modes = sis_setup_channel;
sc->sc_wdcdev.channels = sc->wdc_chanarray;
sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
-
- pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_MISC,
- pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_MISC) |
- SIS_MISC_TIM_SEL | SIS_MISC_FIFO_SIZE);
+ switch(sc->sis_type) {
+ case SIS_TYPE_NOUDMA:
+ case SIS_TYPE_66:
+ case SIS_TYPE_100OLD:
+ sc->sc_wdcdev.set_modes = sis_setup_channel;
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_MISC,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_MISC) |
+ SIS_MISC_TIM_SEL | SIS_MISC_FIFO_SIZE | SIS_MISC_GTC);
+ break;
+ case SIS_TYPE_100NEW:
+ case SIS_TYPE_133OLD:
+ sc->sc_wdcdev.set_modes = sis_setup_channel;
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_49,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_49) | 0x01);
+ break;
+ case SIS_TYPE_133NEW:
+ sc->sc_wdcdev.set_modes = sis96x_setup_channel;
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_50,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_50) & 0xf7);
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_REG_52,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_52) & 0xf7);
+ break;
+ }
+
for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
cp = &sc->pciide_channels[channel];
@@ -3227,11 +3343,78 @@
pciide_map_compat_intr(pa, cp, channel, interface);
if (cp->hw_ok == 0)
continue;
- sis_setup_channel(&cp->wdc_channel);
+ sc->sc_wdcdev.set_modes(&cp->wdc_channel);
}
}
void
+sis96x_setup_channel(chp)
+ struct channel_softc *chp;
+{
+ struct ata_drive_datas *drvp;
+ int drive;
+ u_int32_t sis_tim;
+ u_int32_t idedma_ctl;
+ int regtim;
+ struct pciide_channel *cp = (struct pciide_channel*)chp;
+ struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+
+ sis_tim = 0;
+ idedma_ctl = 0;
+ /* setup DMA if needed */
+ pciide_channel_dma_setup(cp);
+
+ for (drive = 0; drive < 2; drive++) {
+ regtim = SIS_TIM133(
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, SIS_REG_57),
+ chp->channel, drive);
+ drvp = &chp->ch_drive[drive];
+ /* If no drive, skip */
+ if ((drvp->drive_flags & DRIVE) == 0)
+ continue;
+ /* add timing values, setup DMA if needed */
+ if (drvp->drive_flags & DRIVE_UDMA) {
+ /* use Ultra/DMA */
+ drvp->drive_flags &= ~DRIVE_DMA;
+ if (pciide_pci_read(sc->sc_pc, sc->sc_tag,
+ SIS96x_REG_CBL(chp->channel)) & SIS96x_REG_CBL_33) {
+ if (drvp->UDMA_mode > 2)
+ drvp->UDMA_mode = 2;
+ }
+ sis_tim |= sis_udma133new_tim[drvp->UDMA_mode];
Home |
Main Index |
Thread Index |
Old Index