tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: viaide at cardbus (VT6421A)
Hi,
Since the last email, I made some changes, mainly adding additional
unmapping on detach and a few cleanups.
I am not sure whether more diligent unmapping should be implemented in
the failure path of the attach process.
But otherwise, I didn't touch code for a while and consider myself
ready for the initial commit.
Still waiting for comments (or maybe opinions weather it should be
committed at all).
Thanks!
Regards,
Andrius V
On Wed, Sep 9, 2026 at 8:54 AM Andrius V <vezhlys%gmail.com@localhost> wrote:
>
> 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
--- viaideatcardbus.diff 2026-09-09 08:50:31.766545130 +0300
+++ viaideatcardbus2.diff 2026-09-14 13:05:47.571326243 +0300
@@ -84,10 +84,10 @@ index babcaa7ad087..cf4f73c75ae3 100644
#
diff --git a/sys/dev/cardbus/viaide_cardbus.c b/sys/dev/cardbus/viaide_cardbus.c
new file mode 100644
-index 000000000000..cfdb41ad3b83
+index 000000000000..5849a6fec565
--- /dev/null
+++ b/sys/dev/cardbus/viaide_cardbus.c
-@@ -0,0 +1,248 @@
+@@ -0,0 +1,263 @@
+/* $NetBSD$ */
+
+/*-
@@ -151,7 +151,6 @@ index 000000000000..cfdb41ad3b83
+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 {
+
@@ -261,6 +260,12 @@ index 000000000000..cfdb41ad3b83
+ csc->csc_tag = ca->ca_tag;
+
+ csc->csc_ih = Cardbus_intr_establish(ct, IPL_BIO, pciide_pci_intr, sc);
++
++ if (csc->csc_ih == NULL) {
++ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
++ "couldn't establish interrupt\n");
++ return;
++ }
+
+ for (channel = 0; channel < VT6421_NCHANNELS; channel++) {
+ vch = &chan_handlers[channel];
@@ -282,9 +287,17 @@ index 000000000000..cfdb41ad3b83
+ struct viaide_cardbus_softc *csc = device_private(self);
+ struct pciide_softc *sc = &csc->csc_sc;
+ struct cardbus_devfunc *ct = csc->csc_ct;
-+ int rv;
++ int rv, channel;
++
++ for (channel = 0; channel < VT6421_NCHANNELS; channel++) {
++ Cardbus_mapreg_unmap(ct, PCI_BAR(channel), sc->sc_ba5_st, sc->sc_ba5_sh,
++ sc->sc_ba5_ss);
++ }
++ Cardbus_mapreg_unmap(ct, PCI_BAR5, sc->sc_ba5_st, sc->sc_ba5_sh,
++ sc->sc_ba5_ss);
++ Cardbus_mapreg_unmap(ct, PCIIDE_REG_BUS_MASTER_DMA, sc->sc_ba5_st, sc->sc_ba5_sh,
++ sc->sc_ba5_ss);
+
-+ pmf_device_deregister(self);
+ rv = pciide_common_detach(sc, flags);
+ if (rv)
+ return (rv);
@@ -293,6 +306,8 @@ index 000000000000..cfdb41ad3b83
+ csc->csc_ih = NULL;
+ }
+
++ pmf_device_deregister(self);
++
+ return 0;
+}
+
@@ -338,7 +353,7 @@ index 000000000000..cfdb41ad3b83
+}
diff --git a/sys/dev/ic/vt6421.c b/sys/dev/ic/vt6421.c
new file mode 100644
-index 000000000000..52d203d09523
+index 000000000000..4da75497fdf2
--- /dev/null
+++ b/sys/dev/ic/vt6421.c
@@ -0,0 +1,191 @@
@@ -370,7 +385,7 @@ index 000000000000..52d203d09523
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
-+ #include <sys/cdefs.h>
++#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
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..5849a6fec565
--- /dev/null
+++ b/sys/dev/cardbus/viaide_cardbus.c
@@ -0,0 +1,263 @@
+/* $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 *);
+
+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);
+
+ if (csc->csc_ih == NULL) {
+ aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+ "couldn't establish interrupt\n");
+ return;
+ }
+
+ 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, channel;
+
+ for (channel = 0; channel < VT6421_NCHANNELS; channel++) {
+ Cardbus_mapreg_unmap(ct, PCI_BAR(channel), sc->sc_ba5_st, sc->sc_ba5_sh,
+ sc->sc_ba5_ss);
+ }
+ Cardbus_mapreg_unmap(ct, PCI_BAR5, sc->sc_ba5_st, sc->sc_ba5_sh,
+ sc->sc_ba5_ss);
+ Cardbus_mapreg_unmap(ct, PCIIDE_REG_BUS_MASTER_DMA, sc->sc_ba5_st, sc->sc_ba5_sh,
+ sc->sc_ba5_ss);
+
+ 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;
+ }
+
+ pmf_device_deregister(self);
+
+ 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..4da75497fdf2
--- /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