At least under certain (mis)configurations (e.g. on the "Pegasos" board)

the VT8231-IDE's native mode only works with irq 14/15, and cannot be
programmed to use a single native PCI irq alone. So we install an interrupt
handler for each channel, as in compatibility mode.
This behaviour has to be activated by the "use-compat-native-irq" property,
otherwise the driver works as before.
This commit is contained in:
phx 2007-12-16 16:41:01 +00:00
parent f90ed3540d
commit c6d327a8be
2 changed files with 100 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ofw_autoconf.c,v 1.4 2007/11/26 23:13:37 macallan Exp $ */
/* $NetBSD: ofw_autoconf.c,v 1.5 2007/12/16 16:42:12 phx Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ofw_autoconf.c,v 1.4 2007/11/26 23:13:37 macallan Exp $");
__KERNEL_RCSID(0, "$NetBSD: ofw_autoconf.c,v 1.5 2007/12/16 16:42:12 phx Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -214,18 +214,29 @@ device_register(dev, aux)
return;
if (device_is_a(device_parent(dev), "pci")) {
/* see if this is going to be console */
struct pci_attach_args *pa = aux;
prop_dictionary_t dict;
prop_bool_t b;
int node;
char name[32];
dict = device_properties(dev);
node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag);
/* enable configuration of irq 14/15 for VIA native IDE */
if (device_is_a(dev, "viaide") &&
strncmp(model_name, "Pegasos", 7) == 0) {
b = prop_bool_create(true);
KASSERT(b != NULL);
(void)prop_dictionary_set(dict,
"use-compat-native-irq", b);
prop_object_release(b);
}
if (node != 0) {
prop_dictionary_set_uint32(dict, "device_node", node);
/* see if this is going to be console */
memset(name, 0, sizeof(name));
OF_getprop(node, "device_type", name, sizeof(name));
if (strcmp(name, "display") == 0) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: viaide.c,v 1.47 2007/11/14 14:46:12 xtraeme Exp $ */
/* $NetBSD: viaide.c,v 1.48 2007/12/16 16:41:01 phx Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.47 2007/11/14 14:46:12 xtraeme Exp $");
__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.48 2007/12/16 16:41:01 phx Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -44,6 +44,11 @@ __KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.47 2007/11/14 14:46:12 xtraeme Exp $");
static int via_pcib_match(struct pci_attach_args *);
static void via_chip_map(struct pciide_softc *, struct pci_attach_args *);
static void via_mapchan(struct pci_attach_args *, struct pciide_channel *,
pcireg_t, bus_size_t *, bus_size_t *, int (*)(void *));
static void vt8231_mapregs_native(struct pci_attach_args *,
struct pciide_channel *, bus_size_t *, bus_size_t *,
int (*)(void *));
static int via_sata_chip_map_common(struct pciide_softc *,
struct pci_attach_args *);
static void via_sata_chip_map(struct pciide_softc *,
@ -559,11 +564,89 @@ unknown:
cp->ata_channel.ch_flags |= ATACH_DISABLED;
continue;
}
pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
via_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
pciide_pci_intr);
}
}
static void
via_mapchan(struct pci_attach_args *pa, struct pciide_channel *cp,
pcireg_t interface, bus_size_t *cmdsizep, bus_size_t *ctlsizep,
int (*pci_intr)(void *))
{
struct ata_channel *wdc_cp;
struct pciide_softc *sc;
prop_bool_t compat_nat_enable;
wdc_cp = &cp->ata_channel;
sc = CHAN_TO_PCIIDE(&cp->ata_channel);
compat_nat_enable = prop_dictionary_get(
device_properties((struct device *)sc), "use-compat-native-irq");
if (interface & PCIIDE_INTERFACE_PCI(wdc_cp->ch_channel)) {
/* native mode with irq 14/15 requested? */
if (compat_nat_enable != NULL &&
prop_bool_true(compat_nat_enable))
vt8231_mapregs_native(pa, cp, cmdsizep, ctlsizep,
pci_intr);
else
pciide_mapregs_native(pa, cp, cmdsizep, ctlsizep,
pci_intr);
} else {
pciide_mapregs_compat(pa, cp, wdc_cp->ch_channel, cmdsizep,
ctlsizep);
if ((cp->ata_channel.ch_flags & ATACH_DISABLED) == 0)
pciide_map_compat_intr(pa, cp, wdc_cp->ch_channel);
}
wdcattach(wdc_cp);
}
/*
* At least under certain (mis)configurations (e.g. on the "Pegasos" board)
* the VT8231-IDE's native mode only works with irq 14/15, and cannot be
* programmed to use a single native PCI irq alone. So we install an interrupt
* handler for each channel, as in compatibility mode.
*/
static void
vt8231_mapregs_native(struct pci_attach_args *pa, struct pciide_channel *cp,
bus_size_t *cmdsizep, bus_size_t *ctlsizep, int (*pci_intr)(void *))
{
struct ata_channel *wdc_cp;
struct pciide_softc *sc;
pci_intr_handle_t intrhandle;
const char *intrstr;
wdc_cp = &cp->ata_channel;
sc = CHAN_TO_PCIIDE(&cp->ata_channel);
/* XXX prevent pciide_mapregs_native from installing a handler */
if (sc->sc_pci_ih == NULL)
sc->sc_pci_ih = (void *)~0;
pciide_mapregs_native(pa, cp, cmdsizep, ctlsizep, pci_intr);
/* interrupts are fixed to 14/15, as in compatibility mode */
intrhandle = PCIIDE_COMPAT_IRQ(wdc_cp->ch_channel);
intrstr = pci_intr_string(pa->pa_pc, intrhandle);
sc->sc_pci_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO,
pci_intr, sc);
if (sc->sc_pci_ih != NULL) {
aprint_normal("%s: %s channel interrupting at %s\n",
sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, cp->name,
intrstr ? intrstr : "unknown interrupt");
} else {
aprint_error("%s: couldn't establish native-PCI interrupt",
sc->sc_wdcdev.sc_atac.atac_dev.dv_xname);
if (intrstr != NULL)
aprint_normal(" at %s", intrstr);
aprint_normal("\n");
return;
}
/* interrupt handler for this channel */
cp->ih = sc->sc_pci_ih;
}
static void
via_setup_channel(struct ata_channel *chp)
{