tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
viaide at cardbus (VT6421A)
Hi,
I would like to request a review of the attached viaide at cardbus patch.
It is also available at:
https://patch-diff.githubusercontent.com/raw/vezhlys/netbsd-src/pull/7.diff
It supports the VT6421A controller only, which I believe is the only
chip that was used in cardbus devices supported by viaide(4) driver.
Initially, I didn't expect to work on this due to low practical need,
but incidentally it appeared that my SATA cardbus controller had a VIA
controller.
After several sessions, I made a PoC by faking a "pci attachment".
Once it worked, I was motivated enough to implement a proper solution.
Creating an actual patch with cardbus glue was a bit more daunting:
* I moved the VT6421 non-pci specific code to sys/dev/ic/vt6421.c
(mainly from via_sata_chip_map_new).
* PCI and cardbus has their
pci/Cardbus_mapreg_map/conf_read/conf_write/intr_establish functions
calls in their respective pci and cardbus driver.
ic/vt6421.c code uses these pre-set values by the corresponding bus
attachment to set up.
The logic for PCI should not have changed. The cardbus driver just
adds its own code for establishing interrupts, mapping registers, and
other bus-specific setup.
Tested on both cardbus and PCI (detection, mounting, format, writing
files, suspend/resume device, smartctl etc).
parts of dmesg:
...
cbb0 at pci0 dev 8 function 0: Ricoh 5C475 PCI-CardBus Bridge (rev. 0x81)
...
cbb0: osock_ctrl 0x400 sock_ctrl 0x400
cbb0: wait took 0.040026s
cbb0: cacheline 0x0 lattimer 0x20
cbb0: bhlc 0x22000
allocated pic ioapic0 type level pin 16 level 6 to cpu0 slot 9 idt entry 104
cbb0: interrupting at ioapic0 pin 16
cardslot0 at cbb0
cardbus0 at cardslot0: bus 2 cacheline 0x0, lattimer 0x20
pcmcia0 at cardslot0
...
cbb0: wait took 0.031570s
cb_reset: enter bcr 7e3010a
cb_reset: wrote bcr 7e3010a
cb_reset: wrote bcr 7a3010a
cb_reset: end of delay
cardbus0: id reg valid in 0 iterations
viaide2 at cardbus0 function 0: VIA Technologies VT6421 Serial ATA Controller
viaide2: bus-master DMA support present
atabus3 at viaide2 channel 0
atabus4 at viaide2 channel 1
atabus5 at viaide2 channel 2
waiting for devices: atabus1 atabus2 atabus3 atabus4 atabus5
wd0 at atabus1 drive 0
...
waiting for devices: atabus4 atabus5
wd1 at atabus4 drive 0
wd1: <Patriot P220 128GB>
wd1: drive supports 16-sector PIO transfers, LBA48 addressing
wd1: 119 GB, 248085 cyl, 16 head, 63 sec, 512 bytes/sect x 250069680 sectors
waiting for devices: atabus4 atabus5
wd1: 32-bit data port
wd1: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 6
(Ultra/133), WRITE DMA FUA, NCQ (32 tags)
wd1(viaide2:1:0): using PIO mode 4, Ultra-DMA mode 6 (Ultra/133)
(using DMA), WRITE DMA FUA EXT
Regards,
Andrius V
diff --git a/share/man/man4/viaide.4 b/share/man/man4/viaide.4
index dffa278d86f4..d47bec71a407 100644
--- a/share/man/man4/viaide.4
+++ b/share/man/man4/viaide.4
@@ -30,6 +30,7 @@
.Nd AMD, NVIDIA and VIA IDE disk controllers driver
.Sh SYNOPSIS
.Cd "viaide* at pci? dev ? function ? flags 0x0000"
+.Cd "viaide* at cardbus? function ?"
.Cd "options PCIIDE_AMD756_ENABLEDMA"
.Sh DESCRIPTION
The
@@ -61,6 +62,7 @@ problems where the IDE controller is wired up to the system incorrectly.
.Sh SEE ALSO
.Xr ata 4 ,
.Xr atapi 4 ,
+.Xr cardbus 4 ,
.Xr intro 4 ,
.Xr pci 4 ,
.Xr pciide 4 ,
diff --git a/sys/arch/amd64/conf/ALL b/sys/arch/amd64/conf/ALL
index 6e3b7f30c042..ca4b6189d58a 100644
--- a/sys/arch/amd64/conf/ALL
+++ b/sys/arch/amd64/conf/ALL
@@ -917,6 +917,7 @@ wdc* at pcmcia? function ?
# CardBus IDE controllers
njata* at cardbus? function ? flags 0x01 # Workbit NinjaATA-32
siisata* at cardbus? function ? # SiI SteelVine controllers
+viaide* at cardbus? function ? # VIA VT6421 controller
# ISA ST506, ESDI, and IDE controllers
# Use flags 0x01 if you want to try to use 32bits data I/O (the driver will
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 04e3aa3cf8c7..6c66a73fc3d7 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -760,6 +760,7 @@ wdc* at pcmcia? function ?
# CardBus IDE controllers
njata* at cardbus? function ? flags 0x01 # Workbit NinjaATA-32
siisata* at cardbus? function ? # SiI SteelVine controllers
+viaide* at cardbus? function ? # VIA VT6421 controller
# ISA ST506, ESDI, and IDE controllers
# Use flags 0x01 if you want to try to use 32bits data I/O (the driver will
diff --git a/sys/arch/i386/conf/ALL b/sys/arch/i386/conf/ALL
index 70d9a3643619..c30bab800c63 100644
--- a/sys/arch/i386/conf/ALL
+++ b/sys/arch/i386/conf/ALL
@@ -1000,6 +1000,7 @@ wdc* at pcmcia? function ?
# CardBus IDE controllers
njata* at cardbus? function ? flags 0x01 # Workbit NinjaATA-32
siisata* at cardbus? function ? # SiI SteelVine controllers
+viaide* at cardbus? function ? # VIA VT6421 controller
# ISA ST506, ESDI, and IDE controllers
# Use flags 0x01 if you want to try to use 32bits data I/O (the driver will
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index 34142aff3b5e..1f7a771859b8 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -906,6 +906,7 @@ wdc* at pcmcia? function ?
# CardBus IDE controllers
njata* at cardbus? function ? flags 0x01 # Workbit NinjaATA-32
siisata* at cardbus? function ? # SiI SteelVine controllers
+viaide* at cardbus? function ? # VIA VT6421 controller
# ISA ST506, ESDI, and IDE controllers
# Use flags 0x01 if you want to try to use 32bits data I/O (the driver will
diff --git a/sys/dev/cardbus/files.cardbus b/sys/dev/cardbus/files.cardbus
index babcaa7ad087..cf4f73c75ae3 100644
--- a/sys/dev/cardbus/files.cardbus
+++ b/sys/dev/cardbus/files.cardbus
@@ -150,6 +150,11 @@ file dev/cardbus/njata_cardbus.c njata_cardbus
attach siisata at cardbus with siisata_cardbus
file dev/cardbus/siisata_cardbus.c siisata_cardbus
+# VIA VT6421A SATA controllers
+#
+attach viaide at cardbus with viaide_cardbus
+file dev/cardbus/viaide_cardbus.c viaide_cardbus
+
#
# SD Host Controller
#
diff --git a/sys/dev/cardbus/viaide_cardbus.c b/sys/dev/cardbus/viaide_cardbus.c
new file mode 100644
index 000000000000..cfdb41ad3b83
--- /dev/null
+++ b/sys/dev/cardbus/viaide_cardbus.c
@@ -0,0 +1,248 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <dev/cardbus/cardbusvar.h>
+
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pciide_apollo_reg.h>
+#include <dev/pci/pciidereg.h>
+#include <dev/pci/pciidevar.h>
+
+#include <dev/ic/vt6421var.h>
+
+struct viaide_cardbus_softc {
+ struct pciide_softc csc_sc;
+ cardbus_chipset_tag_t csc_cc;
+ cardbus_function_tag_t csc_cf;
+ cardbus_devfunc_t csc_ct;
+ pcitag_t csc_tag;
+ bus_space_tag_t csc_iot; /* CardBus I/O space tag */
+ bus_space_tag_t csc_memt; /* CardBus MEM space tag */
+ rbus_tag_t csc_rbus_iot; /* CardBus i/o rbus tag */
+ rbus_tag_t csc_rbus_memt; /* CardBus mem rbus tag */
+ void *csc_ih;
+};
+
+static int viaide_cardbus_match(device_t, cfdata_t, void *);
+static void viaide_cardbus_attach(device_t, device_t, void *);
+static int viaide_cardbus_detach(device_t, int);
+static bool viaide_cardbus_suspend(device_t, const pmf_qual_t *);
+static bool viaide_cardbus_resume(device_t, const pmf_qual_t *);
+void via_sata_chip_map_new(struct pciide_softc *sc, const struct pci_attach_args *pa);
+
+static const struct viaide_cardbus_product {
+
+ uint32_t ide_product;
+ const char *ide_name;
+} viaide_cardbus_products[] = {
+ { PCI_PRODUCT_VIATECH_VT6421_RAID,
+ "VIA Technologies VT6421 Serial ATA Controller"
+ },
+ { 0,
+ NULL
+ },
+};
+
+CFATTACH_DECL_NEW(viaide_cardbus, sizeof(struct viaide_cardbus_softc),
+ viaide_cardbus_match, viaide_cardbus_attach, viaide_cardbus_detach,
+ NULL);
+
+static const struct viaide_cardbus_product *
+viaide_cardbus_lookup(const struct cardbus_attach_args *ca)
+{
+ const struct viaide_cardbus_product *vcp;
+
+ for (vcp = viaide_cardbus_products; vcp->ide_product != 0; vcp++) {
+ if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_VIATECH &&
+ PCI_PRODUCT(ca->ca_id) == vcp->ide_product)
+ return vcp;
+ }
+
+ return NULL;
+}
+
+static int
+viaide_cardbus_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct cardbus_attach_args *ca = aux;
+
+ if (viaide_cardbus_lookup(ca) != NULL)
+ return 2;
+
+ return 0;
+}
+
+static void
+viaide_cardbus_attach(device_t parent, device_t self, void *aux)
+{
+ const struct cardbus_attach_args *ca = aux;
+ const struct viaide_cardbus_product *vcp;
+ struct viaide_cardbus_softc *csc = device_private(self);
+ struct pciide_softc *sc = &csc->csc_sc;
+ cardbus_devfunc_t ct = ca->ca_ct;
+ cardbus_chipset_tag_t cc = ct->ct_cc;
+ cardbus_function_tag_t cf = ct->ct_cf;
+ pcireg_t reg;
+ struct vt6421_chan_handler chan_handlers[VT6421_NCHANNELS];
+ struct vt6421_chan_handler *vch;
+ int csr, channel;
+
+ vcp = viaide_cardbus_lookup(ca);
+
+ aprint_naive(": SATA HBA\n");
+ aprint_normal(": %s\n", vcp->ide_name);
+
+ /* Map I/O registers */
+ csc->csc_sc.sc_dma_ok = (Cardbus_mapreg_map(ct, PCIIDE_REG_BUS_MASTER_DMA,
+ PCI_MAPREG_TYPE_IO, 0, &sc->sc_dma_iot, &sc->sc_dma_ioh, NULL,
+ &sc->sc_dma_ios) == 0);
+
+ sc->sc_wdcdev.sc_atac.atac_dev = self;
+ aprint_verbose_dev(self, "bus-master DMA support present");
+ vt6421_mapreg_dma(sc, ca->ca_dmat);
+ aprint_verbose("\n");
+
+ if (Cardbus_mapreg_map(ct, PCI_BAR5, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_ba5_st, &sc->sc_ba5_sh, NULL, &sc->sc_ba5_ss)) {
+ aprint_error_dev(self, "couldn't map SATA regs\n");
+ return;
+ }
+
+ csc->csc_cc = cc;
+ csc->csc_cf = cf;
+ csc->csc_ct = ct;
+ csc->csc_tag = ca->ca_tag;
+
+#if NATA_DMA
+ /* Set up DMA defaults; these might be adjusted by chip_map. */
+ sc->sc_dma_maxsegsz = IDEDMA_BYTE_COUNT_MAX;
+ sc->sc_dma_boundary = IDEDMA_BYTE_COUNT_ALIGN;
+#endif
+
+ /*
+ * Map the device.
+ */
+ csr = PCI_COMMAND_MASTER_ENABLE;
+
+ /* Enable the appropriate bits in the PCI CSR. */
+ reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG);
+ csr |= PCI_COMMAND_IO_ENABLE;
+ csr |= PCI_COMMAND_MEM_ENABLE;
+ reg |= csr;
+ Cardbus_conf_write(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg);
+
+ csc->csc_iot = ca->ca_iot;
+ csc->csc_memt = ca->ca_memt;
+ csc->csc_rbus_iot = ca->ca_rbus_iot;
+ csc->csc_rbus_memt = ca->ca_rbus_memt;
+ csc->csc_tag = ca->ca_tag;
+
+ csc->csc_ih = Cardbus_intr_establish(ct, IPL_BIO, pciide_pci_intr, sc);
+
+ for (channel = 0; channel < VT6421_NCHANNELS; channel++) {
+ vch = &chan_handlers[channel];
+ if (Cardbus_mapreg_map(ct, PCI_BAR(channel), PCI_MAPREG_TYPE_IO, 0,
+ &vch->sc_cmd_st, &vch->sc_cmd_sh, NULL, &vch->sc_cmd_ios) != 0)
+ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't map channel %d regs\n", channel);
+ }
+
+ vt6421_chip_map(sc, chan_handlers);
+
+ if (!pmf_device_register(self, viaide_cardbus_suspend, viaide_cardbus_resume))
+ aprint_error_dev(self, "couldn't establish power handler\n");
+}
+
+static int
+viaide_cardbus_detach(device_t self, int flags)
+{
+ struct viaide_cardbus_softc *csc = device_private(self);
+ struct pciide_softc *sc = &csc->csc_sc;
+ struct cardbus_devfunc *ct = csc->csc_ct;
+ int rv;
+
+ pmf_device_deregister(self);
+ rv = pciide_common_detach(sc, flags);
+ if (rv)
+ return (rv);
+ if (csc->csc_ih != NULL) {
+ Cardbus_intr_disestablish(ct, csc->csc_ih);
+ csc->csc_ih = NULL;
+ }
+
+ return 0;
+}
+
+static bool
+viaide_cardbus_suspend(device_t dv, const pmf_qual_t *qual)
+{
+ struct viaide_cardbus_softc *csc = device_private(dv);
+ struct pciide_softc *sc = &csc->csc_sc;
+ struct cardbus_devfunc *ct = csc->csc_ct;
+ int s;
+
+ s = splvm();
+
+ sc->sc_pm_reg[0] = Cardbus_conf_read(ct, csc->csc_tag, APO_IDECONF(sc));
+ /* APO_DATATIM(sc) includes APO_UDMA(sc) */
+ sc->sc_pm_reg[1] = Cardbus_conf_read(ct, csc->csc_tag, APO_DATATIM(sc));
+ sc->sc_pm_reg[2] = Cardbus_conf_read(ct, csc->csc_tag, APO_CTLMISC(sc));
+ sc->sc_pm_reg[3] = Cardbus_conf_read(ct, csc->csc_tag, APO_MISCTIM(sc));
+
+ splx(s);
+
+ return true;
+}
+
+static bool
+viaide_cardbus_resume(device_t dv, const pmf_qual_t *qual)
+{
+ struct viaide_cardbus_softc *csc = device_private(dv);
+ struct pciide_softc *sc = &csc->csc_sc;
+ struct cardbus_devfunc *ct = csc->csc_ct;
+ int s;
+
+ s = splvm();
+
+ Cardbus_conf_write(ct, csc->csc_tag, APO_IDECONF(sc), sc->sc_pm_reg[0]);
+ Cardbus_conf_write(ct, csc->csc_tag, APO_DATATIM(sc), sc->sc_pm_reg[1]);
+ Cardbus_conf_write(ct, csc->csc_tag, APO_CTLMISC(sc), sc->sc_pm_reg[2]);
+ Cardbus_conf_write(ct, csc->csc_tag, APO_MISCTIM(sc), sc->sc_pm_reg[3]);
+
+ splx(s);
+
+ return true;
+}
diff --git a/sys/dev/ic/vt6421.c b/sys/dev/ic/vt6421.c
new file mode 100644
index 000000000000..52d203d09523
--- /dev/null
+++ b/sys/dev/ic/vt6421.c
@@ -0,0 +1,191 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ #include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciidereg.h>
+#include <dev/pci/pciidevar.h>
+#include <dev/pci/pciide_apollo_reg.h>
+
+#include "vt6421var.h"
+
+void
+vt6421_mapreg_dma(struct pciide_softc *sc, bus_dma_tag_t sc_dmat)
+{
+ struct pciide_channel *pc;
+ int chan, reg;
+ bus_size_t size;
+
+ sc->sc_dmat = sc_dmat;
+ if (sc->sc_dma_ok == 0) {
+ aprint_verbose(", but unused (couldn't map registers)");
+ } else {
+ sc->sc_wdcdev.dma_arg = sc;
+ sc->sc_wdcdev.dma_init = pciide_dma_init;
+ sc->sc_wdcdev.dma_start = pciide_dma_start;
+ sc->sc_wdcdev.dma_finish = pciide_dma_finish;
+ }
+
+ if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags &
+ PCIIDE_OPTIONS_NODMA) {
+ aprint_verbose(
+ ", but unused (forced off by config file)");
+ sc->sc_dma_ok = 0;
+ }
+
+ if (sc->sc_dma_ok == 0)
+ return;
+
+ for (chan = 0; chan < 4; chan++) {
+ pc = &sc->pciide_channels[chan];
+ for (reg = 0; reg < IDEDMA_NREGS; reg++) {
+ size = 4;
+ if (size > (IDEDMA_SCH_OFFSET - reg))
+ size = IDEDMA_SCH_OFFSET - reg;
+ if (bus_space_subregion(sc->sc_dma_iot, sc->sc_dma_ioh,
+ IDEDMA_SCH_OFFSET * chan + reg, size,
+ &pc->dma_iohs[reg]) != 0) {
+ sc->sc_dma_ok = 0;
+ aprint_verbose(", but can't subregion offset "
+ "%d size %lu",
+ reg, (u_long)size);
+ return;
+ }
+ }
+ }
+}
+
+static int
+via_vt6421_chansetup(struct pciide_softc *sc, int channel)
+{
+ struct pciide_channel *cp = &sc->pciide_channels[channel];
+
+ sc->wdc_chanarray[channel] = &cp->ata_channel;
+
+ cp->ata_channel.ch_channel = channel;
+ cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
+
+ return 1;
+}
+
+void
+vt6421_chip_map(struct pciide_softc *sc, struct vt6421_chan_handler *chan_handler)
+{
+ struct pciide_channel *cp;
+ struct ata_channel *wdc_cp;
+ struct wdc_regs *wdr;
+ int channel;
+ int i;
+
+ sc->sc_apo_regbase = APO_VIA_VT6421_REGBASE;
+
+ sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
+ sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
+ if (sc->sc_dma_ok) {
+ sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA;
+ sc->sc_wdcdev.irqack = pciide_irqack;
+ sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
+ sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
+ }
+ sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel;
+
+ sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
+ sc->sc_wdcdev.sc_atac.atac_nchannels = VT6421_NCHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
+
+ wdc_allocate_regs(&sc->sc_wdcdev);
+
+ for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels;
+ channel++) {
+ cp = &sc->pciide_channels[channel];
+ if (via_vt6421_chansetup(sc, channel) == 0)
+ continue;
+ wdc_cp = &cp->ata_channel;
+ wdr = CHAN_TO_WDC_REGS(wdc_cp);
+
+ 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 << 6) + 0x0, 4,
+ &wdr->sata_status) != 0) {
+ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't map channel %d sata_status regs\n",
+ wdc_cp->ch_channel);
+ continue;
+ }
+ if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh,
+ (wdc_cp->ch_channel << 6) + 0x4, 4,
+ &wdr->sata_error) != 0) {
+ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't map channel %d sata_error regs\n",
+ wdc_cp->ch_channel);
+ continue;
+ }
+ if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh,
+ (wdc_cp->ch_channel << 6) + 0x8, 4,
+ &wdr->sata_control) != 0) {
+ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't map channel %d sata_control regs\n",
+ wdc_cp->ch_channel);
+ continue;
+ }
+
+
+ wdr->cmd_iot = chan_handler[channel].sc_cmd_st;
+ wdr->cmd_baseioh = chan_handler[channel].sc_cmd_sh;
+ wdr->cmd_ios = chan_handler[channel].sc_cmd_ios;
+
+ wdr->ctl_iot = wdr->cmd_iot;
+ for (i = 0; i < WDC_NREG; i++) {
+ if (bus_space_subregion(wdr->cmd_iot,
+ wdr->cmd_baseioh, i, i == 0 ? 4 : 1,
+ &wdr->cmd_iohs[i]) != 0) {
+ aprint_error_dev(
+ sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't subregion channel %d "
+ "cmd regs\n", channel);
+ return;
+ }
+ }
+ if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh,
+ WDC_NREG + 2, 1, &wdr->ctl_ioh) != 0) {
+ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't map channel %d ctl regs\n", channel);
+ return;
+ }
+ wdc_init_shadow_regs(wdr);
+ wdr->data32iot = wdr->cmd_iot;
+ wdr->data32ioh = wdr->cmd_iohs[wd_data];
+ wdcattach(wdc_cp);
+ }
+}
\ No newline at end of file
diff --git a/sys/dev/ic/vt6421var.h b/sys/dev/ic/vt6421var.h
new file mode 100644
index 000000000000..f33bd0523a6e
--- /dev/null
+++ b/sys/dev/ic/vt6421var.h
@@ -0,0 +1,46 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IC_VT6421_H_
+#define _IC_VT6421_H_
+
+#include <dev/pci/pciidevar.h>
+
+#define VT6421_NCHANNELS 3
+
+struct vt6421_chan_handler {
+ bus_space_tag_t sc_cmd_st;
+ bus_space_handle_t sc_cmd_sh;
+ bus_size_t sc_cmd_ios;
+};
+
+void vt6421_mapreg_dma(struct pciide_softc *, bus_dma_tag_t);
+
+void vt6421_chip_map(struct pciide_softc *, struct vt6421_chan_handler *);
+
+#endif
\ No newline at end of file
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index d098b5c04783..e7e2cf1fb2ab 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -355,6 +355,7 @@ file dev/pci/slide.c slide
device viaide: ata, ata_dma, ata_udma, pciide_common, wdc_common, sata
attach viaide at pci
file dev/pci/viaide.c viaide
+file dev/ic/vt6421.c viaide
# STMicroelectronics STPC IDE controllers
device stpcide: ata, ata_dma, ata_udma, pciide_common, wdc_common
diff --git a/sys/dev/pci/viaide.c b/sys/dev/pci/viaide.c
index d5e0ccd4b95e..974ae5871696 100644
--- a/sys/dev/pci/viaide.c
+++ b/sys/dev/pci/viaide.c
@@ -37,6 +37,8 @@ __KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.108 2026/07/06 17:40:42 andvar Exp $");
#include <dev/pci/pciidevar.h>
#include <dev/pci/pciide_apollo_reg.h>
+#include <dev/ic/vt6421var.h>
+
static int via_pcib_match(const struct pci_attach_args *);
static void via_chip_map(struct pciide_softc *,
const struct pci_attach_args *);
@@ -1130,80 +1132,16 @@ via_sata_chip_map_7(struct pciide_softc *sc, const struct pci_attach_args *pa)
via_sata_chip_map(sc, pa, 7);
}
-static void
-via_vt6421_mapreg_dma(struct pciide_softc *sc, const struct pci_attach_args *pa)
-{
- struct pciide_channel *pc;
- int chan, reg;
- bus_size_t size;
-
- sc->sc_dma_ok = (pci_mapreg_map(pa, PCIIDE_REG_BUS_MASTER_DMA,
- PCI_MAPREG_TYPE_IO, 0, &sc->sc_dma_iot, &sc->sc_dma_ioh,
- NULL, &sc->sc_dma_ios) == 0);
- sc->sc_dmat = pa->pa_dmat;
- if (sc->sc_dma_ok == 0) {
- aprint_verbose(", but unused (couldn't map registers)");
- } else {
- sc->sc_wdcdev.dma_arg = sc;
- sc->sc_wdcdev.dma_init = pciide_dma_init;
- sc->sc_wdcdev.dma_start = pciide_dma_start;
- sc->sc_wdcdev.dma_finish = pciide_dma_finish;
- }
-
- if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags &
- PCIIDE_OPTIONS_NODMA) {
- aprint_verbose(
- ", but unused (forced off by config file)");
- sc->sc_dma_ok = 0;
- }
-
- if (sc->sc_dma_ok == 0)
- return;
-
- for (chan = 0; chan < 4; chan++) {
- pc = &sc->pciide_channels[chan];
- for (reg = 0; reg < IDEDMA_NREGS; reg++) {
- size = 4;
- if (size > (IDEDMA_SCH_OFFSET - reg))
- size = IDEDMA_SCH_OFFSET - reg;
- if (bus_space_subregion(sc->sc_dma_iot, sc->sc_dma_ioh,
- IDEDMA_SCH_OFFSET * chan + reg, size,
- &pc->dma_iohs[reg]) != 0) {
- sc->sc_dma_ok = 0;
- aprint_verbose(", but can't subregion offset "
- "%d size %lu",
- reg, (u_long)size);
- return;
- }
- }
- }
-}
-
-static int
-via_vt6421_chansetup(struct pciide_softc *sc, int channel)
-{
- struct pciide_channel *cp = &sc->pciide_channels[channel];
-
- sc->wdc_chanarray[channel] = &cp->ata_channel;
-
- cp->ata_channel.ch_channel = channel;
- cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
-
- return 1;
-}
-
static void
via_sata_chip_map_new(struct pciide_softc *sc,
const struct pci_attach_args *pa)
{
- struct pciide_channel *cp;
- struct ata_channel *wdc_cp;
- struct wdc_regs *wdr;
int channel;
pci_intr_handle_t intrhandle;
const char *intrstr;
- int i;
char intrbuf[PCI_INTRSTR_LEN];
+ struct vt6421_chan_handler chan_handlers[VT6421_NCHANNELS];
+ struct vt6421_chan_handler *vch;
if (pciide_chipen(sc, pa) == 0)
return;
@@ -1216,31 +1154,15 @@ via_sata_chip_map_new(struct pciide_softc *sc,
"couldn't map SATA regs\n");
}
+ sc->sc_dma_ok = (pci_mapreg_map(pa, PCIIDE_REG_BUS_MASTER_DMA,
+ PCI_MAPREG_TYPE_IO, 0, &sc->sc_dma_iot, &sc->sc_dma_ioh,
+ NULL, &sc->sc_dma_ios) == 0);
+
aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev,
"bus-master DMA support present");
- via_vt6421_mapreg_dma(sc, pa);
+ vt6421_mapreg_dma(sc, pa->pa_dmat);
aprint_verbose("\n");
-
- sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
- sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
- if (sc->sc_dma_ok) {
- sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA;
- sc->sc_wdcdev.irqack = pciide_irqack;
- sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
- sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
- }
- sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel;
-
- sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
- sc->sc_wdcdev.sc_atac.atac_nchannels = 3;
- sc->sc_wdcdev.wdc_maxdrives = 2;
-
- if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
- PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID)
- sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_RAID;
-
- wdc_allocate_regs(&sc->sc_wdcdev);
-
+
if (pci_intr_map(pa, &intrhandle) != 0) {
aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
"couldn't map native-PCI interrupt\n");
@@ -1258,72 +1180,17 @@ via_sata_chip_map_new(struct pciide_softc *sc,
aprint_error("\n");
return;
}
- aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
- "using %s for native-PCI interrupt\n",
- intrstr ? intrstr : "unknown interrupt");
-
- for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels;
- channel++) {
- cp = &sc->pciide_channels[channel];
- if (via_vt6421_chansetup(sc, channel) == 0)
- continue;
- wdc_cp = &cp->ata_channel;
- wdr = CHAN_TO_WDC_REGS(wdc_cp);
-
- 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 << 6) + 0x0, 4,
- &wdr->sata_status) != 0) {
- aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
- "couldn't map channel %d sata_status regs\n",
- wdc_cp->ch_channel);
- continue;
- }
- if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh,
- (wdc_cp->ch_channel << 6) + 0x4, 4,
- &wdr->sata_error) != 0) {
- aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
- "couldn't map channel %d sata_error regs\n",
- wdc_cp->ch_channel);
- continue;
- }
- if (bus_space_subregion(wdr->sata_iot, wdr->sata_baseioh,
- (wdc_cp->ch_channel << 6) + 0x8, 4,
- &wdr->sata_control) != 0) {
- aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
- "couldn't map channel %d sata_control regs\n",
- wdc_cp->ch_channel);
- continue;
- }
+
+ if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
+ PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID)
+ sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_RAID;
- if (pci_mapreg_map(pa, PCI_BAR(wdc_cp->ch_channel),
- PCI_MAPREG_TYPE_IO, 0, &wdr->cmd_iot, &wdr->cmd_baseioh,
- NULL, &wdr->cmd_ios) != 0) {
+ for (channel = 0; channel < VT6421_NCHANNELS; channel++) {
+ vch = &chan_handlers[channel];
+ if (pci_mapreg_map(pa, PCI_BAR(channel), PCI_MAPREG_TYPE_IO, 0,
+ &vch->sc_cmd_st, &vch->sc_cmd_sh, NULL, &vch->sc_cmd_ios) != 0)
aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
"couldn't map channel %d regs\n", channel);
- }
- wdr->ctl_iot = wdr->cmd_iot;
- for (i = 0; i < WDC_NREG; i++) {
- if (bus_space_subregion(wdr->cmd_iot,
- wdr->cmd_baseioh, i, i == 0 ? 4 : 1,
- &wdr->cmd_iohs[i]) != 0) {
- aprint_error_dev(
- sc->sc_wdcdev.sc_atac.atac_dev,
- "couldn't subregion channel %d "
- "cmd regs\n", channel);
- return;
- }
- }
- if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh,
- WDC_NREG + 2, 1, &wdr->ctl_ioh) != 0) {
- aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
- "couldn't map channel %d ctl regs\n", channel);
- return;
- }
- wdc_init_shadow_regs(wdr);
- wdr->data32iot = wdr->cmd_iot;
- wdr->data32ioh = wdr->cmd_iohs[wd_data];
- wdcattach(wdc_cp);
}
+ vt6421_chip_map(sc, chan_handlers);
}
Home |
Main Index |
Thread Index |
Old Index