tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
viaide(4) improvements for CX700/VX800
Hi,
I have been working on the VIA CX700/VX800 SATA/IDE controller to
enable it to work with both SATA and IDE devices in RAID mode,
addressing the issue I reported in PR kern/59010. The final patch is
attached or can be reviewed here
(https://github.com/vezhlys/netbsd-src/pull/1/files). Would like to
get comments on it if it is correct approach and can be committed.
For the context, CX700/VX800 controller is "unique" between VIA
controllers in the way that IDE/SATA ports are not separated by
separate PCI IDs in RAID mode (we registered pci id as CX700_IDE) like
with most older controllers, instead there are two channels under the
same PCI ID, first one for SATA, second for the IDE. It also doesn't
implement BAR(5) to map SATA regs like few other newer VIA SATA
controllers. Finally SATA channel has primary and secondary links, so
two drives needs to be supported by the channel. In IDE mode (which is
identified as pci id CX700M2_IDE) it is not an issue, via_chip_map
attaches all drives as IDE devices. For RAID mode it changes PCI ID to
CX700_IDE and via_sata_chip_map_new is used currently (this method is
tailored for VIA Technologies VT6421 add-in controller), but it was
not actually fully correct decision and IDE drives are not attached
with it. The only reason it worked, because failing to map SATA regs
through BAR(5) doesn't return early.
My implementation adds additional flag to setup channel 1 as PATA
interface and cater other differences. Currently flag is checked four
times, but I will likely need to replace at least two occurrences with
additional flags(?) in the future (something like (DO_NOT_)MAP_BAR5,
TWO_PORTS_PER_CHANNEL) to facilitate other controllers (VT8251 has two
ports per channel but also needs implements BAR(5) e.g.).
Tested changes on two VX800 based boards, all drives attach properly.
If RAID is configured for SATA drives, they are also recognized and
attached as ld(4) device.
Some unknows for me: for SATA ports I can't use wdc_sataprobe as it
causes crash for this controller, so default wdc_drvprobe is used
(VT6421 does the same now). I don't know why. Also, since bar5 is not
mapped, I am not fully sure what happens in via_sata_chip_map lines
like and subsequent bus_space_subregion() calls, but those calls don't
return (or log) any error:
wdr->sata_iot = sc->sc_ba5_st;
wdr->sata_baseioh = sc->sc_ba5_sh;
if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh,
(wdc_cp->ch_channel << satareg_shift) + 0x0, 4,
&wdr->sata_status) != 0) {
...
VX800 chipset documentation can be found here:
https://bitsavers.trailing-edge.com/components/viaTechnologies/VX800_VX820_Series_System_Programming_Manual_Rev_.95_200806.pdf
Thank you.
Regards,
Andrius V
From 3f5c615ccac72acb5d66799d0d714a87ef2aac21 Mon Sep 17 00:00:00 2001
From: Andrius V <vezhlys%netscape.net@localhost>
Date: Sat, 15 Feb 2025 00:34:37 +0200
Subject: [PATCH 1/2] working sata and pata.
---
sys/dev/pci/pcidevs | 4 ++--
sys/dev/pci/pciide_apollo_reg.h | 1 +
sys/dev/pci/pciidevar.h | 1 +
sys/dev/pci/viaide.c | 34 ++++++++++++++++++++++++++++-----
4 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/sys/dev/pci/pcidevs b/sys/dev/pci/pcidevs
index 51dbd5a05656..db1b76088cf5 100644
--- a/sys/dev/pci/pcidevs
+++ b/sys/dev/pci/pcidevs
@@ -10061,7 +10061,7 @@ product VIATECH VT82C505 0x0505 VT82C505 (Pluto)
product VIATECH VT82C561 0x0561 VT82C561
product VIATECH VT82C586A_IDE 0x0571 VT82C586A IDE Controller
product VIATECH VT82C576 0x0576 VT82C576 3V
-product VIATECH CX700_IDE 0x0581 CX700 IDE Controller
+product VIATECH CX700_IDE 0x0581 CX700(M2)/VX700/VX800 SATA/IDE RAID Controller
product VIATECH VT82C580VP 0x0585 VT82C580 (Apollo VP) Host-PCI Bridge
product VIATECH VT82C586_ISA 0x0586 VT82C586 PCI-ISA Bridge
product VIATECH VT8237A_SATA 0x0591 VT8237A Integrated SATA Controller
@@ -10143,7 +10143,7 @@ product VIATECH VT3351_HB_4351 0x4351 VT3351 Host Bridge
product VIATECH VX800_PMC 0x4353 VX800/VX820 Power Management Control
product VIATECH P4M900_4 0x4364 CN896/P4M900 Host Bridge
product VIATECH VX900_1 0x4410 VX900 Power Management Controller
-product VIATECH CX700M2_IDE 0x5324 CX700M2/VX700 IDE Controller
+product VIATECH CX700M2_IDE 0x5324 CX700(M2)/VX700/VX800/VX820 IDE Controller
product VIATECH VT8237A_SATA_2 0x5337 VT8237A Integrated SATA Controller
product VIATECH VT3351_IOAPIC 0x5351 VT3351 I/O APIC Interrupt Controller
product VIATECH VX800_APIC 0x5353 VX800/VX820 APIC and Central Traffic Control
diff --git a/sys/dev/pci/pciide_apollo_reg.h b/sys/dev/pci/pciide_apollo_reg.h
index f901a52c1a6a..4191d2a06367 100644
--- a/sys/dev/pci/pciide_apollo_reg.h
+++ b/sys/dev/pci/pciide_apollo_reg.h
@@ -92,6 +92,7 @@
#define APO_AMD_REGBASE 0x40
#define APO_NVIDIA_REGBASE 0x50
#define APO_VIA_VT6421_REGBASE 0xa0
+#define APO_VIA_CX700_REGBASE 0xc0
/* misc. configuration registers */
#define APO_IDECONF(sc) ((sc)->sc_apo_regbase + 0x00)
diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h
index 43d62443e27d..19785e680793 100644
--- a/sys/dev/pci/pciidevar.h
+++ b/sys/dev/pci/pciidevar.h
@@ -180,6 +180,7 @@ struct pciide_product_desc {
/* Flags for ide_flags */
#define IDE_16BIT_IOSPACE 0x0002 /* I/O space BARS ignore upper word */
#define IDE_SHARED_CHANNELS 0x0004 /* channels are not independent */
+#define HAS_PATA_CHANNEL 0x0006 /* one SATA/one PATA channel */
/* inlines for reading/writing 8-bit PCI registers */
diff --git a/sys/dev/pci/viaide.c b/sys/dev/pci/viaide.c
index 39172665956a..b885ef808c36 100644
--- a/sys/dev/pci/viaide.c
+++ b/sys/dev/pci/viaide.c
@@ -300,9 +300,9 @@ static const struct pciide_product_desc pciide_via_products[] = {
via_chip_map,
},
{ PCI_PRODUCT_VIATECH_CX700_IDE,
- 0,
+ HAS_PATA_CHANNEL,
NULL,
- via_sata_chip_map_new,
+ via_sata_chip_map_7,
},
{ PCI_PRODUCT_VIATECH_CX700M2_IDE,
0,
@@ -891,6 +891,13 @@ via_setup_channel(struct ata_channel *chp)
pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA(sc))), DEBUG_PROBE);
}
+static void via_sata_pata_setup_channel(struct ata_channel *chp) {
+ if (chp->ch_channel == 0)
+ sata_setup_channel(chp);
+ else
+ via_setup_channel(chp);
+}
+
static int
via_sata_chip_map_common(struct pciide_softc *sc,
const struct pci_attach_args *cpa)
@@ -920,7 +927,12 @@ via_sata_chip_map_common(struct pciide_softc *sc,
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
- sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel;
+ if (sc->sc_pp->ide_flags & HAS_PATA_CHANNEL) {
+ sc->sc_wdcdev.sc_atac.atac_set_modes = via_sata_pata_setup_channel;
+ sc->sc_apo_regbase = APO_VIA_CX700_REGBASE;
+ }
+ else
+ sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel;
sc->sc_wdcdev.wdc_maxdrives = 2;
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
@@ -928,6 +940,9 @@ via_sata_chip_map_common(struct pciide_softc *sc,
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_RAID;
wdc_allocate_regs(&sc->sc_wdcdev);
+ if (sc->sc_pp->ide_flags & HAS_PATA_CHANNEL) {
+ return 1;
+ }
maptype = pci_mapreg_type(pa->pa_pc, pa->pa_tag,
PCI_MAPREG_START + 0x14);
switch(maptype) {
@@ -991,8 +1006,11 @@ via_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa,
PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
}
- sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
- sc->sc_wdcdev.wdc_maxdrives = 1;
+ if ((sc->sc_pp->ide_flags & HAS_PATA_CHANNEL) == 0) {
+ sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
+ }
+
for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels;
channel++) {
cp = &sc->pciide_channels[channel];
@@ -1000,6 +1018,12 @@ via_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa,
continue;
wdc_cp = &cp->ata_channel;
wdr = CHAN_TO_WDC_REGS(wdc_cp);
+ if (sc->sc_pp->ide_flags & HAS_PATA_CHANNEL) {
+ if (channel == 1) {
+ via_mapchan(pa, cp, interface, pciide_pci_intr);
+ continue;
+ }
+ }
wdr->sata_iot = sc->sc_ba5_st;
wdr->sata_baseioh = sc->sc_ba5_sh;
if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh,
From e1ea779ac2b75db50581fc7eef3d4f55e8193851 Mon Sep 17 00:00:00 2001
From: Andrius V <vezhlys%netscape.net@localhost>
Date: Fri, 21 Feb 2025 01:23:44 +0200
Subject: [PATCH 2/2] identify CX700/VX800 IDE controllers by PCI ID only. Add
descriptions for them (and VX900) and use fallthrough to set udma_cap as a
result.
---
sys/dev/pci/pciidevar.h | 10 +++++++++-
sys/dev/pci/viaide.c | 21 ++++++---------------
2 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h
index 19785e680793..80a7088d140e 100644
--- a/sys/dev/pci/pciidevar.h
+++ b/sys/dev/pci/pciidevar.h
@@ -180,7 +180,15 @@ struct pciide_product_desc {
/* Flags for ide_flags */
#define IDE_16BIT_IOSPACE 0x0002 /* I/O space BARS ignore upper word */
#define IDE_SHARED_CHANNELS 0x0004 /* channels are not independent */
-#define HAS_PATA_CHANNEL 0x0006 /* one SATA/one PATA channel */
+/*
+ * VIA CX700(M/M2)/VX700/VX800 has one SATA and one PATA channel sharing
+ * the same PCI ID. In RAID mode, channels must be configured based on their
+ * respective interfaces.
+ *
+ * For details, refer to VX800 / VX820 Series System Programming Manual
+ * https://bitsavers.trailing-edge.com/components/viaTechnologies/VX800_VX820_Series_System_Programming_Manual_Rev_.95_200806.pdf
+ */
+#define HAS_PATA_CHANNEL 0x0006
/* inlines for reading/writing 8-bit PCI registers */
diff --git a/sys/dev/pci/viaide.c b/sys/dev/pci/viaide.c
index b885ef808c36..f1fd00136b9a 100644
--- a/sys/dev/pci/viaide.c
+++ b/sys/dev/pci/viaide.c
@@ -301,17 +301,17 @@ static const struct pciide_product_desc pciide_via_products[] = {
},
{ PCI_PRODUCT_VIATECH_CX700_IDE,
HAS_PATA_CHANNEL,
- NULL,
+ "VIA Technologies CX700(M2)/VX700/VX800 SATA/IDE RAID Controller",
via_sata_chip_map_7,
},
{ PCI_PRODUCT_VIATECH_CX700M2_IDE,
0,
- NULL,
+ "VIA Technologies CX700(M2)/VX700/VX800 SATA/IDE Controller",
via_chip_map,
},
{ PCI_PRODUCT_VIATECH_VX900_IDE,
0,
- NULL,
+ "VIA Technologies VX900 SATA controller",
via_chip_map,
},
{ PCI_PRODUCT_VIATECH_VT6410_RAID,
@@ -484,11 +484,10 @@ via_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
break;
case PCI_PRODUCT_VIATECH_VT8261_SATA:
- sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
- break;
+ /* FALLTHROUGH */
+ case PCI_PRODUCT_VIATECH_CX700M2_IDE:
+ /* FALLTHROUGH */
case PCI_PRODUCT_VIATECH_VX900_IDE:
- aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
- "VIA Technologies VX900 ATA133 controller\n");
sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
break;
default:
@@ -556,10 +555,6 @@ via_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
aprint_normal("VT8237A ATA133 controller\n");
sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
break;
- case PCI_PRODUCT_VIATECH_CX700:
- aprint_normal("CX700 ATA133 controller\n");
- sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
- break;
case PCI_PRODUCT_VIATECH_VT8251:
aprint_normal("VT8251 ATA133 controller\n");
sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
@@ -568,10 +563,6 @@ via_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
aprint_normal("VT8261 ATA133 controller\n");
sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
break;
- case PCI_PRODUCT_VIATECH_VX800:
- aprint_normal("VX800 ATA133 controller\n");
- sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
- break;
case PCI_PRODUCT_VIATECH_VX855:
aprint_normal("VX855 ATA133 controller\n");
sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
Home |
Main Index |
Thread Index |
Old Index