summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2003-05-02 09:33:34 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2003-05-02 09:33:34 +0000
commitb7c3fc1d2fbe20b25e4443231260472da16d4da6 (patch)
tree4c21cbb01eb82bf4993e7ecbbf124d8359ec0a5f
parent23c53b94c65e87a6e5c233cbdf04ec2f6d16645e (diff)
Rework SIS IDE support. Unbreak the newest chips and fix issues with the
old ones. Original work by sos@freebsd, then adapted for netbsd by bouyer@netbsd. Many thanks to Paul de Weerd <paul@mail.me.maar.nu> for problem report, providing url to the preliminary netbsd diff and access to testing machine. Extra testing by tedu@.
-rw-r--r--sys/dev/pci/pciide.c320
-rw-r--r--sys/dev/pci/pciide_sis_reg.h68
2 files changed, 342 insertions, 46 deletions
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index b513af827a8..f4602fde90d 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.122 2003/04/27 11:22:53 ho Exp $ */
+/* $OpenBSD: pciide.c,v 1.123 2003/05/02 09:33:33 grange Exp $ */
/* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */
/*
@@ -167,6 +167,9 @@ struct pciide_softc {
const struct cy82c693_handle *sc_cy_handle;
int sc_cy_compatchan;
+ /* For SiS */
+ u_int8_t sis_type;
+
/* Chip description */
const struct pciide_product_desc *sc_pp;
/* common definitions */
@@ -222,6 +225,9 @@ void cy693_setup_channel(struct channel_softc*);
void sis_chip_map(struct pciide_softc*, struct pci_attach_args*);
void sis_setup_channel(struct channel_softc*);
+void sis96x_setup_channel(struct channel_softc *);
+int sis_hostbr_match(struct pci_attach_args *);
+int sis_south_match(struct pci_attach_args *);
void natsemi_chip_map(struct pciide_softc*, struct pci_attach_args*);
void natsemi_setup_channel(struct channel_softc*);
@@ -3196,6 +3202,92 @@ cy693_setup_channel(chp)
}
}
+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 */
+ {PCI_PRODUCT_SIS_530, 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_530, 0x02, 0, "530 (buggy)", SIS_TYPE_NOUDMA},
+#endif
+ {PCI_PRODUCT_SIS_540, 0x00, 4, "540", SIS_TYPE_66},
+ {PCI_PRODUCT_SIS_550, 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: 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;
+
+int
+sis_hostbr_match(struct pci_attach_args *pa)
+{
+ 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);
+}
+
+int
+sis_south_match(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
sis_chip_map(sc, pa)
struct pciide_softc *sc;
@@ -3207,58 +3299,118 @@ sis_chip_map(sc, pa)
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;
+ pcitag_t br_tag;
+ struct pci_attach_args br_pa;
if (pciide_chipen(sc, pa) == 0)
return;
+ /* Find PCI bridge (dev 0 func 0 on the same bus) */
+ br_tag = pci_make_tag(pa->pa_pc, pa->pa_bus, 0, 0);
+ br_pa.pa_id = pci_conf_read(sc->sc_pc, br_tag, PCI_ID_REG);
+ br_pa.pa_class = pci_conf_read(sc->sc_pc, br_tag, PCI_CLASS_REG);
+ WDCDEBUG_PRINT(("%s: PCI bridge pa_id=0x%x pa_class=0x%x\n",
+ __func__, br_pa.pa_id, br_pa.pa_class), DEBUG_PROBE);
+
+ if (sis_hostbr_match(&br_pa)) {
+ 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) {
+ sc->sis_type = SIS_TYPE_133NEW;
+ sc->sc_wdcdev.UDMA_cap =
+ sis_hostbr_type_match->udma_mode;
+ } else {
+ /* Find ISA bridge (func 0 of the same dev) */
+ br_tag = pci_make_tag(pa->pa_pc, pa->pa_bus,
+ pa->pa_device, 0);
+ br_pa.pa_id = pci_conf_read(sc->sc_pc,
+ br_tag, PCI_ID_REG);
+ br_pa.pa_class = pci_conf_read(sc->sc_pc,
+ br_tag, PCI_CLASS_REG);
+ WDCDEBUG_PRINT(("%s: ISA bridge "
+ "pa_id=0x%x pa_class=0x%x\n",
+ __func__, br_pa.pa_id, br_pa.pa_class),
+ DEBUG_PROBE);
+
+ if (sis_south_match(&br_pa)) {
+ 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 {
+ sc->sis_type = sis_hostbr_type_match->type;
+ sc->sc_wdcdev.UDMA_cap =
+ sis_hostbr_type_match->udma_mode;
+ }
+ printf(": %s", sis_hostbr_type_match->name);
+ } else {
+ printf(": 5597/5598");
+ if (rev >= 0xd0) {
+ sc->sc_wdcdev.UDMA_cap = 2;
+ sc->sis_type = SIS_TYPE_66;
+ } else {
+ sc->sc_wdcdev.UDMA_cap = 0;
+ sc->sis_type = SIS_TYPE_NOUDMA;
+ }
+ }
+
printf(": DMA");
pciide_mapreg_dma(sc, pa);
- /* 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 with rev > 0xd0 support UDMA 2 at least
- * controllers associated to a rev 0x2 530 Host to PCI Bridge
- * have problems with UDMA
- */
- if (rev >= 0xd0 &&
- (PCI_PRODUCT(pchb_id) != PCI_PRODUCT_SIS_530 ||
- 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)
- sc->sc_wdcdev.UDMA_cap = 2;
- sc->sc_wdcdev.set_modes = sis_setup_channel;
sc->sc_wdcdev.channels = sc->wdc_chanarray;
sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
+ 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;
+ }
pciide_print_channels(sc->sc_wdcdev.nchannels, interface);
- 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);
-
for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
cp = &sc->pciide_channels[channel];
if (pciide_chansetup(sc, channel, interface) == 0)
continue;
if ((channel == 0 && (sis_ctr0 & SIS_CTRL0_CHAN0_EN) == 0) ||
- (channel == 1 && (sis_ctr0 & SIS_CTRL0_CHAN1_EN) == 0)) {
+ (channel == 1 && (sis_ctr0 & SIS_CTRL0_CHAN1_EN) == 0)) {
printf("%s: %s ignored (disabled)\n",
sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
continue;
@@ -3284,8 +3436,73 @@ sis_chip_map(sc, pa)
pciide_unmap_compat_intr(pa, cp, channel, interface);
continue;
}
- sis_setup_channel(&cp->wdc_channel);
+ sc->sc_wdcdev.set_modes(&cp->wdc_channel);
+ }
+}
+
+void
+sis96x_setup_channel(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];
+ sis_tim |= sis_pio133new_tim[drvp->PIO_mode];
+ idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
+ } else 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 > (drvp->DMA_mode + 2))
+ drvp->PIO_mode = drvp->DMA_mode + 2;
+ if (drvp->DMA_mode + 2 > (drvp->PIO_mode))
+ drvp->DMA_mode = (drvp->PIO_mode > 2) ?
+ drvp->PIO_mode - 2 : 0;
+ sis_tim |= sis_dma133new_tim[drvp->DMA_mode];
+ idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
+ } else {
+ sis_tim |= sis_pio133new_tim[drvp->PIO_mode];
+ }
+ WDCDEBUG_PRINT(("sis96x_setup_channel: new timings reg for "
+ "channel %d drive %d: 0x%x (reg 0x%x)\n",
+ chp->channel, drive, sis_tim, regtim), DEBUG_PROBE);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, regtim, sis_tim);
+ }
+ if (idedma_ctl != 0) {
+ /* Add software bits in status register */
+ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ IDEDMA_CTL(chp->channel), idedma_ctl);
}
+ pciide_print_modes(cp);
}
void
@@ -3321,9 +3538,30 @@ sis_setup_channel(chp)
if (drvp->drive_flags & DRIVE_UDMA) {
/* use Ultra/DMA */
drvp->drive_flags &= ~DRIVE_DMA;
- sis_tim |= sis_udma_tim[drvp->UDMA_mode] <<
- SIS_TIM_UDMA_TIME_OFF(drive);
- sis_tim |= SIS_TIM_UDMA_EN(drive);
+ if (pciide_pci_read(sc->sc_pc, sc->sc_tag,
+ SIS_REG_CBL) & SIS_REG_CBL_33(chp->channel)) {
+ if (drvp->UDMA_mode > 2)
+ drvp->UDMA_mode = 2;
+ }
+ switch (sc->sis_type) {
+ case SIS_TYPE_66:
+ case SIS_TYPE_100OLD:
+ sis_tim |= sis_udma66_tim[drvp->UDMA_mode] <<
+ SIS_TIM66_UDMA_TIME_OFF(drive);
+ break;
+ case SIS_TYPE_100NEW:
+ sis_tim |=
+ sis_udma100new_tim[drvp->UDMA_mode] <<
+ SIS_TIM100_UDMA_TIME_OFF(drive);
+ case SIS_TYPE_133OLD:
+ sis_tim |=
+ sis_udma133old_tim[drvp->UDMA_mode] <<
+ SIS_TIM100_UDMA_TIME_OFF(drive);
+ break;
+ default:
+ printf("unknown SiS IDE type %d\n",
+ sc->sis_type);
+ }
} else {
/*
* use Multiword DMA
@@ -3339,10 +3577,26 @@ sis_setup_channel(chp)
drvp->PIO_mode = 0;
}
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
-pio: sis_tim |= sis_pio_act[drvp->PIO_mode] <<
- SIS_TIM_ACT_OFF(drive);
- sis_tim |= sis_pio_rec[drvp->PIO_mode] <<
- SIS_TIM_REC_OFF(drive);
+pio: switch (sc->sis_type) {
+ case SIS_TYPE_NOUDMA:
+ case SIS_TYPE_66:
+ case SIS_TYPE_100OLD:
+ sis_tim |= sis_pio_act[drvp->PIO_mode] <<
+ SIS_TIM66_ACT_OFF(drive);
+ sis_tim |= sis_pio_rec[drvp->PIO_mode] <<
+ SIS_TIM66_REC_OFF(drive);
+ break;
+ case SIS_TYPE_100NEW:
+ case SIS_TYPE_133OLD:
+ sis_tim |= sis_pio_act[drvp->PIO_mode] <<
+ SIS_TIM100_ACT_OFF(drive);
+ sis_tim |= sis_pio_rec[drvp->PIO_mode] <<
+ SIS_TIM100_REC_OFF(drive);
+ break;
+ default:
+ printf("unknown SiS IDE type %d\n",
+ sc->sis_type);
+ }
}
WDCDEBUG_PRINT(("sis_setup_channel: new timings reg for "
"channel %d 0x%x\n", chp->channel, sis_tim), DEBUG_PROBE);
diff --git a/sys/dev/pci/pciide_sis_reg.h b/sys/dev/pci/pciide_sis_reg.h
index 0e1f14fb29e..07ec1479d4f 100644
--- a/sys/dev/pci/pciide_sis_reg.h
+++ b/sys/dev/pci/pciide_sis_reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide_sis_reg.h,v 1.3 2003/02/21 20:10:34 grange Exp $ */
+/* $OpenBSD: pciide_sis_reg.h,v 1.4 2003/05/02 09:33:33 grange Exp $ */
/* $NetBSD: pciide_sis_reg.h,v 1.6 2000/05/15 08:46:01 bouyer Exp $ */
/*
@@ -37,12 +37,24 @@
* Available from http://www.sis.com.tw/html/databook.html
*/
-/* IDE timing control registers (32 bits) */
+/* IDE timing control registers (32 bits), for all but 96x */
#define SIS_TIM(channel) (0x40 + (channel * 4))
-#define SIS_TIM_REC_OFF(drive) (16 * (drive))
-#define SIS_TIM_ACT_OFF(drive) (8 + 16 * (drive))
-#define SIS_TIM_UDMA_TIME_OFF(drive) (13 + 16 * (drive))
-#define SIS_TIM_UDMA_EN(drive) (1 << (15 + 16 * (drive)))
+/* for 730, 630 and older (66, 100OLD) */
+#define SIS_TIM66_REC_OFF(drive) (16 * (drive))
+#define SIS_TIM66_ACT_OFF(drive) (8 + 16 * (drive))
+#define SIS_TIM66_UDMA_TIME_OFF(drive) (12 + 16 * (drive))
+/* for older than 96x (100NEW, 133OLD) */
+#define SIS_TIM100_REC_OFF(drive) (16 * (drive))
+#define SIS_TIM100_ACT_OFF(drive) (4 + 16 * (drive))
+#define SIS_TIM100_UDMA_TIME_OFF(drive) (8 + 16 * (drive))
+
+/*
+ * From FreeBSD: on 96x, the timing registers may start from 0x40 or 0x70
+ * depending on the value from register 0x57. 32bits of timing info for
+ * each drive.
+ */
+#define SIS_TIM133(reg57, channel, drive) \
+ ((((reg57) & 0x40) ? 0x70 : 0x40) + ((channel) << 3) + ((drive) << 2))
/* IDE general control register 0 (8 bits) */
#define SIS_CTRL0 0x4a
@@ -63,10 +75,40 @@
#define SIS_MISC_GTC 0x04
#define SIS_MISC_FIFO_SIZE 0x01
-static int8_t sis_pio_act[] = {7, 5, 4, 3, 3};
-static int8_t sis_pio_rec[] = {7, 0, 5, 3, 1};
-#ifdef unused
-static int8_t sis_dma_act[] = {0, 3, 3};
-static int8_t sis_dma_rec[] = {0, 2, 1};
-#endif
-static int8_t sis_udma_tim[] = {3, 2, 1};
+/* following are from FreeBSD (sorry, no description) */
+#define SIS_REG_49 0x49
+#define SIS_REG_50 0x50
+#define SIS_REG_51 0x51
+#define SIS_REG_52 0x52
+#define SIS_REG_53 0x53
+#define SIS_REG_57 0x57
+
+#define SIS_REG_CBL 0x48
+#define SIS_REG_CBL_33(channel) (0x10 << (channel))
+#define SIS96x_REG_CBL(channel) (0x51 + (channel) * 2)
+#define SIS96x_REG_CBL_33 0x80
+
+#define SIS_PRODUCT_5518 0x5518
+
+/* timings values, mostly from FreeBSD */
+/* PIO timings, for all up to 133NEW */
+static const u_int8_t sis_pio_act[] =
+ {12, 6, 4, 3, 3};
+static const u_int8_t sis_pio_rec[] =
+ {11, 7, 4, 3, 1};
+/* DMA timings for 66 and 100OLD */
+static const u_int8_t sis_udma66_tim[] =
+ {15, 13, 11, 10, 9, 8};
+/* DMA timings for 100NEW */
+static const u_int8_t sis_udma100new_tim[] =
+ {0x8b, 0x87, 0x85, 0x84, 0x82, 0x81};
+/* DMA timings for 133OLD */
+static const u_int8_t sis_udma133old_tim[] =
+ {0x8f, 0x8a, 0x87, 0x85, 0x83, 0x82, 0x81};
+/* PIO, DMA and UDMA timings for 133NEW */
+static const u_int32_t sis_pio133new_tim[] =
+ {0x28269008, 0x0c266008, 0x4263008, 0x0c0a3008, 0x05093008};
+static const u_int32_t sis_dma133new_tim[] =
+ {0x22196008, 0x0c0a3008, 0x05093008};
+static const u_int32_t sis_udma133new_tim[] =
+ {0x9f4, 0x64a, 0x474, 0x254, 0x234, 0x224, 0x214};