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:
parent
f90ed3540d
commit
c6d327a8be
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue