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