2001-11-09 20:19:58 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1999, 2000 Matthew R. Green
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
* Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>
|
2001-11-09 20:19:58 +00:00
|
|
|
* 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.
|
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
|
|
|
*
|
2002-02-13 16:07:59 +00:00
|
|
|
* from: NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp
|
2001-11-09 20:19:58 +00:00
|
|
|
*
|
|
|
|
* $FreeBSD$
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2001-12-21 21:35:47 +00:00
|
|
|
* Support for `psycho' and `psycho+' UPA to PCI bridge and
|
2001-11-09 20:19:58 +00:00
|
|
|
* UltraSPARC IIi and IIe `sabre' PCI controllers.
|
|
|
|
*/
|
|
|
|
|
2004-06-30 23:21:07 +00:00
|
|
|
#define __RMAN_RESOURCE_VISIBLE
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
#include "opt_ofw_pci.h"
|
2001-11-09 20:19:58 +00:00
|
|
|
#include "opt_psycho.h"
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/kernel.h>
|
2004-06-04 11:52:25 +00:00
|
|
|
#include <sys/module.h>
|
2001-11-09 20:19:58 +00:00
|
|
|
#include <sys/malloc.h>
|
2002-12-01 23:30:26 +00:00
|
|
|
#include <sys/pcpu.h>
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2003-08-23 00:11:16 +00:00
|
|
|
#include <dev/ofw/openfirm.h>
|
|
|
|
#include <dev/ofw/ofw_pci.h>
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
#include <machine/bus.h>
|
Further cleanup of the sparc64 busdma implementation:
- Move prototypes for sparc64-specific helper functions from bus.h to
bus_private.h
- Move the method pointers from struct bus_dma_tag into a separate
structure; this saves some memory, and allows to use a single method
table for each busdma backend, so that the bus drivers need no longer
be changed if the methods tables need to be modified.
- Remove the hierarchical tag method lookup. It was never really useful,
since the layering is fixed, and the current implementations do not
need to call into parent implementations anyway. Each tag inherits
its method table pointer and cookie from the parent (or the root tag)
now, and the method wrapper macros directly use the method table
of the tag.
- Add a method table to the non-IOMMU backend, remove unnecessary
prototypes, remove the extra parent tag argument.
- Rename sparc64_dmamem_alloc_map() and sparc64_dmamem_free_map() to
sparc64_dma_alloc_map() and sparc64_dma_free_map(), move them to a
better place and use them for all map allocations and deallocations.
- Add a method table to the iommu backend, and staticize functions,
remove the extra parent tag argument.
- Change the psycho and sbus drivers to just set cookie and method table
in the root tag.
- Miscellaneous small fixes.
2003-06-18 16:41:36 +00:00
|
|
|
#include <machine/bus_private.h>
|
2001-11-09 20:19:58 +00:00
|
|
|
#include <machine/iommureg.h>
|
|
|
|
#include <machine/bus_common.h>
|
|
|
|
#include <machine/frame.h>
|
|
|
|
#include <machine/intr_machdep.h>
|
|
|
|
#include <machine/nexusvar.h>
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
#include <machine/ofw_bus.h>
|
2001-11-09 20:19:58 +00:00
|
|
|
#include <machine/ofw_upa.h>
|
|
|
|
#include <machine/resource.h>
|
|
|
|
|
|
|
|
#include <sys/rman.h>
|
|
|
|
|
|
|
|
#include <machine/iommuvar.h>
|
|
|
|
|
2003-08-22 07:39:05 +00:00
|
|
|
#include <dev/pci/pcivar.h>
|
|
|
|
#include <dev/pci/pcireg.h>
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
#include <sparc64/pci/ofw_pci.h>
|
|
|
|
#include <sparc64/pci/psychoreg.h>
|
|
|
|
#include <sparc64/pci/psychovar.h>
|
|
|
|
|
|
|
|
#include "pcib_if.h"
|
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
static void psycho_set_intr(struct psycho_softc *, int, device_t, bus_addr_t,
|
2001-11-09 20:19:58 +00:00
|
|
|
int, driver_intr_t);
|
2002-02-13 16:07:59 +00:00
|
|
|
static int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *,
|
|
|
|
bus_addr_t *, u_long *);
|
2001-11-09 20:19:58 +00:00
|
|
|
static void psycho_intr_stub(void *);
|
|
|
|
static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int);
|
|
|
|
|
|
|
|
/* Interrupt handlers */
|
|
|
|
static void psycho_ue(void *);
|
|
|
|
static void psycho_ce(void *);
|
|
|
|
static void psycho_bus_a(void *);
|
|
|
|
static void psycho_bus_b(void *);
|
|
|
|
static void psycho_powerfail(void *);
|
|
|
|
#ifdef PSYCHO_MAP_WAKEUP
|
|
|
|
static void psycho_wakeup(void *);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* IOMMU support */
|
|
|
|
static void psycho_iommu_init(struct psycho_softc *, int);
|
|
|
|
|
|
|
|
/*
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
* Methods.
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
static device_probe_t psycho_probe;
|
|
|
|
static device_attach_t psycho_attach;
|
|
|
|
static bus_read_ivar_t psycho_read_ivar;
|
|
|
|
static bus_setup_intr_t psycho_setup_intr;
|
|
|
|
static bus_teardown_intr_t psycho_teardown_intr;
|
|
|
|
static bus_alloc_resource_t psycho_alloc_resource;
|
|
|
|
static bus_activate_resource_t psycho_activate_resource;
|
|
|
|
static bus_deactivate_resource_t psycho_deactivate_resource;
|
|
|
|
static bus_release_resource_t psycho_release_resource;
|
|
|
|
static pcib_maxslots_t psycho_maxslots;
|
|
|
|
static pcib_read_config_t psycho_read_config;
|
|
|
|
static pcib_write_config_t psycho_write_config;
|
|
|
|
static pcib_route_interrupt_t psycho_route_interrupt;
|
|
|
|
static ofw_pci_intr_pending_t psycho_intr_pending;
|
|
|
|
static ofw_pci_get_bus_handle_t psycho_get_bus_handle;
|
|
|
|
static ofw_pci_get_node_t psycho_get_node;
|
|
|
|
static ofw_pci_adjust_busrange_t psycho_adjust_busrange;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
static device_method_t psycho_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, psycho_probe),
|
|
|
|
DEVMETHOD(device_attach, psycho_attach),
|
|
|
|
|
|
|
|
/* Bus interface */
|
|
|
|
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
|
|
|
DEVMETHOD(bus_read_ivar, psycho_read_ivar),
|
|
|
|
DEVMETHOD(bus_setup_intr, psycho_setup_intr),
|
|
|
|
DEVMETHOD(bus_teardown_intr, psycho_teardown_intr),
|
|
|
|
DEVMETHOD(bus_alloc_resource, psycho_alloc_resource),
|
|
|
|
DEVMETHOD(bus_activate_resource, psycho_activate_resource),
|
|
|
|
DEVMETHOD(bus_deactivate_resource, psycho_deactivate_resource),
|
|
|
|
DEVMETHOD(bus_release_resource, psycho_release_resource),
|
|
|
|
|
|
|
|
/* pcib interface */
|
|
|
|
DEVMETHOD(pcib_maxslots, psycho_maxslots),
|
|
|
|
DEVMETHOD(pcib_read_config, psycho_read_config),
|
|
|
|
DEVMETHOD(pcib_write_config, psycho_write_config),
|
|
|
|
DEVMETHOD(pcib_route_interrupt, psycho_route_interrupt),
|
|
|
|
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
/* ofw_pci interface */
|
|
|
|
DEVMETHOD(ofw_pci_intr_pending, psycho_intr_pending),
|
|
|
|
DEVMETHOD(ofw_pci_get_bus_handle, psycho_get_bus_handle),
|
|
|
|
DEVMETHOD(ofw_pci_get_node, psycho_get_node),
|
|
|
|
DEVMETHOD(ofw_pci_adjust_busrange, psycho_adjust_busrange),
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t psycho_driver = {
|
|
|
|
"pcib",
|
|
|
|
psycho_methods,
|
|
|
|
sizeof(struct psycho_softc),
|
|
|
|
};
|
|
|
|
|
|
|
|
static devclass_t psycho_devclass;
|
|
|
|
|
|
|
|
DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, 0, 0);
|
|
|
|
|
2002-10-16 17:03:36 +00:00
|
|
|
SLIST_HEAD(, psycho_softc) psycho_softcs =
|
|
|
|
SLIST_HEAD_INITIALIZER(psycho_softcs);
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
struct psycho_clr {
|
2002-02-13 16:07:59 +00:00
|
|
|
struct psycho_softc *pci_sc;
|
|
|
|
bus_addr_t pci_clr; /* clear register */
|
2001-11-09 20:19:58 +00:00
|
|
|
driver_intr_t *pci_handler; /* handler to call */
|
2002-02-13 16:07:59 +00:00
|
|
|
void *pci_arg; /* argument for the handler */
|
|
|
|
void *pci_cookie; /* interrupt cookie of parent bus */
|
2001-11-09 20:19:58 +00:00
|
|
|
};
|
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
struct psycho_strayclr {
|
|
|
|
struct psycho_softc *psc_sc;
|
|
|
|
bus_addr_t psc_clr; /* clear register */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define PSYCHO_READ8(sc, off) \
|
|
|
|
bus_space_read_8((sc)->sc_bustag, (sc)->sc_bushandle, (off))
|
|
|
|
#define PSYCHO_WRITE8(sc, off, v) \
|
|
|
|
bus_space_write_8((sc)->sc_bustag, (sc)->sc_bushandle, (off), (v))
|
|
|
|
#define PCICTL_READ8(sc, off) \
|
|
|
|
PSYCHO_READ8((sc), (sc)->sc_pcictl + (off))
|
|
|
|
#define PCICTL_WRITE8(sc, off, v) \
|
|
|
|
PSYCHO_WRITE8((sc), (sc)->sc_pcictl + (off), (v))
|
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
|
|
|
* "sabre" is the UltraSPARC IIi onboard UPA to PCI bridge. It manages a
|
|
|
|
* single PCI bus and does not have a streaming buffer. It often has an APB
|
|
|
|
* (advanced PCI bridge) connected to it, which was designed specifically for
|
|
|
|
* the IIi. The APB let's the IIi handle two independednt PCI buses, and
|
|
|
|
* appears as two "simba"'s underneath the sabre.
|
|
|
|
*
|
2004-04-25 00:30:28 +00:00
|
|
|
* "psycho" and "psycho+" are dual UPA to PCI bridges. They sit on the UPA bus
|
|
|
|
* and manage two PCI buses. "psycho" has two 64-bit 33MHz buses, while
|
2001-11-09 20:19:58 +00:00
|
|
|
* "psycho+" controls both a 64-bit 33Mhz and a 64-bit 66Mhz PCI bus. You
|
|
|
|
* will usually find a "psycho+" since I don't think the original "psycho"
|
2001-12-21 21:35:47 +00:00
|
|
|
* ever shipped, and if it did it would be in the U30.
|
2001-11-09 20:19:58 +00:00
|
|
|
*
|
|
|
|
* Each "psycho" PCI bus appears as a separate OFW node, but since they are
|
|
|
|
* both part of the same IC, they only have a single register space. As such,
|
|
|
|
* they need to be configured together, even though the autoconfiguration will
|
|
|
|
* attach them separately.
|
|
|
|
*
|
|
|
|
* On UltraIIi machines, "sabre" itself usually takes pci0, with "simba" often
|
|
|
|
* as pci1 and pci2, although they have been implemented with other PCI bus
|
|
|
|
* numbers on some machines.
|
|
|
|
*
|
|
|
|
* On UltraII machines, there can be any number of "psycho+" ICs, each
|
2001-12-21 21:35:47 +00:00
|
|
|
* providing two PCI buses.
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
2002-11-14 11:29:16 +00:00
|
|
|
#ifdef DEBUGGER_ON_POWERFAIL
|
|
|
|
#define PSYCHO_PWRFAIL_INT_FLAGS INTR_FAST
|
|
|
|
#else
|
|
|
|
#define PSYCHO_PWRFAIL_INT_FLAGS 0
|
|
|
|
#endif
|
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
#define OFW_PCI_TYPE "pci"
|
2002-10-16 17:37:50 +00:00
|
|
|
|
|
|
|
struct psycho_desc {
|
|
|
|
char *pd_string;
|
|
|
|
int pd_mode;
|
|
|
|
char *pd_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct psycho_desc psycho_compats[] = {
|
|
|
|
{ "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" },
|
|
|
|
{ "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre (US-IIi) compatible" },
|
|
|
|
{ "pci108e,a001", PSYCHO_MODE_SABRE, "Sabre (US-IIe) compatible" },
|
|
|
|
{ NULL, 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct psycho_desc psycho_models[] = {
|
|
|
|
{ "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" },
|
|
|
|
{ "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" },
|
|
|
|
{ NULL, 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct psycho_desc *
|
|
|
|
psycho_find_desc(struct psycho_desc *table, char *string)
|
|
|
|
{
|
|
|
|
struct psycho_desc *desc;
|
|
|
|
|
|
|
|
for (desc = table; desc->pd_string != NULL; desc++) {
|
|
|
|
if (strcmp(desc->pd_string, string) == 0)
|
|
|
|
return (desc);
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct psycho_desc *
|
|
|
|
psycho_get_desc(phandle_t node, char *model)
|
|
|
|
{
|
|
|
|
struct psycho_desc *rv;
|
|
|
|
char compat[32];
|
|
|
|
|
|
|
|
rv = NULL;
|
|
|
|
if (model != NULL)
|
|
|
|
rv = psycho_find_desc(psycho_models, model);
|
|
|
|
if (rv == NULL &&
|
|
|
|
OF_getprop(node, "compatible", compat, sizeof(compat)) != -1)
|
|
|
|
rv = psycho_find_desc(psycho_compats, compat);
|
|
|
|
return (rv);
|
|
|
|
}
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_probe(device_t dev)
|
|
|
|
{
|
|
|
|
phandle_t node;
|
2002-10-16 17:37:50 +00:00
|
|
|
char *dtype;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
node = nexus_get_node(dev);
|
|
|
|
dtype = nexus_get_device_type(dev);
|
|
|
|
if (nexus_get_reg(dev) != NULL && dtype != NULL &&
|
|
|
|
strcmp(dtype, OFW_PCI_TYPE) == 0 &&
|
2002-10-16 17:37:50 +00:00
|
|
|
psycho_get_desc(node, nexus_get_model(dev)) != NULL) {
|
2001-11-09 20:19:58 +00:00
|
|
|
device_set_desc(dev, "U2P UPA-PCI bridge");
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_attach(device_t dev)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
struct psycho_softc *osc = NULL;
|
|
|
|
struct psycho_softc *asc;
|
2002-01-02 18:27:13 +00:00
|
|
|
struct upa_regs *reg;
|
2002-10-16 17:37:50 +00:00
|
|
|
struct psycho_desc *desc;
|
2001-11-09 20:19:58 +00:00
|
|
|
phandle_t node;
|
|
|
|
u_int64_t csr;
|
2003-04-08 06:35:09 +00:00
|
|
|
u_long mlen;
|
2001-11-09 20:19:58 +00:00
|
|
|
int psycho_br[2];
|
2002-01-02 18:27:13 +00:00
|
|
|
int n, i, nreg, rid;
|
2003-06-12 15:00:34 +00:00
|
|
|
#ifdef PSYCHO_DEBUG
|
2002-02-13 16:07:59 +00:00
|
|
|
bus_addr_t map, clr;
|
|
|
|
u_int64_t mr;
|
|
|
|
#endif
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
node = nexus_get_node(dev);
|
|
|
|
sc = device_get_softc(dev);
|
2002-10-16 17:37:50 +00:00
|
|
|
desc = psycho_get_desc(node, nexus_get_model(dev));
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
sc->sc_node = node;
|
|
|
|
sc->sc_dev = dev;
|
|
|
|
sc->sc_dmatag = nexus_get_dmatag(dev);
|
2002-10-16 17:37:50 +00:00
|
|
|
sc->sc_mode = desc->pd_mode;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The psycho gets three register banks:
|
|
|
|
* (0) per-PBM configuration and status registers
|
|
|
|
* (1) per-PBM PCI configuration space, containing only the
|
|
|
|
* PBM 256-byte PCI header
|
2004-04-25 00:30:28 +00:00
|
|
|
* (2) the shared psycho configuration registers
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
|
|
|
reg = nexus_get_reg(dev);
|
|
|
|
nreg = nexus_get_nreg(dev);
|
|
|
|
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
|
2002-01-02 18:27:13 +00:00
|
|
|
if (nreg <= 2)
|
2001-11-09 20:19:58 +00:00
|
|
|
panic("psycho_attach: %d not enough registers", nreg);
|
2003-04-08 06:35:09 +00:00
|
|
|
sc->sc_basepaddr = (vm_paddr_t)UPA_REG_PHYS(®[2]);
|
2002-01-02 18:27:13 +00:00
|
|
|
mlen = UPA_REG_SIZE(®[2]);
|
Fix interrupt assignment for non-builtin PCI devices on e450s.
This machine uses a non-standard scheme to specify the interrupts to
be assigned for devices in PCI slots; instead of giving the INO
or full interrupt number (which is done for the other devices in this
box), the firmware interrupt properties contain intpin numbers, which
have to be swizzled as usual on PCI-PCI bridges; however, the PCI host
bridge nodes have no interrupt map, so we need to guess the
correct INO by slot number of the device or the closest PCI-PCI
bridge leading to it, and the intpin.
To do this, this fix makes the following changes:
- Add a newbus method for sparc64 PCI host bridges to guess
the INO, and glue code in ofw_pci_orb_callback() to invoke it based
on a new quirk entry. The guessing is only done for interrupt numbers
too low to contain any IGN found on e450s.
- Create another new quirk entry was created to prevent mapping of EBus
interrupts at PCI level; the e450 has full INOs in the interrupt
properties of EBus devices, so trying to remap them could cause
problems.
- Set both quirk entries for e450s; remove the no-swizzle entry.
- Determine the psycho half (bus A or B) a driver instance manages
in psycho_attach()
- Implement the new guessing method for psycho, using the slot number,
psycho half and property value (intpin).
Thanks go to the testers, especially Brian Denehy, who tested many kernels
for me until I had found the right workaround.
Tested by: Brian Denehy <B.Denehy@90east.com>, jake, fenner,
Marius Strobl <marius@alchemy.franken.de>,
Marian Dobre <mari@onix.ro>
Approved by: re (scottl)
2003-05-30 20:48:05 +00:00
|
|
|
sc->sc_pcictl = UPA_REG_PHYS(®[0]) - sc->sc_basepaddr;
|
|
|
|
switch (sc->sc_pcictl) {
|
|
|
|
case PSR_PCICTL0:
|
|
|
|
sc->sc_half = 0;
|
|
|
|
break;
|
|
|
|
case PSR_PCICTL1:
|
|
|
|
sc->sc_half = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("psycho_attach: bogus pci control register "
|
|
|
|
"location");
|
|
|
|
}
|
2001-11-09 20:19:58 +00:00
|
|
|
} else {
|
2002-01-02 18:27:13 +00:00
|
|
|
if (nreg <= 0)
|
2001-11-09 20:19:58 +00:00
|
|
|
panic("psycho_attach: %d not enough registers", nreg);
|
2003-04-08 06:35:09 +00:00
|
|
|
sc->sc_basepaddr = (vm_paddr_t)UPA_REG_PHYS(®[0]);
|
2002-01-02 18:27:13 +00:00
|
|
|
mlen = UPA_REG_SIZE(reg);
|
Fix interrupt assignment for non-builtin PCI devices on e450s.
This machine uses a non-standard scheme to specify the interrupts to
be assigned for devices in PCI slots; instead of giving the INO
or full interrupt number (which is done for the other devices in this
box), the firmware interrupt properties contain intpin numbers, which
have to be swizzled as usual on PCI-PCI bridges; however, the PCI host
bridge nodes have no interrupt map, so we need to guess the
correct INO by slot number of the device or the closest PCI-PCI
bridge leading to it, and the intpin.
To do this, this fix makes the following changes:
- Add a newbus method for sparc64 PCI host bridges to guess
the INO, and glue code in ofw_pci_orb_callback() to invoke it based
on a new quirk entry. The guessing is only done for interrupt numbers
too low to contain any IGN found on e450s.
- Create another new quirk entry was created to prevent mapping of EBus
interrupts at PCI level; the e450 has full INOs in the interrupt
properties of EBus devices, so trying to remap them could cause
problems.
- Set both quirk entries for e450s; remove the no-swizzle entry.
- Determine the psycho half (bus A or B) a driver instance manages
in psycho_attach()
- Implement the new guessing method for psycho, using the slot number,
psycho half and property value (intpin).
Thanks go to the testers, especially Brian Denehy, who tested many kernels
for me until I had found the right workaround.
Tested by: Brian Denehy <B.Denehy@90east.com>, jake, fenner,
Marius Strobl <marius@alchemy.franken.de>,
Marian Dobre <mari@onix.ro>
Approved by: re (scottl)
2003-05-30 20:48:05 +00:00
|
|
|
sc->sc_pcictl = PSR_PCICTL0;
|
|
|
|
sc->sc_half = 0;
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Match other psycho's that are already configured against
|
|
|
|
* the base physical address. This will be the same for a
|
|
|
|
* pair of devices that share register space.
|
|
|
|
*/
|
2002-10-16 17:03:36 +00:00
|
|
|
SLIST_FOREACH(asc, &psycho_softcs, sc_link) {
|
|
|
|
if (asc->sc_basepaddr == sc->sc_basepaddr) {
|
|
|
|
/* Found partner */
|
|
|
|
osc = asc;
|
|
|
|
break;
|
|
|
|
}
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
if (osc == NULL) {
|
|
|
|
rid = 0;
|
|
|
|
sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
|
|
|
|
sc->sc_basepaddr, sc->sc_basepaddr + mlen - 1, mlen,
|
|
|
|
RF_ACTIVE);
|
|
|
|
if (sc->sc_mem_res == NULL ||
|
|
|
|
rman_get_start(sc->sc_mem_res) != sc->sc_basepaddr)
|
|
|
|
panic("psycho_attach: can't allocate device memory");
|
|
|
|
sc->sc_bustag = rman_get_bustag(sc->sc_mem_res);
|
|
|
|
sc->sc_bushandle = rman_get_bushandle(sc->sc_mem_res);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* There's another psycho using the same register space. Copy the
|
|
|
|
* relevant stuff.
|
|
|
|
*/
|
|
|
|
sc->sc_mem_res = NULL;
|
|
|
|
sc->sc_bustag = osc->sc_bustag;
|
|
|
|
sc->sc_bushandle = osc->sc_bushandle;
|
|
|
|
}
|
|
|
|
csr = PSYCHO_READ8(sc, PSR_CS);
|
|
|
|
sc->sc_ign = 0x7c0; /* APB IGN is always 0x7c */
|
|
|
|
if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
|
|
|
|
sc->sc_ign = PSYCHO_GCSR_IGN(csr) << 6;
|
|
|
|
|
Fix interrupt assignment for non-builtin PCI devices on e450s.
This machine uses a non-standard scheme to specify the interrupts to
be assigned for devices in PCI slots; instead of giving the INO
or full interrupt number (which is done for the other devices in this
box), the firmware interrupt properties contain intpin numbers, which
have to be swizzled as usual on PCI-PCI bridges; however, the PCI host
bridge nodes have no interrupt map, so we need to guess the
correct INO by slot number of the device or the closest PCI-PCI
bridge leading to it, and the intpin.
To do this, this fix makes the following changes:
- Add a newbus method for sparc64 PCI host bridges to guess
the INO, and glue code in ofw_pci_orb_callback() to invoke it based
on a new quirk entry. The guessing is only done for interrupt numbers
too low to contain any IGN found on e450s.
- Create another new quirk entry was created to prevent mapping of EBus
interrupts at PCI level; the e450 has full INOs in the interrupt
properties of EBus devices, so trying to remap them could cause
problems.
- Set both quirk entries for e450s; remove the no-swizzle entry.
- Determine the psycho half (bus A or B) a driver instance manages
in psycho_attach()
- Implement the new guessing method for psycho, using the slot number,
psycho half and property value (intpin).
Thanks go to the testers, especially Brian Denehy, who tested many kernels
for me until I had found the right workaround.
Tested by: Brian Denehy <B.Denehy@90east.com>, jake, fenner,
Marius Strobl <marius@alchemy.franken.de>,
Marian Dobre <mari@onix.ro>
Approved by: re (scottl)
2003-05-30 20:48:05 +00:00
|
|
|
device_printf(dev, "%s, impl %d, version %d, ign %#x, bus %c\n",
|
2002-10-16 17:37:50 +00:00
|
|
|
desc->pd_name, (int)PSYCHO_GCSR_IMPL(csr),
|
Fix interrupt assignment for non-builtin PCI devices on e450s.
This machine uses a non-standard scheme to specify the interrupts to
be assigned for devices in PCI slots; instead of giving the INO
or full interrupt number (which is done for the other devices in this
box), the firmware interrupt properties contain intpin numbers, which
have to be swizzled as usual on PCI-PCI bridges; however, the PCI host
bridge nodes have no interrupt map, so we need to guess the
correct INO by slot number of the device or the closest PCI-PCI
bridge leading to it, and the intpin.
To do this, this fix makes the following changes:
- Add a newbus method for sparc64 PCI host bridges to guess
the INO, and glue code in ofw_pci_orb_callback() to invoke it based
on a new quirk entry. The guessing is only done for interrupt numbers
too low to contain any IGN found on e450s.
- Create another new quirk entry was created to prevent mapping of EBus
interrupts at PCI level; the e450 has full INOs in the interrupt
properties of EBus devices, so trying to remap them could cause
problems.
- Set both quirk entries for e450s; remove the no-swizzle entry.
- Determine the psycho half (bus A or B) a driver instance manages
in psycho_attach()
- Implement the new guessing method for psycho, using the slot number,
psycho half and property value (intpin).
Thanks go to the testers, especially Brian Denehy, who tested many kernels
for me until I had found the right workaround.
Tested by: Brian Denehy <B.Denehy@90east.com>, jake, fenner,
Marius Strobl <marius@alchemy.franken.de>,
Marian Dobre <mari@onix.ro>
Approved by: re (scottl)
2003-05-30 20:48:05 +00:00
|
|
|
(int)PSYCHO_GCSR_VERS(csr), sc->sc_ign, 'A' + sc->sc_half);
|
2002-02-13 16:07:59 +00:00
|
|
|
|
2004-04-25 00:30:28 +00:00
|
|
|
/* Setup the PCI control register. */
|
2002-02-13 16:07:59 +00:00
|
|
|
csr = PCICTL_READ8(sc, PCR_CS);
|
|
|
|
csr |= PCICTL_MRLM | PCICTL_ARB_PARK | PCICTL_ERRINTEN | PCICTL_4ENABLE;
|
|
|
|
csr &= ~(PCICTL_SERR | PCICTL_CPU_PRIO | PCICTL_ARB_PRIO |
|
2001-11-09 20:19:58 +00:00
|
|
|
PCICTL_RTRYWAIT);
|
2002-02-13 16:07:59 +00:00
|
|
|
PCICTL_WRITE8(sc, PCR_CS, csr);
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2003-01-06 16:51:06 +00:00
|
|
|
if (sc->sc_mode == PSYCHO_MODE_SABRE) {
|
2004-04-25 00:30:28 +00:00
|
|
|
/* Use the PROM preset for now. */
|
2003-01-06 16:51:06 +00:00
|
|
|
csr = PCICTL_READ8(sc, PCR_TAS);
|
|
|
|
if (csr == 0)
|
|
|
|
panic("psycho_attach: sabre TAS not initialized.");
|
|
|
|
sc->sc_dvmabase = (ffs(csr) - 1) << PCITAS_ADDR_SHIFT;
|
|
|
|
} else
|
|
|
|
sc->sc_dvmabase = -1;
|
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
/* Initialize memory and i/o rmans */
|
|
|
|
sc->sc_io_rman.rm_type = RMAN_ARRAY;
|
|
|
|
sc->sc_io_rman.rm_descr = "Psycho PCI I/O Ports";
|
|
|
|
if (rman_init(&sc->sc_io_rman) != 0 ||
|
|
|
|
rman_manage_region(&sc->sc_io_rman, 0, PSYCHO_IO_SIZE) != 0)
|
|
|
|
panic("psycho_probe: failed to set up i/o rman");
|
|
|
|
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
|
|
|
|
sc->sc_mem_rman.rm_descr = "Psycho PCI Memory";
|
|
|
|
if (rman_init(&sc->sc_mem_rman) != 0 ||
|
|
|
|
rman_manage_region(&sc->sc_mem_rman, 0, PSYCHO_MEM_SIZE) != 0)
|
|
|
|
panic("psycho_probe: failed to set up memory rman");
|
2004-04-25 00:30:28 +00:00
|
|
|
|
|
|
|
sc->sc_nrange = OF_getprop_alloc(sc->sc_node, "ranges",
|
|
|
|
sizeof(*sc->sc_range), (void **)&sc->sc_range);
|
|
|
|
if (sc->sc_nrange == -1)
|
|
|
|
panic("could not get psycho ranges");
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
|
|
|
* Find the addresses of the various bus spaces.
|
|
|
|
* There should not be multiple ones of one kind.
|
|
|
|
* The physical start addresses of the ranges are the configuration,
|
|
|
|
* memory and IO handles.
|
|
|
|
*/
|
|
|
|
for (n = 0; n < sc->sc_nrange; n++) {
|
|
|
|
i = UPA_RANGE_CS(&sc->sc_range[n]);
|
|
|
|
if (sc->sc_bh[i] != 0)
|
|
|
|
panic("psycho_attach: duplicate range for space %d", i);
|
|
|
|
sc->sc_bh[i] = UPA_RANGE_PHYS(&sc->sc_range[n]);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Check that all needed handles are present. The PCI_CS_MEM64 one is
|
|
|
|
* not currently used.
|
|
|
|
*/
|
|
|
|
for (n = 0; n < 3; n++) {
|
|
|
|
if (sc->sc_bh[n] == 0)
|
|
|
|
panic("psycho_attach: range %d missing", n);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Register the softc, this is needed for paired psychos. */
|
2002-10-16 17:03:36 +00:00
|
|
|
SLIST_INSERT_HEAD(&psycho_softcs, sc, sc_link);
|
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
2003-06-11 20:30:52 +00:00
|
|
|
* If we're a sabre or the first of a pair of psycho's to arrive here,
|
|
|
|
* start up the IOMMU.
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
|
|
|
if (osc == NULL) {
|
|
|
|
/*
|
|
|
|
* Establish handlers for interesting interrupts....
|
|
|
|
*
|
|
|
|
* XXX We need to remember these and remove this to support
|
|
|
|
* hotplug on the UPA/FHC bus.
|
|
|
|
*
|
|
|
|
* XXX Not all controllers have these, but installing them
|
|
|
|
* is better than trying to sort through this mess.
|
|
|
|
*/
|
2002-02-13 16:07:59 +00:00
|
|
|
psycho_set_intr(sc, 0, dev, PSR_UE_INT_MAP, INTR_FAST,
|
|
|
|
psycho_ue);
|
|
|
|
psycho_set_intr(sc, 1, dev, PSR_CE_INT_MAP, 0, psycho_ce);
|
|
|
|
psycho_set_intr(sc, 2, dev, PSR_PCIAERR_INT_MAP, INTR_FAST,
|
2001-11-09 20:19:58 +00:00
|
|
|
psycho_bus_a);
|
2002-11-14 11:29:16 +00:00
|
|
|
psycho_set_intr(sc, 4, dev, PSR_POWER_INT_MAP,
|
|
|
|
PSYCHO_PWRFAIL_INT_FLAGS, psycho_powerfail);
|
2002-04-02 17:27:35 +00:00
|
|
|
/* Psycho-specific initialization. */
|
|
|
|
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
|
|
|
|
/*
|
|
|
|
* Sabres do not have the following two interrupts.
|
|
|
|
*/
|
|
|
|
psycho_set_intr(sc, 3, dev, PSR_PCIBERR_INT_MAP,
|
|
|
|
INTR_FAST, psycho_bus_b);
|
2001-11-09 20:19:58 +00:00
|
|
|
#ifdef PSYCHO_MAP_WAKEUP
|
2002-04-02 17:27:35 +00:00
|
|
|
/*
|
|
|
|
* psycho_wakeup() doesn't do anything useful right
|
|
|
|
* now.
|
|
|
|
*/
|
|
|
|
psycho_set_intr(sc, 5, dev, PSR_PWRMGT_INT_MAP, 0,
|
|
|
|
psycho_wakeup);
|
2001-11-09 20:19:58 +00:00
|
|
|
#endif /* PSYCHO_MAP_WAKEUP */
|
|
|
|
|
2002-04-02 17:27:35 +00:00
|
|
|
/* Initialize the counter-timer. */
|
2002-02-13 16:07:59 +00:00
|
|
|
sparc64_counter_init(sc->sc_bustag, sc->sc_bushandle,
|
|
|
|
PSR_TC0);
|
|
|
|
}
|
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
|
|
|
* Setup IOMMU and PCI configuration if we're the first
|
|
|
|
* of a pair of psycho's to arrive here.
|
|
|
|
*
|
|
|
|
* We should calculate a TSB size based on amount of RAM
|
2002-12-30 21:18:15 +00:00
|
|
|
* and number of bus controllers and number and type of
|
2001-11-09 20:19:58 +00:00
|
|
|
* child devices.
|
|
|
|
*
|
|
|
|
* For the moment, 32KB should be more than enough.
|
|
|
|
*/
|
2002-02-13 16:07:59 +00:00
|
|
|
sc->sc_is = malloc(sizeof(struct iommu_state), M_DEVBUF,
|
|
|
|
M_NOWAIT);
|
|
|
|
if (sc->sc_is == NULL)
|
|
|
|
panic("psycho_attach: malloc iommu_state failed");
|
|
|
|
sc->sc_is->is_sb[0] = 0;
|
|
|
|
sc->sc_is->is_sb[1] = 0;
|
|
|
|
if (OF_getproplen(sc->sc_node, "no-streaming-cache") < 0)
|
|
|
|
sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF;
|
2003-05-02 01:21:37 +00:00
|
|
|
psycho_iommu_init(sc, 3);
|
2001-11-09 20:19:58 +00:00
|
|
|
} else {
|
|
|
|
/* Just copy IOMMU state, config tag and address */
|
|
|
|
sc->sc_is = osc->sc_is;
|
2002-02-13 16:07:59 +00:00
|
|
|
if (OF_getproplen(sc->sc_node, "no-streaming-cache") < 0)
|
|
|
|
sc->sc_is->is_sb[1] = sc->sc_pcictl + PCR_STRBUF;
|
|
|
|
iommu_reset(sc->sc_is);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
2003-06-11 20:30:52 +00:00
|
|
|
/* Allocate our tags. */
|
|
|
|
sc->sc_memt = psycho_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
|
|
|
|
sc->sc_iot = psycho_alloc_bus_tag(sc, PCI_IO_BUS_SPACE);
|
|
|
|
sc->sc_cfgt = psycho_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE);
|
|
|
|
if (bus_dma_tag_create(sc->sc_dmatag, 8, 1, 0, 0x3ffffffff, NULL, NULL,
|
2003-07-01 15:52:06 +00:00
|
|
|
0x3ffffffff, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_dmat) != 0)
|
2003-06-11 20:30:52 +00:00
|
|
|
panic("psycho_attach: bus_dma_tag_create failed");
|
|
|
|
/* Customize the tag. */
|
|
|
|
sc->sc_dmat->dt_cookie = sc->sc_is;
|
Further cleanup of the sparc64 busdma implementation:
- Move prototypes for sparc64-specific helper functions from bus.h to
bus_private.h
- Move the method pointers from struct bus_dma_tag into a separate
structure; this saves some memory, and allows to use a single method
table for each busdma backend, so that the bus drivers need no longer
be changed if the methods tables need to be modified.
- Remove the hierarchical tag method lookup. It was never really useful,
since the layering is fixed, and the current implementations do not
need to call into parent implementations anyway. Each tag inherits
its method table pointer and cookie from the parent (or the root tag)
now, and the method wrapper macros directly use the method table
of the tag.
- Add a method table to the non-IOMMU backend, remove unnecessary
prototypes, remove the extra parent tag argument.
- Rename sparc64_dmamem_alloc_map() and sparc64_dmamem_free_map() to
sparc64_dma_alloc_map() and sparc64_dma_free_map(), move them to a
better place and use them for all map allocations and deallocations.
- Add a method table to the iommu backend, and staticize functions,
remove the extra parent tag argument.
- Change the psycho and sbus drivers to just set cookie and method table
in the root tag.
- Miscellaneous small fixes.
2003-06-18 16:41:36 +00:00
|
|
|
sc->sc_dmat->dt_mt = &iommu_dma_methods;
|
2003-06-11 20:30:52 +00:00
|
|
|
/* XXX: register as root dma tag (kludge). */
|
|
|
|
sparc64_root_dma_tag = sc->sc_dmat;
|
|
|
|
|
2003-06-12 15:00:34 +00:00
|
|
|
#ifdef PSYCHO_DEBUG
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
2003-06-12 15:00:34 +00:00
|
|
|
* Enable all interrupts and clear all interrupt states.
|
|
|
|
* This aids the debugging of interrupt routing problems.
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
2002-02-13 16:07:59 +00:00
|
|
|
for (map = PSR_PCIA0_INT_MAP, clr = PSR_PCIA0_INT_CLR, n = 0;
|
|
|
|
map <= PSR_PCIB3_INT_MAP; map += 8, clr += 32, n++) {
|
|
|
|
mr = PSYCHO_READ8(sc, map);
|
|
|
|
device_printf(dev, "intr map (pci) %d: %#lx\n", n, (u_long)mr);
|
|
|
|
PSYCHO_WRITE8(sc, map, mr & ~INTMAP_V);
|
2001-11-09 20:19:58 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
2002-02-13 16:07:59 +00:00
|
|
|
PCICTL_WRITE8(sc, clr + i * 8, 0);
|
2002-12-01 23:30:26 +00:00
|
|
|
PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid)));
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
2002-02-13 16:07:59 +00:00
|
|
|
for (map = PSR_SCSI_INT_MAP, clr = PSR_SCSI_INT_CLR, n = 0;
|
2002-12-06 13:16:52 +00:00
|
|
|
map <= PSR_SERIAL_INT_MAP; map += 8, clr += 8, n++) {
|
2002-02-13 16:07:59 +00:00
|
|
|
mr = PSYCHO_READ8(sc, map);
|
|
|
|
device_printf(dev, "intr map (obio) %d: %#lx, clr: %#lx\n", n,
|
|
|
|
(u_long)mr, (u_long)clr);
|
|
|
|
PSYCHO_WRITE8(sc, map, mr & ~INTMAP_V);
|
|
|
|
PSYCHO_WRITE8(sc, clr, 0);
|
2002-12-01 23:30:26 +00:00
|
|
|
PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid)));
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
2003-06-12 15:00:34 +00:00
|
|
|
#endif /* PSYCHO_DEBUG */
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2002-06-12 19:20:57 +00:00
|
|
|
/*
|
|
|
|
* Get the bus range from the firmware; it is used solely for obtaining
|
|
|
|
* the inital bus number, and cannot be trusted on all machines.
|
|
|
|
*/
|
|
|
|
n = OF_getprop(node, "bus-range", (void *)psycho_br, sizeof(psycho_br));
|
|
|
|
if (n == -1)
|
|
|
|
panic("could not get psycho bus-range");
|
|
|
|
if (n != sizeof(psycho_br))
|
|
|
|
panic("broken psycho bus-range (%d)", n);
|
|
|
|
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
sc->sc_secbus = sc->sc_subbus = ofw_pci_alloc_busno(sc->sc_node);
|
|
|
|
/*
|
|
|
|
* Program the bus range registers.
|
2004-04-25 00:30:28 +00:00
|
|
|
* NOTE: for the psycho, the second write changes the bus number the
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
* psycho itself uses for it's configuration space, so these
|
|
|
|
* writes must be kept in this order!
|
|
|
|
* The sabre always uses bus 0, but there only can be one sabre per
|
|
|
|
* machine.
|
|
|
|
*/
|
|
|
|
PCIB_WRITE_CONFIG(dev, psycho_br[0], PCS_DEVICE, PCS_FUNC, PCSR_SUBBUS,
|
|
|
|
sc->sc_subbus, 1);
|
|
|
|
PCIB_WRITE_CONFIG(dev, psycho_br[0], PCS_DEVICE, PCS_FUNC, PCSR_SECBUS,
|
|
|
|
sc->sc_secbus, 1);
|
|
|
|
|
|
|
|
ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_pci_intr_t));
|
2001-12-21 21:35:47 +00:00
|
|
|
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
device_add_child(dev, "pci", sc->sc_secbus);
|
2001-11-09 20:19:58 +00:00
|
|
|
return (bus_generic_attach(dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_set_intr(struct psycho_softc *sc, int index,
|
2002-02-13 16:07:59 +00:00
|
|
|
device_t dev, bus_addr_t map, int iflags, driver_intr_t handler)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
2002-02-13 16:07:59 +00:00
|
|
|
int rid, vec;
|
|
|
|
u_int64_t mr;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
mr = PSYCHO_READ8(sc, map);
|
|
|
|
vec = INTVEC(mr);
|
2002-01-02 18:27:13 +00:00
|
|
|
sc->sc_irq_res[index] = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
2002-02-13 16:07:59 +00:00
|
|
|
vec, vec, 1, RF_ACTIVE);
|
2002-01-02 18:27:13 +00:00
|
|
|
if (sc->sc_irq_res[index] == NULL)
|
2002-02-13 16:07:59 +00:00
|
|
|
panic("psycho_set_intr: failed to get interrupt");
|
2002-01-02 18:27:13 +00:00
|
|
|
bus_setup_intr(dev, sc->sc_irq_res[index], INTR_TYPE_MISC | iflags,
|
2001-11-09 20:19:58 +00:00
|
|
|
handler, sc, &sc->sc_ihand[index]);
|
2002-12-01 23:30:26 +00:00
|
|
|
PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid)));
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2002-02-13 16:07:59 +00:00
|
|
|
psycho_find_intrmap(struct psycho_softc *sc, int ino, bus_addr_t *intrmapptr,
|
|
|
|
bus_addr_t *intrclrptr, bus_addr_t *intrdiagptr)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
2002-02-13 16:07:59 +00:00
|
|
|
bus_addr_t intrmap, intrclr;
|
|
|
|
u_int64_t im;
|
|
|
|
u_long diag;
|
2001-11-09 20:19:58 +00:00
|
|
|
int found;
|
|
|
|
|
|
|
|
found = 0;
|
|
|
|
/* Hunt thru obio first */
|
2002-02-13 16:07:59 +00:00
|
|
|
diag = PSYCHO_READ8(sc, PSR_OBIO_INT_DIAG);
|
|
|
|
for (intrmap = PSR_SCSI_INT_MAP, intrclr = PSR_SCSI_INT_CLR;
|
2002-12-06 13:16:52 +00:00
|
|
|
intrmap <= PSR_SERIAL_INT_MAP; intrmap += 8, intrclr += 8,
|
2002-02-13 16:07:59 +00:00
|
|
|
diag >>= 2) {
|
|
|
|
im = PSYCHO_READ8(sc, intrmap);
|
|
|
|
if (INTINO(im) == ino) {
|
2001-11-09 20:19:58 +00:00
|
|
|
diag &= 2;
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2002-02-13 16:07:59 +00:00
|
|
|
diag = PSYCHO_READ8(sc, PSR_PCI_INT_DIAG);
|
2001-11-09 20:19:58 +00:00
|
|
|
/* Now do PCI interrupts */
|
2002-02-13 16:07:59 +00:00
|
|
|
for (intrmap = PSR_PCIA0_INT_MAP, intrclr = PSR_PCIA0_INT_CLR;
|
|
|
|
intrmap <= PSR_PCIB3_INT_MAP; intrmap += 8, intrclr += 32,
|
|
|
|
diag >>= 8) {
|
2002-12-01 23:21:15 +00:00
|
|
|
if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
|
|
|
|
(intrmap == PSR_PCIA2_INT_MAP ||
|
|
|
|
intrmap == PSR_PCIA3_INT_MAP))
|
|
|
|
continue;
|
2002-02-13 16:07:59 +00:00
|
|
|
im = PSYCHO_READ8(sc, intrmap);
|
|
|
|
if (((im ^ ino) & 0x3c) == 0) {
|
|
|
|
intrclr += 8 * (ino & 3);
|
2001-11-09 20:19:58 +00:00
|
|
|
diag = (diag >> ((ino & 3) * 2)) & 2;
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (intrmapptr != NULL)
|
|
|
|
*intrmapptr = intrmap;
|
|
|
|
if (intrclrptr != NULL)
|
|
|
|
*intrclrptr = intrclr;
|
|
|
|
if (intrdiagptr != NULL)
|
|
|
|
*intrdiagptr = diag;
|
|
|
|
return (found);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Interrupt handlers.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
psycho_ue(void *arg)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = (struct psycho_softc *)arg;
|
2002-02-13 16:07:59 +00:00
|
|
|
u_int64_t afar, afsr;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
afar = PSYCHO_READ8(sc, PSR_UE_AFA);
|
|
|
|
afsr = PSYCHO_READ8(sc, PSR_UE_AFS);
|
2002-03-23 20:42:23 +00:00
|
|
|
/*
|
|
|
|
* On the UltraSPARC-IIi/IIe, IOMMU misses/protection faults cause
|
|
|
|
* the AFAR to be set to the physical address of the TTE entry that
|
|
|
|
* was invalid/write protected. Call into the iommu code to have
|
|
|
|
* them decoded to virtual IO addresses.
|
|
|
|
*/
|
|
|
|
if ((afsr & UEAFSR_P_DTE) != 0)
|
|
|
|
iommu_decode_fault(sc->sc_is, afar);
|
2003-01-06 16:51:06 +00:00
|
|
|
panic("%s: uncorrectable DMA error AFAR %#lx AFSR %#lx",
|
2002-02-13 16:07:59 +00:00
|
|
|
device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_ce(void *arg)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = (struct psycho_softc *)arg;
|
2002-02-13 16:07:59 +00:00
|
|
|
u_int64_t afar, afsr;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
afar = PSYCHO_READ8(sc, PSR_CE_AFA);
|
|
|
|
afsr = PSYCHO_READ8(sc, PSR_CE_AFS);
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
device_printf(sc->sc_dev, "correctable DMA error AFAR %#lx "
|
|
|
|
"AFSR %#lx\n", (u_long)afar, (u_long)afsr);
|
2003-09-04 15:25:10 +00:00
|
|
|
/* Clear the error bits that we caught. */
|
|
|
|
PSYCHO_WRITE8(sc, PSR_CE_AFS, afsr & CEAFSR_ERRMASK);
|
|
|
|
PSYCHO_WRITE8(sc, PSR_CE_INT_CLR, 0);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_bus_a(void *arg)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = (struct psycho_softc *)arg;
|
2002-02-13 16:07:59 +00:00
|
|
|
u_int64_t afar, afsr;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
afar = PSYCHO_READ8(sc, PSR_PCICTL0 + PCR_AFA);
|
|
|
|
afsr = PSYCHO_READ8(sc, PSR_PCICTL0 + PCR_AFS);
|
2003-01-06 16:51:06 +00:00
|
|
|
panic("%s: PCI bus A error AFAR %#lx AFSR %#lx",
|
2002-02-13 16:07:59 +00:00
|
|
|
device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_bus_b(void *arg)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = (struct psycho_softc *)arg;
|
2002-02-13 16:07:59 +00:00
|
|
|
u_int64_t afar, afsr;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
afar = PSYCHO_READ8(sc, PSR_PCICTL1 + PCR_AFA);
|
|
|
|
afsr = PSYCHO_READ8(sc, PSR_PCICTL1 + PCR_AFS);
|
2003-01-06 16:51:06 +00:00
|
|
|
panic("%s: PCI bus B error AFAR %#lx AFSR %#lx",
|
2002-02-13 16:07:59 +00:00
|
|
|
device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_powerfail(void *arg)
|
|
|
|
{
|
|
|
|
|
2002-03-13 05:58:45 +00:00
|
|
|
#ifdef DEBUGGER_ON_POWERFAIL
|
|
|
|
struct psycho_softc *sc = (struct psycho_softc *)arg;
|
|
|
|
|
|
|
|
Debugger("powerfail");
|
|
|
|
PSYCHO_WRITE8(sc, PSR_POWER_INT_CLR, 0);
|
|
|
|
#else
|
2001-11-09 20:19:58 +00:00
|
|
|
printf("Power Failure Detected: Shutting down NOW.\n");
|
|
|
|
shutdown_nice(0);
|
2002-03-13 05:58:45 +00:00
|
|
|
#endif
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef PSYCHO_MAP_WAKEUP
|
|
|
|
static void
|
|
|
|
psycho_wakeup(void *arg)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = (struct psycho_softc *)arg;
|
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
PSYCHO_WRITE8(sc, PSR_PWRMGT_INT_CLR, 0);
|
2001-11-09 20:19:58 +00:00
|
|
|
/* Gee, we don't really have a framework to deal with this properly. */
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
device_printf(sc->sc_dev, "power management wakeup\n");
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
#endif /* PSYCHO_MAP_WAKEUP */
|
|
|
|
|
|
|
|
void
|
|
|
|
psycho_iommu_init(struct psycho_softc *sc, int tsbsize)
|
|
|
|
{
|
|
|
|
char *name;
|
2002-02-13 16:07:59 +00:00
|
|
|
struct iommu_state *is = sc->sc_is;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
/* punch in our copies */
|
|
|
|
is->is_bustag = sc->sc_bustag;
|
2002-02-13 16:07:59 +00:00
|
|
|
is->is_bushandle = sc->sc_bushandle;
|
|
|
|
is->is_iommu = PSR_IOMMU;
|
|
|
|
is->is_dtag = PSR_IOMMU_TLB_TAG_DIAG;
|
|
|
|
is->is_ddram = PSR_IOMMU_TLB_DATA_DIAG;
|
|
|
|
is->is_dqueue = PSR_IOMMU_QUEUE_DIAG;
|
|
|
|
is->is_dva = PSR_IOMMU_SVADIAG;
|
|
|
|
is->is_dtcmp = PSR_IOMMU_TLB_CMP_DIAG;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
/* give us a nice name.. */
|
|
|
|
name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
|
|
|
|
if (name == 0)
|
|
|
|
panic("couldn't malloc iommu name");
|
2004-04-25 00:30:28 +00:00
|
|
|
snprintf(name, 32, "%s dvma", device_get_nameunit(sc->sc_dev));
|
2001-11-09 20:19:58 +00:00
|
|
|
|
2003-01-06 16:51:06 +00:00
|
|
|
iommu_init(name, is, tsbsize, sc->sc_dvmabase, 0);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_maxslots(device_t dev)
|
|
|
|
{
|
|
|
|
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
/* XXX: is this correct? */
|
|
|
|
return (PCI_SLOTMAX);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static u_int32_t
|
|
|
|
psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
|
|
|
|
int width)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
bus_space_handle_t bh;
|
|
|
|
u_long offset = 0;
|
2003-06-22 01:26:08 +00:00
|
|
|
u_int8_t byte;
|
|
|
|
u_int16_t shrt;
|
|
|
|
u_int32_t wrd;
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
u_int32_t r;
|
2001-12-21 21:35:47 +00:00
|
|
|
int i;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(dev);
|
|
|
|
offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
|
|
|
|
bh = sc->sc_bh[PCI_CS_CONFIG];
|
|
|
|
switch (width) {
|
|
|
|
case 1:
|
2003-06-22 01:26:08 +00:00
|
|
|
i = bus_space_peek_1(sc->sc_cfgt, bh, offset, &byte);
|
|
|
|
r = byte;
|
2001-11-09 20:19:58 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2003-06-22 01:26:08 +00:00
|
|
|
i = bus_space_peek_2(sc->sc_cfgt, bh, offset, &shrt);
|
|
|
|
r = shrt;
|
2001-11-09 20:19:58 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
2003-06-22 01:26:08 +00:00
|
|
|
i = bus_space_peek_4(sc->sc_cfgt, bh, offset, &wrd);
|
|
|
|
r = wrd;
|
2001-11-09 20:19:58 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("psycho_read_config: bad width");
|
|
|
|
}
|
2003-06-22 01:26:08 +00:00
|
|
|
|
|
|
|
if (i) {
|
|
|
|
#ifdef PSYCHO_DEBUG
|
|
|
|
printf("psycho read data error reading: %d.%d.%d: 0x%x\n",
|
|
|
|
bus, slot, func, reg);
|
|
|
|
#endif
|
|
|
|
r = -1;
|
|
|
|
}
|
2001-11-09 20:19:58 +00:00
|
|
|
return (r);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func,
|
|
|
|
u_int reg, u_int32_t val, int width)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
bus_space_handle_t bh;
|
|
|
|
u_long offset = 0;
|
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(dev);
|
|
|
|
offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
|
|
|
|
bh = sc->sc_bh[PCI_CS_CONFIG];
|
|
|
|
switch (width) {
|
|
|
|
case 1:
|
|
|
|
bus_space_write_1(sc->sc_cfgt, bh, offset, val);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bus_space_write_2(sc->sc_cfgt, bh, offset, val);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
bus_space_write_4(sc->sc_cfgt, bh, offset, val);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("psycho_write_config: bad width");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
psycho_route_interrupt(device_t bridge, device_t dev, int pin)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
struct psycho_softc *sc = device_get_softc(bridge);
|
|
|
|
struct ofw_pci_register reg;
|
|
|
|
bus_addr_t intrmap;
|
|
|
|
phandle_t node = ofw_pci_get_node(dev);
|
|
|
|
ofw_pci_intr_t pintr, mintr;
|
|
|
|
u_int8_t maskbuf[sizeof(reg) + sizeof(pintr)];
|
|
|
|
|
|
|
|
pintr = pin;
|
|
|
|
if (ofw_bus_lookup_imap(node, &sc->sc_iinfo, ®, sizeof(reg),
|
|
|
|
&pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
|
|
|
|
return (mintr);
|
|
|
|
/*
|
|
|
|
* If this is outside of the range for an intpin, it's likely a full
|
|
|
|
* INO, and no mapping is required at all; this happens on the u30,
|
2004-04-25 00:30:28 +00:00
|
|
|
* where there's no interrupt map at the psycho node. Fortunately,
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
* there seem to be no INOs in the intpin range on this boxen, so
|
|
|
|
* this easy heuristics will do.
|
|
|
|
*/
|
|
|
|
if (pin > 4)
|
|
|
|
return (pin);
|
|
|
|
/*
|
|
|
|
* Guess the INO; we always assume that this is a non-OBIO
|
|
|
|
* device, and that pin is a "real" intpin number. Determine
|
|
|
|
* the mapping register to be used by the slot number.
|
|
|
|
* We only need to do this on e450s, it seems; here, the slot numbers
|
|
|
|
* for bus A are one-based, while those for bus B seemingly have an
|
|
|
|
* offset of 2 (hence the factor of 3 below).
|
|
|
|
*/
|
|
|
|
intrmap = PSR_PCIA0_INT_MAP +
|
|
|
|
8 * (pci_get_slot(dev) - 1 + 3 * sc->sc_half);
|
|
|
|
mintr = INTINO(PSYCHO_READ8(sc, intrmap)) + pin - 1;
|
|
|
|
device_printf(bridge, "guessing interrupt %d for device %d/%d pin %d\n",
|
|
|
|
(int)mintr, pci_get_slot(dev), pci_get_function(dev), pin);
|
|
|
|
return (mintr);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2002-02-13 16:07:59 +00:00
|
|
|
psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(dev);
|
|
|
|
switch (which) {
|
|
|
|
case PCIB_IVAR_BUS:
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
*result = sc->sc_secbus;
|
2001-11-09 20:19:58 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
return (ENOENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write to the correct clr register, and call the actual handler. */
|
|
|
|
static void
|
|
|
|
psycho_intr_stub(void *arg)
|
|
|
|
{
|
|
|
|
struct psycho_clr *pc;
|
|
|
|
|
|
|
|
pc = (struct psycho_clr *)arg;
|
|
|
|
pc->pci_handler(pc->pci_arg);
|
2002-02-13 16:07:59 +00:00
|
|
|
PSYCHO_WRITE8(pc->pci_sc, pc->pci_clr, 0);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_setup_intr(device_t dev, device_t child,
|
|
|
|
struct resource *ires, int flags, driver_intr_t *intr, void *arg,
|
|
|
|
void **cookiep)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
struct psycho_clr *pc;
|
2002-02-13 16:07:59 +00:00
|
|
|
bus_addr_t intrmapptr, intrclrptr;
|
2001-11-09 20:19:58 +00:00
|
|
|
long vec = rman_get_start(ires);
|
2002-02-13 16:07:59 +00:00
|
|
|
u_int64_t mr;
|
|
|
|
int ino, error;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(dev);
|
2002-02-13 16:07:59 +00:00
|
|
|
pc = (struct psycho_clr *)malloc(sizeof(*pc), M_DEVBUF, M_NOWAIT);
|
2001-11-09 20:19:58 +00:00
|
|
|
if (pc == NULL)
|
2003-12-26 14:04:19 +00:00
|
|
|
return (0);
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Hunt through all the interrupt mapping regs to look for our
|
|
|
|
* interrupt vector.
|
|
|
|
*
|
|
|
|
* XXX We only compare INOs rather than IGNs since the firmware may
|
2004-04-25 00:30:28 +00:00
|
|
|
* not provide the IGN and the IGN is constant for all devices on that
|
2001-11-09 20:19:58 +00:00
|
|
|
* PCI controller. This could cause problems for the FFB/external
|
2001-12-21 21:35:47 +00:00
|
|
|
* interrupt which has a full vector that can be set arbitrarily.
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
|
|
|
ino = INTINO(vec);
|
|
|
|
|
|
|
|
if (!psycho_find_intrmap(sc, ino, &intrmapptr, &intrclrptr, NULL)) {
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
device_printf(dev, "Cannot find interrupt vector %lx\n", vec);
|
2001-11-09 20:19:58 +00:00
|
|
|
free(pc, M_DEVBUF);
|
2003-12-26 14:04:19 +00:00
|
|
|
return (0);
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef PSYCHO_DEBUG
|
2002-02-13 16:07:59 +00:00
|
|
|
device_printf(dev, "psycho_setup_intr: INO %d, map %#lx, clr %#lx\n",
|
|
|
|
ino, (u_long)intrmapptr, (u_long)intrclrptr);
|
2001-11-09 20:19:58 +00:00
|
|
|
#endif
|
2002-02-13 16:07:59 +00:00
|
|
|
pc->pci_sc = sc;
|
2001-11-09 20:19:58 +00:00
|
|
|
pc->pci_arg = arg;
|
|
|
|
pc->pci_handler = intr;
|
|
|
|
pc->pci_clr = intrclrptr;
|
|
|
|
/* Disable the interrupt while we fiddle with it */
|
2002-02-13 16:07:59 +00:00
|
|
|
mr = PSYCHO_READ8(sc, intrmapptr);
|
|
|
|
PSYCHO_WRITE8(sc, intrmapptr, mr & ~INTMAP_V);
|
2001-12-21 21:35:47 +00:00
|
|
|
error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
|
|
|
|
psycho_intr_stub, pc, cookiep);
|
2001-11-09 20:19:58 +00:00
|
|
|
if (error != 0) {
|
|
|
|
free(pc, M_DEVBUF);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
pc->pci_cookie = *cookiep;
|
|
|
|
*cookiep = pc;
|
2001-12-21 21:35:47 +00:00
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
|
|
|
* Clear the interrupt, it might have been triggered before it was
|
|
|
|
* set up.
|
|
|
|
*/
|
2002-02-13 16:07:59 +00:00
|
|
|
PSYCHO_WRITE8(sc, intrclrptr, 0);
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
2002-12-01 23:30:26 +00:00
|
|
|
* Enable the interrupt and program the target module now we have the
|
|
|
|
* handler installed.
|
2001-11-09 20:19:58 +00:00
|
|
|
*/
|
2002-12-01 23:30:26 +00:00
|
|
|
PSYCHO_WRITE8(sc, intrmapptr, INTMAP_ENABLE(mr, PCPU_GET(mid)));
|
2001-11-09 20:19:58 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_teardown_intr(device_t dev, device_t child,
|
|
|
|
struct resource *vec, void *cookie)
|
|
|
|
{
|
|
|
|
struct psycho_clr *pc;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
pc = (struct psycho_clr *)cookie;
|
2001-12-21 21:35:47 +00:00
|
|
|
error = BUS_TEARDOWN_INTR(device_get_parent(dev), child, vec,
|
|
|
|
pc->pci_cookie);
|
2001-11-09 20:19:58 +00:00
|
|
|
/*
|
|
|
|
* Don't disable the interrupt for now, so that stray interupts get
|
|
|
|
* detected...
|
|
|
|
*/
|
|
|
|
if (error != 0)
|
|
|
|
free(pc, M_DEVBUF);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct resource *
|
|
|
|
psycho_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
|
|
|
u_long start, u_long end, u_long count, u_int flags)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
struct resource *rv;
|
|
|
|
struct rman *rm;
|
|
|
|
bus_space_tag_t bt;
|
|
|
|
bus_space_handle_t bh;
|
|
|
|
int needactivate = flags & RF_ACTIVE;
|
|
|
|
|
|
|
|
flags &= ~RF_ACTIVE;
|
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(bus);
|
|
|
|
if (type == SYS_RES_IRQ) {
|
|
|
|
/*
|
|
|
|
* XXX: Don't accept blank ranges for now, only single
|
|
|
|
* interrupts. The other case should not happen with the MI pci
|
|
|
|
* code...
|
|
|
|
* XXX: This may return a resource that is out of the range
|
|
|
|
* that was specified. Is this correct...?
|
|
|
|
*/
|
|
|
|
if (start != end)
|
|
|
|
panic("psycho_alloc_resource: XXX: interrupt range");
|
|
|
|
start = end |= sc->sc_ign;
|
2004-04-25 00:30:28 +00:00
|
|
|
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
|
|
|
|
rid, start, end, count, flags));
|
2001-11-09 20:19:58 +00:00
|
|
|
}
|
|
|
|
switch (type) {
|
|
|
|
case SYS_RES_MEMORY:
|
|
|
|
rm = &sc->sc_mem_rman;
|
|
|
|
bt = sc->sc_memt;
|
|
|
|
bh = sc->sc_bh[PCI_CS_MEM32];
|
|
|
|
break;
|
|
|
|
case SYS_RES_IOPORT:
|
|
|
|
rm = &sc->sc_io_rman;
|
|
|
|
bt = sc->sc_iot;
|
|
|
|
bh = sc->sc_bh[PCI_CS_IO];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = rman_reserve_resource(rm, start, end, count, flags, child);
|
|
|
|
if (rv == NULL)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
bh += rman_get_start(rv);
|
|
|
|
rman_set_bustag(rv, bt);
|
2001-12-21 21:35:47 +00:00
|
|
|
rman_set_bushandle(rv, bh);
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
if (needactivate) {
|
|
|
|
if (bus_activate_resource(child, type, *rid, rv)) {
|
|
|
|
rman_release_resource(rv);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
}
|
2001-12-21 21:35:47 +00:00
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_activate_resource(device_t bus, device_t child, int type, int rid,
|
|
|
|
struct resource *r)
|
|
|
|
{
|
2002-03-24 01:51:29 +00:00
|
|
|
void *p;
|
|
|
|
int error;
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
if (type == SYS_RES_IRQ)
|
2004-04-25 00:30:28 +00:00
|
|
|
return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
|
|
|
|
type, rid, r));
|
2002-03-24 01:51:29 +00:00
|
|
|
if (type == SYS_RES_MEMORY) {
|
|
|
|
/*
|
|
|
|
* Need to memory-map the device space, as some drivers depend
|
|
|
|
* on the virtual address being set and useable.
|
|
|
|
*/
|
|
|
|
error = sparc64_bus_mem_map(rman_get_bustag(r),
|
2003-12-26 14:04:19 +00:00
|
|
|
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
|
2002-03-24 01:51:29 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
rman_set_virtual(r, p);
|
|
|
|
}
|
2001-11-09 20:19:58 +00:00
|
|
|
return (rman_activate_resource(r));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
|
|
|
struct resource *r)
|
|
|
|
{
|
2001-12-21 21:35:47 +00:00
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
if (type == SYS_RES_IRQ)
|
2004-04-25 00:30:28 +00:00
|
|
|
return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
|
|
|
|
type, rid, r));
|
2002-03-24 01:51:29 +00:00
|
|
|
if (type == SYS_RES_MEMORY) {
|
|
|
|
sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r));
|
|
|
|
rman_set_virtual(r, NULL);
|
|
|
|
}
|
2001-11-09 20:19:58 +00:00
|
|
|
return (rman_deactivate_resource(r));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
psycho_release_resource(device_t bus, device_t child, int type, int rid,
|
2002-02-13 16:07:59 +00:00
|
|
|
struct resource *r)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (type == SYS_RES_IRQ)
|
2004-04-25 00:30:28 +00:00
|
|
|
return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
|
|
|
|
type, rid, r));
|
2001-11-09 20:19:58 +00:00
|
|
|
if (rman_get_flags(r) & RF_ACTIVE) {
|
|
|
|
error = bus_deactivate_resource(child, type, rid, r);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
return (rman_release_resource(r));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
psycho_intr_pending(device_t dev, ofw_pci_intr_t intr)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
u_long diag;
|
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(dev);
|
|
|
|
if (!psycho_find_intrmap(sc, intr, NULL, NULL, &diag)) {
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
device_printf(dev, "psycho_intr_pending: mapping not found for"
|
|
|
|
" %d\n", intr);
|
2001-11-09 20:19:58 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
return (diag != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bus_space_handle_t
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
psycho_get_bus_handle(device_t dev, int type, bus_space_handle_t childhdl,
|
|
|
|
bus_space_tag_t *tag)
|
2001-11-09 20:19:58 +00:00
|
|
|
{
|
|
|
|
struct psycho_softc *sc;
|
|
|
|
|
|
|
|
sc = (struct psycho_softc *)device_get_softc(dev);
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
switch (type) {
|
|
|
|
case SYS_RES_IOPORT:
|
2001-11-09 20:19:58 +00:00
|
|
|
*tag = sc->sc_iot;
|
|
|
|
return (sc->sc_bh[PCI_CS_IO] + childhdl);
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
case SYS_RES_MEMORY:
|
2001-11-09 20:19:58 +00:00
|
|
|
*tag = sc->sc_memt;
|
|
|
|
return (sc->sc_bh[PCI_CS_MEM32] + childhdl);
|
|
|
|
default:
|
|
|
|
panic("psycho_get_bus_handle: illegal space\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add the new sparc64 OFW PCI framework, conditional on options OFW_NEWPCI
for now. It introduces a OFW PCI bus driver and a generic OFW PCI-PCI
bridge driver. By utilizing these, the PCI handling is much more elegant
now.
The advantages of the new approach are:
- Device enumeration should hopefully be more like on Solaris now,
so unit numbers should match what's printed on the box more
closely.
- Real interrupt routing is implemented now, so cardbus bridges
etc. have at least a chance to work.
- The quirk tables are gone and have been replaced by (hopefully
sufficient) heuristics.
- Much cleaner code.
There was also a report that previously bogus interrupt assignments
are fixed now, which can be attributed to the new heuristics.
A pitfall, and the reason why this is not the default yet, is that
it changes device enumeration, as mentioned above, which can make
it necessary to change the system configuration if more than one
unit of a device type is present (on a system with two hme cars,
for example, it is possible that hme0 becomes hme1 and vice versa
after enabling the option). Systems with multiple disk controllers
may need to be booted into single user (and require manual specification
of the root file system on boot) to adjust the fstab.
Nevertheless, I would like to encourage users to use this option,
so that it can be made the default soon.
In detail, the changes are:
- Introduce an OFW PCI bus driver; it inherits most methods from the
generic PCI bus driver, but uses the firmware for enumeration,
performs additional initialization for devices and firmware-specific
interrupt routing. It also implements an OFW-specific method to allow
child devices to get their firmware nodes.
- Introduce an OFW PCI-PCI bridge driver; again, it inherits most
of the generic PCI-PCI bridge driver; it has it's own method for
interrupt routing, as well as some sparc64-specific methods (one to
get the node again, and one to adjust the bridge bus range, since
we need to reenumerate all PCI buses).
- Convert the apb driver to the new way of handling things.
- Provide a common framework for OFW bridge drivers, used be the two
drivers above.
- Provide a small common framework for interrupt routing (for all
bridge types).
- Convert the psycho driver to the new framework; this gets rid of a
bunch of old kludges in pci_read_config(), and the whole
preinitialization (ofw_pci_init()).
- Convert the ISA MD part and the EBus driver to the new way
interrupts and nodes are handled.
- Introduce types for firmware interrupt properties.
- Rename the old sparcbus_if to ofw_pci_if by repo copy (it is only
required for PCI), and move it to a more correct location (new
support methodsx were also added, and an old one was deprecated).
- Fix a bunch of minor bugs, perform some cleanups.
In some cases, I introduced some minor code duplication to keep the
new code clean, in hopes that the old code will be unifdef'ed soon.
Reviewed in part by: imp
Tested by: jake, Marius Strobl <marius@alchemy.franken.de>,
Sergey Mokryshev <mokr@mokr.net>,
Chris Jackman <cjackNOSPAM@klatsch.org>
Info on u30 firmware provided by: kris
2003-07-01 14:52:47 +00:00
|
|
|
static phandle_t
|
|
|
|
psycho_get_node(device_t bus, device_t dev)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = device_get_softc(bus);
|
|
|
|
|
|
|
|
/* We only have one child, the PCI bus, which needs our own node. */
|
|
|
|
return (sc->sc_node);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
psycho_adjust_busrange(device_t dev, u_int subbus)
|
|
|
|
{
|
|
|
|
struct psycho_softc *sc = device_get_softc(dev);
|
|
|
|
|
|
|
|
/* If necessary, adjust the subordinate bus number register. */
|
|
|
|
if (subbus > sc->sc_subbus) {
|
|
|
|
#ifdef PSYCHO_DEBUG
|
|
|
|
device_printf(dev,
|
|
|
|
"adjusting secondary bus number from %d to %d\n",
|
|
|
|
sc->sc_subbus, subbus);
|
|
|
|
#endif
|
|
|
|
sc->sc_subbus = subbus;
|
|
|
|
PCIB_WRITE_CONFIG(dev, sc->sc_secbus, PCS_DEVICE, PCS_FUNC,
|
|
|
|
PCSR_SUBBUS, subbus, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-09 20:19:58 +00:00
|
|
|
static bus_space_tag_t
|
|
|
|
psycho_alloc_bus_tag(struct psycho_softc *sc, int type)
|
|
|
|
{
|
|
|
|
bus_space_tag_t bt;
|
|
|
|
|
2002-02-13 16:07:59 +00:00
|
|
|
bt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF,
|
|
|
|
M_NOWAIT | M_ZERO);
|
2001-11-09 20:19:58 +00:00
|
|
|
if (bt == NULL)
|
2002-02-13 16:07:59 +00:00
|
|
|
panic("psycho_alloc_bus_tag: out of memory");
|
2001-11-09 20:19:58 +00:00
|
|
|
|
|
|
|
bzero(bt, sizeof *bt);
|
2003-01-06 19:43:10 +00:00
|
|
|
bt->bst_cookie = sc;
|
|
|
|
bt->bst_parent = sc->sc_bustag;
|
|
|
|
bt->bst_type = type;
|
2001-11-09 20:19:58 +00:00
|
|
|
return (bt);
|
|
|
|
}
|