mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-07 13:14:51 +00:00
Implement an EISA new-bus framework. The old driver probe mechanism
had a quirk that made a shim rather hard to implement properly and it was just easier to convert the drivers in one go. The changes to the buslogic driver go beyond just this - the whole driver was new-bus'ed including pci and isa. I have only tested the EISA part of this so far. Submitted by: Doug Rabson <dfr@nlsystems.com>
This commit is contained in:
parent
a7375c7225
commit
a49a3d4433
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=45791
@ -34,7 +34,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
|
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
|
||||||
* $Id: autoconf.c,v 1.112 1999/04/15 14:52:24 bde Exp $
|
* $Id: autoconf.c,v 1.113 1999/04/16 21:22:11 peter Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -232,10 +232,6 @@ configure(dummy)
|
|||||||
INTREN(IRQ_SLAVE);
|
INTREN(IRQ_SLAVE);
|
||||||
#endif /* APIC_IO */
|
#endif /* APIC_IO */
|
||||||
|
|
||||||
#if NEISA > 0
|
|
||||||
eisa_configure();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NPNP > 0
|
#if NPNP > 0
|
||||||
pnp_configure();
|
pnp_configure();
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: adv_eisa.c,v 1.1 1998/09/15 07:05:39 gibbs Exp $
|
* $Id: adv_eisa.c,v 1.2 1998/12/22 18:14:09 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -41,9 +41,13 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
@ -69,9 +73,6 @@
|
|||||||
#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL)
|
#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL)
|
||||||
#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL)
|
#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL)
|
||||||
|
|
||||||
static int adveisaprobe(void);
|
|
||||||
static int adveisaattach(struct eisa_device *e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The overrun buffer shared amongst all EISA adapters.
|
* The overrun buffer shared amongst all EISA adapters.
|
||||||
*/
|
*/
|
||||||
@ -80,22 +81,10 @@ static bus_dma_tag_t overrun_dmat;
|
|||||||
static bus_dmamap_t overrun_dmamap;
|
static bus_dmamap_t overrun_dmamap;
|
||||||
static bus_addr_t overrun_physbase;
|
static bus_addr_t overrun_physbase;
|
||||||
|
|
||||||
static struct eisa_driver adv_eisa_driver =
|
|
||||||
{
|
|
||||||
"adv",
|
|
||||||
adveisaprobe,
|
|
||||||
adveisaattach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&adv_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, adv_eisa_driver);
|
|
||||||
|
|
||||||
static const char *adveisamatch(eisa_id_t type);
|
static const char *adveisamatch(eisa_id_t type);
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
adveisamatch(type)
|
adveisamatch(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch (type & ~0xF) {
|
switch (type & ~0xF) {
|
||||||
case EISA_DEVICE_ID_ADVANSYS_740:
|
case EISA_DEVICE_ID_ADVANSYS_740:
|
||||||
@ -111,69 +100,78 @@ adveisamatch(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
adveisaprobe(void)
|
adveisaprobe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_int32_t iobase;
|
u_int32_t iobase;
|
||||||
u_int8_t irq;
|
u_int8_t irq;
|
||||||
struct eisa_device *e_dev = NULL;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count = 0;
|
desc = adveisamatch(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, adveisamatch))) {
|
if (!desc)
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
|
return (ENXIO);
|
||||||
+ ADV_EISA_SLOT_OFFSET;
|
device_set_desc(dev, desc);
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE)
|
||||||
irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
|
+ ADV_EISA_SLOT_OFFSET;
|
||||||
irq &= ADV_EISA_IRQ_MASK;
|
|
||||||
switch (irq) {
|
eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
case 0:
|
irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
|
||||||
case 1:
|
irq &= ADV_EISA_IRQ_MASK;
|
||||||
case 2:
|
switch (irq) {
|
||||||
case 4:
|
case 0:
|
||||||
case 5:
|
case 1:
|
||||||
break;
|
case 2:
|
||||||
default:
|
case 4:
|
||||||
printf("adv at slot %d: illegal "
|
case 5:
|
||||||
"irq setting %d\n", e_dev->ioconf.slot,
|
break;
|
||||||
irq);
|
default:
|
||||||
continue;
|
printf("adv at slot %d: illegal "
|
||||||
}
|
"irq setting %d\n", eisa_get_slot(dev),
|
||||||
eisa_add_intr(e_dev, irq + 10);
|
irq);
|
||||||
eisa_registerdev(e_dev, &adv_eisa_driver);
|
return ENXIO;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
eisa_add_intr(dev, irq + 10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
adveisaattach(struct eisa_device *e_dev)
|
adveisaattach(device_t dev)
|
||||||
{
|
{
|
||||||
struct adv_softc *adv;
|
struct adv_softc *adv;
|
||||||
struct adv_softc *adv_b;
|
struct adv_softc *adv_b;
|
||||||
resvaddr_t *iospace;
|
struct resource *io;
|
||||||
int unit;
|
struct resource *irq;
|
||||||
int irq;
|
int unit = device_get_unit(dev);
|
||||||
int error;
|
int rid, error;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
adv_b = NULL;
|
adv_b = NULL;
|
||||||
unit = e_dev->unit;
|
|
||||||
iospace = e_dev->ioconf.ioaddrs.lh_first;
|
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
rid = 0;
|
||||||
return (-1);
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "No irq?!\n");
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
if (!iospace)
|
}
|
||||||
return (-1);
|
|
||||||
|
|
||||||
switch (e_dev->id & ~0xF) {
|
switch (eisa_get_id(dev) & ~0xF) {
|
||||||
case EISA_DEVICE_ID_ADVANSYS_750:
|
case EISA_DEVICE_ID_ADVANSYS_750:
|
||||||
adv_b = adv_alloc(unit, I386_BUS_SPACE_IO,
|
adv_b = adv_alloc(unit, rman_get_bustag(io),
|
||||||
iospace->addr + ADV_EISA_OFFSET_CHAN2);
|
rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2);
|
||||||
if (adv_b == NULL)
|
if (adv_b == NULL)
|
||||||
return (-1);
|
goto bad;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a parent dmatag for all tags created
|
* Allocate a parent dmatag for all tags created
|
||||||
@ -195,19 +193,19 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
printf("%s: Could not allocate DMA tag - error %d\n",
|
printf("%s: Could not allocate DMA tag - error %d\n",
|
||||||
adv_name(adv_b), error);
|
adv_name(adv_b), error);
|
||||||
adv_free(adv_b);
|
adv_free(adv_b);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
adv_b->init_level++;
|
adv_b->init_level++;
|
||||||
|
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case EISA_DEVICE_ID_ADVANSYS_740:
|
case EISA_DEVICE_ID_ADVANSYS_740:
|
||||||
adv = adv_alloc(unit, I386_BUS_SPACE_IO,
|
adv = adv_alloc(unit, rman_get_bustag(io),
|
||||||
iospace->addr + ADV_EISA_OFFSET_CHAN1);
|
rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1);
|
||||||
if (adv == NULL) {
|
if (adv == NULL) {
|
||||||
if (adv_b != NULL)
|
if (adv_b != NULL)
|
||||||
adv_free(adv_b);
|
adv_free(adv_b);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -230,14 +228,14 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
printf("%s: Could not allocate DMA tag - error %d\n",
|
printf("%s: Could not allocate DMA tag - error %d\n",
|
||||||
adv_name(adv), error);
|
adv_name(adv), error);
|
||||||
adv_free(adv);
|
adv_free(adv);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
adv->init_level++;
|
adv->init_level++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("adveisaattach: Unknown device type!\n");
|
printf("adveisaattach: Unknown device type!\n");
|
||||||
return (-1);
|
goto bad;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +254,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
/*flags*/0,
|
/*flags*/0,
|
||||||
&overrun_dmat) != 0) {
|
&overrun_dmat) != 0) {
|
||||||
adv_free(adv);
|
adv_free(adv);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
if (bus_dmamem_alloc(overrun_dmat,
|
if (bus_dmamem_alloc(overrun_dmat,
|
||||||
(void **)&overrun_buf,
|
(void **)&overrun_buf,
|
||||||
@ -264,7 +262,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
&overrun_dmamap) != 0) {
|
&overrun_dmamap) != 0) {
|
||||||
bus_dma_tag_destroy(overrun_dmat);
|
bus_dma_tag_destroy(overrun_dmat);
|
||||||
adv_free(adv);
|
adv_free(adv);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
/* And permanently map it in */
|
/* And permanently map it in */
|
||||||
bus_dmamap_load(overrun_dmat, overrun_dmamap,
|
bus_dmamap_load(overrun_dmat, overrun_dmamap,
|
||||||
@ -273,23 +271,6 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
/*flags*/0);
|
/*flags*/0);
|
||||||
}
|
}
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, iospace)) {
|
|
||||||
adv_free(adv);
|
|
||||||
if (adv_b != NULL)
|
|
||||||
adv_free(adv_b);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, adv_intr, (void *)adv, &cam_imask,
|
|
||||||
/*shared ==*/TRUE)) {
|
|
||||||
adv_free(adv);
|
|
||||||
if (adv_b != NULL)
|
|
||||||
adv_free(adv_b);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we know we own the resources we need, do the
|
* Now that we know we own the resources we need, do the
|
||||||
* card initialization.
|
* card initialization.
|
||||||
@ -301,7 +282,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
|
ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
|
||||||
ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
|
ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
|
||||||
|
|
||||||
adv->chip_version = EISA_REVISION_ID(e_dev->id)
|
adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
|
||||||
+ ADV_CHIP_MIN_VER_EISA - 1;
|
+ ADV_CHIP_MIN_VER_EISA - 1;
|
||||||
|
|
||||||
if (adv_init(adv) != 0) {
|
if (adv_init(adv) != 0) {
|
||||||
@ -321,7 +302,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
|
ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
|
||||||
ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
|
ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
|
||||||
|
|
||||||
adv_b->chip_version = EISA_REVISION_ID(e_dev->id)
|
adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
|
||||||
+ ADV_CHIP_MIN_VER_EISA - 1;
|
+ ADV_CHIP_MIN_VER_EISA - 1;
|
||||||
|
|
||||||
if (adv_init(adv_b) != 0) {
|
if (adv_init(adv_b) != 0) {
|
||||||
@ -335,13 +316,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
/*
|
/*
|
||||||
* Enable our interrupt handler.
|
* Enable our interrupt handler.
|
||||||
*/
|
*/
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
bus_setup_intr(dev, irq, adv_intr, adv, &ih);
|
||||||
adv_free(adv);
|
|
||||||
if (adv_b != NULL)
|
|
||||||
adv_free(adv_b);
|
|
||||||
eisa_release_intr(e_dev, irq, adv_intr);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attach sub-devices - always succeeds */
|
/* Attach sub-devices - always succeeds */
|
||||||
adv_attach(adv);
|
adv_attach(adv);
|
||||||
@ -349,6 +324,30 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
adv_attach(adv_b);
|
adv_attach(adv_b);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t adv_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, adveisaprobe),
|
||||||
|
DEVMETHOD(device_attach, adveisaattach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t adv_eisa_driver = {
|
||||||
|
"adv",
|
||||||
|
adv_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t adv_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: ahb.c,v 1.7 1999/03/05 23:37:07 gibbs Exp $
|
* $Id: ahb.c,v 1.8 1999/04/11 03:06:05 eivind Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -36,10 +36,14 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <cam/cam.h>
|
#include <cam/cam.h>
|
||||||
#include <cam/cam_ccb.h>
|
#include <cam/cam_ccb.h>
|
||||||
@ -71,9 +75,7 @@
|
|||||||
bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value)
|
bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value)
|
||||||
|
|
||||||
static const char *ahbmatch(eisa_id_t type);
|
static const char *ahbmatch(eisa_id_t type);
|
||||||
static int ahbprobe(void);
|
static struct ahb_softc *ahballoc(u_long unit, u_int iobase);
|
||||||
static int ahbattach(struct eisa_device *dev);
|
|
||||||
static struct ahb_softc *ahballoc(u_long unit, u_int iobase, u_int irq);
|
|
||||||
static void ahbfree(struct ahb_softc *ahb);
|
static void ahbfree(struct ahb_softc *ahb);
|
||||||
static int ahbreset(struct ahb_softc *ahb);
|
static int ahbreset(struct ahb_softc *ahb);
|
||||||
static void ahbmapecbs(void *arg, bus_dma_segment_t *segs,
|
static void ahbmapecbs(void *arg, bus_dma_segment_t *segs,
|
||||||
@ -184,19 +186,6 @@ ahbqueuembox(struct ahb_softc *ahb, u_int32_t mboxval, u_int attn_code)
|
|||||||
ahb_outb(ahb, ATTN, attn_code);
|
ahb_outb(ahb, ATTN, attn_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u_long ahbunit;
|
|
||||||
|
|
||||||
static struct eisa_driver ahb_eisa_driver =
|
|
||||||
{
|
|
||||||
"ahb",
|
|
||||||
ahbprobe,
|
|
||||||
ahbattach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&ahbunit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, ahb_eisa_driver);
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
ahbmatch(eisa_id_t type)
|
ahbmatch(eisa_id_t type)
|
||||||
{
|
{
|
||||||
@ -211,98 +200,93 @@ ahbmatch(eisa_id_t type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ahbprobe(void)
|
ahbprobe(device_t dev)
|
||||||
{
|
{
|
||||||
struct eisa_device *e_dev = NULL;
|
const char *desc;
|
||||||
u_int32_t iobase;
|
u_int32_t iobase;
|
||||||
u_int32_t irq;
|
u_int32_t irq;
|
||||||
int count;
|
u_int8_t intdef;
|
||||||
|
|
||||||
count = 0;
|
desc = ahbmatch(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, ahbmatch))) {
|
if (!desc)
|
||||||
u_int8_t intdef;
|
return (ENXIO);
|
||||||
|
device_set_desc(dev, desc);
|
||||||
|
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE) +
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) +
|
||||||
AHB_EISA_SLOT_OFFSET;
|
AHB_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
intdef = inb(INTDEF + iobase);
|
intdef = inb(INTDEF + iobase);
|
||||||
switch (intdef & 0x7) {
|
switch (intdef & 0x7) {
|
||||||
case INT9:
|
case INT9:
|
||||||
irq = 9;
|
irq = 9;
|
||||||
break;
|
break;
|
||||||
case INT10:
|
case INT10:
|
||||||
irq = 10;
|
irq = 10;
|
||||||
break;
|
break;
|
||||||
case INT11:
|
case INT11:
|
||||||
irq = 11;
|
irq = 11;
|
||||||
break;
|
break;
|
||||||
case INT12:
|
case INT12:
|
||||||
irq = 12;
|
irq = 12;
|
||||||
break;
|
break;
|
||||||
case INT14:
|
case INT14:
|
||||||
irq = 14;
|
irq = 14;
|
||||||
break;
|
break;
|
||||||
case INT15:
|
case INT15:
|
||||||
irq = 15;
|
irq = 15;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Adaptec 174X at slot %d: illegal "
|
printf("Adaptec 174X at slot %d: illegal "
|
||||||
"irq setting %d\n", e_dev->ioconf.slot,
|
"irq setting %d\n", eisa_get_slot(dev),
|
||||||
(intdef & 0x7));
|
(intdef & 0x7));
|
||||||
irq = 0;
|
irq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (irq == 0)
|
|
||||||
continue;
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &ahb_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
if (irq == 0)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ahbattach(struct eisa_device *e_dev)
|
ahbattach(device_t dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* find unit and check we have that many defined
|
* find unit and check we have that many defined
|
||||||
*/
|
*/
|
||||||
struct ahb_softc *ahb;
|
struct ahb_softc *ahb;
|
||||||
struct ecb* next_ecb;
|
struct ecb* next_ecb;
|
||||||
resvaddr_t *iospace;
|
struct resource *io = 0;
|
||||||
u_int irq;
|
struct resource *irq = 0;
|
||||||
|
int shared, rid;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
rid = 0;
|
||||||
return (-1);
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
iospace = e_dev->ioconf.ioaddrs.lh_first;
|
return ENOMEM;
|
||||||
|
|
||||||
if (iospace == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, iospace)) {
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ahb = ahballoc(e_dev->unit, iospace->addr, irq)) == NULL) {
|
if ((ahb = ahballoc(device_get_unit(dev), rman_get_start(io))) == NULL) {
|
||||||
eisa_reg_end(e_dev);
|
goto error_exit2;
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ahbreset(ahb) != 0)
|
if (ahbreset(ahb) != 0)
|
||||||
return (-1);
|
goto error_exit;
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, ahbintr, (void *)ahb, &cam_imask,
|
shared = (ahb_inb(ahb, INTDEF) & INTLEVEL) ? RF_SHAREABLE : 0;
|
||||||
(ahb_inb(ahb, INTDEF) & INTLEVEL) ? TRUE : FALSE)) {
|
rid = 0;
|
||||||
eisa_reg_end(e_dev);
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
ahbfree(ahb);
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
return (-1);
|
if (!irq) {
|
||||||
|
device_printf(dev, "Can't allocate interrupt\n");
|
||||||
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -377,8 +361,6 @@ ahbattach(struct eisa_device *e_dev)
|
|||||||
|
|
||||||
ahb->init_level++;
|
ahb->init_level++;
|
||||||
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we know we own the resources we need, register
|
* Now that we know we own the resources we need, register
|
||||||
* our bus with the XPT.
|
* our bus with the XPT.
|
||||||
@ -387,21 +369,26 @@ ahbattach(struct eisa_device *e_dev)
|
|||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
/* Enable our interrupt */
|
/* Enable our interrupt */
|
||||||
eisa_enable_intr(e_dev, irq);
|
bus_setup_intr(dev, irq, ahbintr, ahb, &ih);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error_exit:
|
error_exit:
|
||||||
/*
|
/*
|
||||||
* The board's IRQ line will not be left enabled
|
* The board's IRQ line will not be left enabled
|
||||||
* if we can't intialize correctly, so its safe
|
* if we can't intialize correctly, so its safe
|
||||||
* to release the irq.
|
* to release the irq.
|
||||||
*/
|
*/
|
||||||
eisa_release_intr(e_dev, irq, ahbintr);
|
|
||||||
ahbfree(ahb);
|
ahbfree(ahb);
|
||||||
|
error_exit2:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ahb_softc *
|
static struct ahb_softc *
|
||||||
ahballoc(u_long unit, u_int iobase, u_int irq)
|
ahballoc(u_long unit, u_int iobase)
|
||||||
{
|
{
|
||||||
struct ahb_softc *ahb;
|
struct ahb_softc *ahb;
|
||||||
|
|
||||||
@ -1348,4 +1335,23 @@ ahbtimeout(void *arg)
|
|||||||
splx(s);
|
splx(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t ahb_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, ahbprobe),
|
||||||
|
DEVMETHOD(device_attach, ahbattach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ahb_eisa_driver = {
|
||||||
|
"ahb",
|
||||||
|
ahb_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ahb_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(ahb, eisa, ahb_eisa_driver, ahb_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA */
|
#endif /* NEISA */
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: ahc_eisa.c,v 1.4 1998/12/15 08:24:45 gibbs Exp $
|
* $Id: ahc_eisa.c,v 1.5 1999/03/05 23:28:42 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -35,9 +35,13 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
@ -61,26 +65,12 @@
|
|||||||
#define AHC_EISA_IOSIZE 0x100
|
#define AHC_EISA_IOSIZE 0x100
|
||||||
#define INTDEF 0x5cul /* Interrupt Definition Register */
|
#define INTDEF 0x5cul /* Interrupt Definition Register */
|
||||||
|
|
||||||
static int aic7770probe(void);
|
|
||||||
static int aic7770_attach(struct eisa_device *e_dev);
|
|
||||||
static void aha2840_load_seeprom(struct ahc_softc *ahc);
|
static void aha2840_load_seeprom(struct ahc_softc *ahc);
|
||||||
|
|
||||||
static struct eisa_driver ahc_eisa_driver =
|
|
||||||
{
|
|
||||||
"ahc",
|
|
||||||
aic7770probe,
|
|
||||||
aic7770_attach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&ahc_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, ahc_eisa_driver);
|
|
||||||
|
|
||||||
static const char *aic7770_match(eisa_id_t type);
|
static const char *aic7770_match(eisa_id_t type);
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
aic7770_match(type)
|
aic7770_match(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
||||||
@ -100,75 +90,75 @@ aic7770_match(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
aic7770probe(void)
|
aic7770_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_int32_t iobase;
|
u_int32_t iobase;
|
||||||
u_int32_t irq;
|
u_int32_t irq;
|
||||||
u_int8_t intdef;
|
u_int8_t intdef;
|
||||||
u_int8_t hcntrl;
|
u_int8_t hcntrl;
|
||||||
struct eisa_device *e_dev;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
e_dev = NULL;
|
desc = aic7770_match(eisa_get_id(dev));
|
||||||
count = 0;
|
if (!desc)
|
||||||
while ((e_dev = eisa_match_dev(e_dev, aic7770_match))) {
|
return (ENXIO);
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
|
device_set_desc(dev, desc);
|
||||||
+ AHC_EISA_SLOT_OFFSET;
|
|
||||||
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE)
|
||||||
|
+ AHC_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
/* Pause the card preseving the IRQ type */
|
/* Pause the card preseving the IRQ type */
|
||||||
hcntrl = inb(iobase + HCNTRL) & IRQMS;
|
hcntrl = inb(iobase + HCNTRL) & IRQMS;
|
||||||
|
|
||||||
outb(iobase + HCNTRL, hcntrl | PAUSE);
|
outb(iobase + HCNTRL, hcntrl | PAUSE);
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
intdef = inb(INTDEF + iobase);
|
intdef = inb(INTDEF + iobase);
|
||||||
irq = intdef & 0xf;
|
irq = intdef & 0xf;
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case 9:
|
case 9:
|
||||||
case 10:
|
case 10:
|
||||||
case 11:
|
case 11:
|
||||||
case 12:
|
case 12:
|
||||||
case 14:
|
case 14:
|
||||||
case 15:
|
case 15:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("aic7770 at slot %d: illegal "
|
printf("aic7770 at slot %d: illegal "
|
||||||
"irq setting %d\n", e_dev->ioconf.slot,
|
"irq setting %d\n", eisa_get_slot(dev),
|
||||||
intdef);
|
intdef);
|
||||||
irq = 0;
|
irq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (irq == 0)
|
|
||||||
continue;
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &ahc_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
if (irq == 0)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
aic7770_attach(struct eisa_device *e_dev)
|
aic7770_attach(device_t dev)
|
||||||
{
|
{
|
||||||
ahc_chip chip;
|
ahc_chip chip;
|
||||||
|
|
||||||
struct ahc_softc *ahc;
|
struct ahc_softc *ahc;
|
||||||
resvaddr_t *iospace;
|
struct resource *io = 0;
|
||||||
int unit = e_dev->unit;
|
struct resource *irq = 0;
|
||||||
int irq;
|
int unit = device_get_unit(dev);
|
||||||
int error;
|
int error, rid;
|
||||||
|
int shared;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
rid = 0;
|
||||||
return (-1);
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
switch (eisa_get_id(dev)) {
|
||||||
|
|
||||||
iospace = e_dev->ioconf.ioaddrs.lh_first;
|
|
||||||
|
|
||||||
if (!iospace)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
switch (e_dev->id) {
|
|
||||||
case EISA_DEVICE_ID_ADAPTEC_274x:
|
case EISA_DEVICE_ID_ADAPTEC_274x:
|
||||||
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
||||||
chip = AHC_AIC7770|AHC_EISA;
|
chip = AHC_AIC7770|AHC_EISA;
|
||||||
@ -179,13 +169,12 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("aic7770_attach: Unknown device type!\n");
|
printf("aic7770_attach: Unknown device type!\n");
|
||||||
return -1;
|
goto bad;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ahc = ahc_alloc(unit, iospace->addr, NULL,
|
if (!(ahc = ahc_alloc(unit, rman_get_start(io), NULL,
|
||||||
chip, AHC_AIC7770_FE, AHC_FNONE, NULL)))
|
chip, AHC_AIC7770_FE, AHC_FNONE, NULL)))
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
ahc->channel = 'A';
|
ahc->channel = 'A';
|
||||||
ahc->channel_b = 'B';
|
ahc->channel_b = 'B';
|
||||||
@ -204,31 +193,27 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
printf("%s: Could not allocate DMA tag - error %d\n",
|
printf("%s: Could not allocate DMA tag - error %d\n",
|
||||||
ahc_name(ahc), error);
|
ahc_name(ahc), error);
|
||||||
ahc_free(ahc);
|
ahc_free(ahc);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, iospace)) {
|
|
||||||
ahc_free(ahc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ahc_reset(ahc) != 0) {
|
if (ahc_reset(ahc) != 0) {
|
||||||
ahc_free(ahc);
|
ahc_free(ahc);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The IRQMS bit enables level sensitive interrupts. Only allow
|
* The IRQMS bit enables level sensitive interrupts. Only allow
|
||||||
* IRQ sharing if it's set.
|
* IRQ sharing if it's set.
|
||||||
*/
|
*/
|
||||||
if (eisa_reg_intr(e_dev, irq, ahc_intr, (void *)ahc, &cam_imask,
|
shared = (ahc->pause & IRQMS) ? RF_SHAREABLE : 0;
|
||||||
/*shared ==*/ahc->pause & IRQMS)) {
|
rid = 0;
|
||||||
ahc_free(ahc);
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
return -1;
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "Can't allocate interrupt\n");
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the user what type of interrupts we're using.
|
* Tell the user what type of interrupts we're using.
|
||||||
@ -355,8 +340,7 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
* The board's IRQ line is not yet enabled so it's safe
|
* The board's IRQ line is not yet enabled so it's safe
|
||||||
* to release the irq.
|
* to release the irq.
|
||||||
*/
|
*/
|
||||||
eisa_release_intr(e_dev, irq, ahc_intr);
|
goto bad;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -367,16 +351,20 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
/*
|
/*
|
||||||
* Enable our interrupt handler.
|
* Enable our interrupt handler.
|
||||||
*/
|
*/
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
if (bus_setup_intr(dev, irq, ahc_intr, ahc, &ih))
|
||||||
ahc_free(ahc);
|
goto bad;
|
||||||
eisa_release_intr(e_dev, irq, ahc_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attach sub-devices - always succeeds */
|
/* Attach sub-devices - always succeeds */
|
||||||
ahc_attach(ahc);
|
ahc_attach(ahc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -474,4 +462,23 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t ahc_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, aic7770_probe),
|
||||||
|
DEVMETHOD(device_attach, aic7770_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ahc_eisa_driver = {
|
||||||
|
"ahc",
|
||||||
|
ahc_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ahc_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(ahc, eisa, ahc_eisa_driver, ahc_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt.c,v 1.14 1999/03/08 21:36:33 gibbs Exp $
|
* $Id: bt.c,v 1.15 1999/04/07 23:01:43 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -46,6 +46,7 @@
|
|||||||
#include <sys/buf.h>
|
#include <sys/buf.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX It appears that BusLogic PCI adapters go out to lunch if you
|
* XXX It appears that BusLogic PCI adapters go out to lunch if you
|
||||||
@ -60,6 +61,7 @@
|
|||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <cam/cam.h>
|
#include <cam/cam.h>
|
||||||
#include <cam/cam_ccb.h>
|
#include <cam/cam_ccb.h>
|
||||||
@ -208,48 +210,29 @@ u_int16_t bt_board_ports[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Exported functions */
|
/* Exported functions */
|
||||||
struct bt_softc *
|
void
|
||||||
bt_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh)
|
bt_init_softc(device_t dev, struct resource *port,
|
||||||
|
struct resource *irq, struct resource *drq)
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
if (unit != BT_TEMP_UNIT) {
|
|
||||||
if (unit >= NBT) {
|
|
||||||
printf("bt: unit number (%d) too high\n", unit);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a storage area for us
|
|
||||||
*/
|
|
||||||
if (bt_softcs[unit]) {
|
|
||||||
printf("bt%d: memory already allocated\n", unit);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bt = malloc(sizeof(struct bt_softc), M_DEVBUF, M_NOWAIT);
|
|
||||||
if (!bt) {
|
|
||||||
printf("bt%d: cannot malloc!\n", unit);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
bzero(bt, sizeof(struct bt_softc));
|
|
||||||
SLIST_INIT(&bt->free_bt_ccbs);
|
SLIST_INIT(&bt->free_bt_ccbs);
|
||||||
LIST_INIT(&bt->pending_ccbs);
|
LIST_INIT(&bt->pending_ccbs);
|
||||||
SLIST_INIT(&bt->sg_maps);
|
SLIST_INIT(&bt->sg_maps);
|
||||||
bt->unit = unit;
|
bt->dev = dev;
|
||||||
bt->tag = tag;
|
bt->unit = device_get_unit(dev);
|
||||||
bt->bsh = bsh;
|
bt->port = port;
|
||||||
|
bt->irq = irq;
|
||||||
if (bt->unit != BT_TEMP_UNIT) {
|
bt->drq = drq;
|
||||||
bt_softcs[unit] = bt;
|
bt->tag = rman_get_bustag(port);
|
||||||
}
|
bt->bsh = rman_get_bushandle(port);
|
||||||
return (bt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bt_free(struct bt_softc *bt)
|
bt_free_softc(device_t dev)
|
||||||
{
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
switch (bt->init_level) {
|
switch (bt->init_level) {
|
||||||
default:
|
default:
|
||||||
case 11:
|
case 11:
|
||||||
@ -294,20 +277,17 @@ bt_free(struct bt_softc *bt)
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (bt->unit != BT_TEMP_UNIT) {
|
|
||||||
bt_softcs[bt->unit] = NULL;
|
|
||||||
}
|
|
||||||
free(bt, M_DEVBUF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bt_port_probe(struct bt_softc *bt, struct bt_probe_info *info)
|
bt_port_probe(device_t dev, struct bt_probe_info *info)
|
||||||
{
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
config_data_t config_data;
|
config_data_t config_data;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* See if there is really a card present */
|
/* See if there is really a card present */
|
||||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt))
|
if (bt_probe(dev) || bt_fetch_adapter_info(dev))
|
||||||
return(1);
|
return(1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -365,8 +345,9 @@ bt_port_probe(struct bt_softc *bt, struct bt_probe_info *info)
|
|||||||
* Probe the adapter and verify that the card is a BusLogic.
|
* Probe the adapter and verify that the card is a BusLogic.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
bt_probe(struct bt_softc* bt)
|
bt_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
esetup_info_data_t esetup_info;
|
esetup_info_data_t esetup_info;
|
||||||
u_int status;
|
u_int status;
|
||||||
u_int intstat;
|
u_int intstat;
|
||||||
@ -384,21 +365,21 @@ bt_probe(struct bt_softc* bt)
|
|||||||
|| (status & (DIAG_ACTIVE|CMD_REG_BUSY|
|
|| (status & (DIAG_ACTIVE|CMD_REG_BUSY|
|
||||||
STATUS_REG_RSVD|CMD_INVALID)) != 0) {
|
STATUS_REG_RSVD|CMD_INVALID)) != 0) {
|
||||||
if (bootverbose)
|
if (bootverbose)
|
||||||
printf("%s: Failed Status Reg Test - %x\n", bt_name(bt),
|
device_printf(dev, "Failed Status Reg Test - %x\n",
|
||||||
status);
|
status);
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
intstat = bt_inb(bt, INTSTAT_REG);
|
intstat = bt_inb(bt, INTSTAT_REG);
|
||||||
if ((intstat & INTSTAT_REG_RSVD) != 0) {
|
if ((intstat & INTSTAT_REG_RSVD) != 0) {
|
||||||
printf("%s: Failed Intstat Reg Test\n", bt_name(bt));
|
device_printf(dev, "Failed Intstat Reg Test\n");
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry = bt_inb(bt, GEOMETRY_REG);
|
geometry = bt_inb(bt, GEOMETRY_REG);
|
||||||
if (geometry == 0xFF) {
|
if (geometry == 0xFF) {
|
||||||
if (bootverbose)
|
if (bootverbose)
|
||||||
printf("%s: Failed Geometry Reg Test\n", bt_name(bt));
|
device_printf(dev, "Failed Geometry Reg Test\n");
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +390,7 @@ bt_probe(struct bt_softc* bt)
|
|||||||
*/
|
*/
|
||||||
if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) {
|
if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) {
|
||||||
if (bootverbose)
|
if (bootverbose)
|
||||||
printf("%s: Failed Reset\n", bt_name(bt));
|
device_printf(dev, "Failed Reset\n");
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,8 +409,9 @@ bt_probe(struct bt_softc* bt)
|
|||||||
* Pull the boards setup information and record it in our softc.
|
* Pull the boards setup information and record it in our softc.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
bt_fetch_adapter_info(struct bt_softc *bt)
|
bt_fetch_adapter_info(device_t dev)
|
||||||
{
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
board_id_data_t board_id;
|
board_id_data_t board_id;
|
||||||
esetup_info_data_t esetup_info;
|
esetup_info_data_t esetup_info;
|
||||||
config_data_t config_data;
|
config_data_t config_data;
|
||||||
@ -441,8 +423,7 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
(u_int8_t*)&board_id, sizeof(board_id),
|
(u_int8_t*)&board_id, sizeof(board_id),
|
||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed Get Board Info\n",
|
device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n");
|
||||||
bt_name(bt));
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
bt->firmware_ver[0] = board_id.firmware_rev_major;
|
bt->firmware_ver[0] = board_id.firmware_rev_major;
|
||||||
@ -460,8 +441,9 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
(u_int8_t*)&bt->firmware_ver[3], 1,
|
(u_int8_t*)&bt->firmware_ver[3], 1,
|
||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed Get "
|
device_printf(dev,
|
||||||
"Firmware 3rd Digit\n", bt_name(bt));
|
"bt_fetch_adapter_info - Failed Get "
|
||||||
|
"Firmware 3rd Digit\n");
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
if (bt->firmware_ver[3] == ' ')
|
if (bt->firmware_ver[3] == ' ')
|
||||||
@ -475,8 +457,9 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
(u_int8_t*)&bt->firmware_ver[4], 1,
|
(u_int8_t*)&bt->firmware_ver[4], 1,
|
||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed Get "
|
device_printf(dev,
|
||||||
"Firmware 4th Digit\n", bt_name(bt));
|
"bt_fetch_adapter_info - Failed Get "
|
||||||
|
"Firmware 4th Digit\n");
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
if (bt->firmware_ver[4] == ' ')
|
if (bt->firmware_ver[4] == ' ')
|
||||||
@ -532,8 +515,9 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
(u_int8_t*)&model_data, sizeof(model_data),
|
(u_int8_t*)&model_data, sizeof(model_data),
|
||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed Inquire "
|
device_printf(dev,
|
||||||
"Model Number\n", bt_name(bt));
|
"bt_fetch_adapter_info - Failed Inquire "
|
||||||
|
"Model Number\n");
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
for (i = 0; i < sizeof(model_data.ascii_model); i++) {
|
for (i = 0; i < sizeof(model_data.ascii_model); i++) {
|
||||||
@ -617,8 +601,9 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT);
|
sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT);
|
||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed "
|
device_printf(dev,
|
||||||
"Get Auto SCSI Info\n", bt_name(bt));
|
"bt_fetch_adapter_info - Failed "
|
||||||
|
"Get Auto SCSI Info\n");
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,8 +636,9 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
|
sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
|
||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed "
|
device_printf(dev,
|
||||||
"Get Setup Info\n", bt_name(bt));
|
"bt_fetch_adapter_info - Failed "
|
||||||
|
"Get Setup Info\n");
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,8 +664,8 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
(u_int8_t*)&config_data, sizeof(config_data),
|
(u_int8_t*)&config_data, sizeof(config_data),
|
||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
printf("%s: bt_fetch_adapter_info - Failed Get Config\n",
|
device_printf(dev,
|
||||||
bt_name(bt));
|
"bt_fetch_adapter_info - Failed Get Config\n");
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
bt->scsi_id = config_data.scsi_id;
|
bt->scsi_id = config_data.scsi_id;
|
||||||
@ -691,11 +677,12 @@ bt_fetch_adapter_info(struct bt_softc *bt)
|
|||||||
* Start the board, ready for normal operation
|
* Start the board, ready for normal operation
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
bt_init(struct bt_softc* bt)
|
bt_init(device_t dev)
|
||||||
{
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
/* Announce the Adapter */
|
/* Announce the Adapter */
|
||||||
printf("%s: BT-%s FW Rev. %s ", bt_name(bt),
|
device_printf(dev, "BT-%s FW Rev. %s ", bt->model, bt->firmware_ver);
|
||||||
bt->model, bt->firmware_ver);
|
|
||||||
|
|
||||||
if (bt->ultra_scsi != 0)
|
if (bt->ultra_scsi != 0)
|
||||||
printf("Ultra ");
|
printf("Ultra ");
|
||||||
@ -818,8 +805,8 @@ bt_init(struct bt_softc* bt)
|
|||||||
btallocccbs(bt);
|
btallocccbs(bt);
|
||||||
|
|
||||||
if (bt->num_ccbs == 0) {
|
if (bt->num_ccbs == 0) {
|
||||||
printf("%s: bt_init - Unable to allocate initial ccbs\n",
|
device_printf(dev,
|
||||||
bt_name(bt));
|
"bt_init - Unable to allocate initial ccbs\n");
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,8 +821,9 @@ bt_init(struct bt_softc* bt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bt_attach(struct bt_softc *bt)
|
bt_attach(device_t dev)
|
||||||
{
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
int tagged_dev_openings;
|
int tagged_dev_openings;
|
||||||
struct cam_devq *devq;
|
struct cam_devq *devq;
|
||||||
|
|
||||||
@ -878,18 +866,14 @@ bt_attach(struct bt_softc *bt)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup interrupt.
|
||||||
|
*/
|
||||||
|
bus_setup_intr(dev, bt->irq, bt_intr, bt, &bt->ih);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
bt_name(struct bt_softc *bt)
|
|
||||||
{
|
|
||||||
static char name[10];
|
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "bt%d", bt->unit);
|
|
||||||
return (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
bt_check_probed_iop(u_int ioport)
|
bt_check_probed_iop(u_int ioport)
|
||||||
{
|
{
|
||||||
@ -1055,7 +1039,7 @@ btgetccb(struct bt_softc *bt)
|
|||||||
btallocccbs(bt);
|
btallocccbs(bt);
|
||||||
bccb = SLIST_FIRST(&bt->free_bt_ccbs);
|
bccb = SLIST_FIRST(&bt->free_bt_ccbs);
|
||||||
if (bccb == NULL)
|
if (bccb == NULL)
|
||||||
printf("%s: Can't malloc BCCB\n", bt_name(bt));
|
device_printf(bt->dev, "Can't malloc BCCB\n");
|
||||||
else {
|
else {
|
||||||
SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
|
SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
|
||||||
bt->active_ccbs++;
|
bt->active_ccbs++;
|
||||||
@ -1388,8 +1372,9 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
if (error != EFBIG)
|
if (error != EFBIG)
|
||||||
printf("%s: Unexepected error 0x%x returned from "
|
device_printf(bt->dev,
|
||||||
"bus_dmamap_load\n", bt_name(bt), error);
|
"Unexepected error 0x%x returned from "
|
||||||
|
"bus_dmamap_load\n", error);
|
||||||
if (ccb->ccb_h.status == CAM_REQ_INPROG) {
|
if (ccb->ccb_h.status == CAM_REQ_INPROG) {
|
||||||
xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
|
xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
|
||||||
ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
|
ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
|
||||||
@ -1470,9 +1455,10 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||||||
* hung, one of the pending transactions will
|
* hung, one of the pending transactions will
|
||||||
* timeout causing us to start recovery operations.
|
* timeout causing us to start recovery operations.
|
||||||
*/
|
*/
|
||||||
printf("%s: Encountered busy mailbox with %d out of %d "
|
device_printf(bt->dev,
|
||||||
"commands active!!!\n", bt_name(bt), bt->active_ccbs,
|
"Encountered busy mailbox with %d out of %d "
|
||||||
bt->max_ccbs);
|
"commands active!!!\n", bt->active_ccbs,
|
||||||
|
bt->max_ccbs);
|
||||||
untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);
|
untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);
|
||||||
if (nseg != 0)
|
if (nseg != 0)
|
||||||
bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
|
bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
|
||||||
@ -1531,8 +1517,9 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
|
|||||||
csio = &bccb->ccb->csio;
|
csio = &bccb->ccb->csio;
|
||||||
|
|
||||||
if ((bccb->flags & BCCB_ACTIVE) == 0) {
|
if ((bccb->flags & BCCB_ACTIVE) == 0) {
|
||||||
printf("%s: btdone - Attempt to free non-active BCCB %p\n",
|
device_printf(bt->dev,
|
||||||
bt_name(bt), (void *)bccb);
|
"btdone - Attempt to free non-active BCCB %p\n",
|
||||||
|
(void *)bccb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1586,7 +1573,7 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
|
|||||||
ccb_h = LIST_NEXT(ccb_h, sim_links.le);
|
ccb_h = LIST_NEXT(ccb_h, sim_links.le);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("%s: No longer in timeout\n", bt_name(bt));
|
device_printf(bt->dev, "No longer in timeout\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1594,12 +1581,12 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
|
|||||||
|
|
||||||
switch (comp_code) {
|
switch (comp_code) {
|
||||||
case BMBI_FREE:
|
case BMBI_FREE:
|
||||||
printf("%s: btdone - CCB completed with free status!\n",
|
device_printf(bt->dev,
|
||||||
bt_name(bt));
|
"btdone - CCB completed with free status!\n");
|
||||||
break;
|
break;
|
||||||
case BMBI_NOT_FOUND:
|
case BMBI_NOT_FOUND:
|
||||||
printf("%s: btdone - CCB Abort failed to find CCB\n",
|
device_printf(bt->dev,
|
||||||
bt_name(bt));
|
"btdone - CCB Abort failed to find CCB\n");
|
||||||
break;
|
break;
|
||||||
case BMBI_ABORT:
|
case BMBI_ABORT:
|
||||||
case BMBI_ERROR:
|
case BMBI_ERROR:
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_eisa.c,v 1.2 1999/03/08 21:35:03 gibbs Exp $
|
* $Id: bt_eisa.c,v 1.3 1999/03/23 07:27:38 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -35,9 +35,13 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
@ -99,21 +103,59 @@
|
|||||||
#define AMI_MISC2_OPTIONS 0x49E
|
#define AMI_MISC2_OPTIONS 0x49E
|
||||||
#define AMI_ENABLE_ISA_DMA 0x08
|
#define AMI_ENABLE_ISA_DMA 0x08
|
||||||
|
|
||||||
static int bt_eisa_probe(void);
|
|
||||||
static int bt_eisa_attach(struct eisa_device *e_dev);
|
|
||||||
|
|
||||||
static struct eisa_driver bt_eisa_driver = {
|
|
||||||
"bt",
|
|
||||||
bt_eisa_probe,
|
|
||||||
bt_eisa_attach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&bt_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, bt_eisa_driver);
|
|
||||||
|
|
||||||
static const char *bt_match(eisa_id_t type);
|
static const char *bt_match(eisa_id_t type);
|
||||||
|
|
||||||
|
static int
|
||||||
|
bt_eisa_alloc_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
int rid;
|
||||||
|
struct resource *port;
|
||||||
|
struct resource *irq;
|
||||||
|
int shared;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX assumes that the iospace ranges are sorted in increasing
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
rid = 1;
|
||||||
|
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!port)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
bt_init_softc(dev, port, 0, 0);
|
||||||
|
|
||||||
|
if (eisa_get_irq(dev) != -1) {
|
||||||
|
shared = bt->level_trigger_ints ? RF_SHAREABLE : 0;
|
||||||
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
irq = 0;
|
||||||
|
bt->irq = irq;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_eisa_release_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
bt_match(eisa_id_t type)
|
bt_match(eisa_id_t type)
|
||||||
{
|
{
|
||||||
@ -137,155 +179,119 @@ bt_match(eisa_id_t type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bt_eisa_probe(void)
|
bt_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
struct eisa_device *e_dev = NULL;
|
struct bt_probe_info info;
|
||||||
int count;
|
u_long port;
|
||||||
|
u_long iosize;
|
||||||
|
u_int ioconf;
|
||||||
|
int result;
|
||||||
|
|
||||||
count = 0;
|
desc = bt_match(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, bt_match))) {
|
if (!desc)
|
||||||
struct bt_softc *bt;
|
return (ENXIO);
|
||||||
struct bt_probe_info info;
|
device_set_desc(dev, desc);
|
||||||
u_long port;
|
|
||||||
u_long iosize;
|
|
||||||
u_int ioconf;
|
|
||||||
|
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE);
|
||||||
if (e_dev->id == EISA_DEVICE_ID_AMI_4801) {
|
if (eisa_get_id(dev) == EISA_DEVICE_ID_AMI_4801) {
|
||||||
u_int ioconf1;
|
u_int ioconf1;
|
||||||
|
|
||||||
iobase += AMI_EISA_SLOT_OFFSET;
|
iobase += AMI_EISA_SLOT_OFFSET;
|
||||||
iosize = AMI_EISA_IOSIZE;
|
iosize = AMI_EISA_IOSIZE;
|
||||||
ioconf1 = inb(iobase + AMI_EISA_IOCONF1);
|
ioconf1 = inb(iobase + AMI_EISA_IOCONF1);
|
||||||
/* Determine "ISA" I/O port */
|
/* Determine "ISA" I/O port */
|
||||||
switch (ioconf1 & AMI_PORTADDR) {
|
switch (ioconf1 & AMI_PORTADDR) {
|
||||||
case AMI_PORT_330:
|
case AMI_PORT_330:
|
||||||
port = 0x330;
|
port = 0x330;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_334:
|
case AMI_PORT_334:
|
||||||
port = 0x334;
|
port = 0x334;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_230:
|
case AMI_PORT_230:
|
||||||
port = 0x230;
|
port = 0x230;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_234:
|
case AMI_PORT_234:
|
||||||
port = 0x234;
|
port = 0x234;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_134:
|
case AMI_PORT_134:
|
||||||
port = 0x134;
|
port = 0x134;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_130:
|
case AMI_PORT_130:
|
||||||
port = 0x130;
|
port = 0x130;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Disabled */
|
/* Disabled */
|
||||||
printf("bt: AMI EISA Adapter at "
|
printf("bt: AMI EISA Adapter at "
|
||||||
"slot %d has a disabled I/O "
|
"slot %d has a disabled I/O "
|
||||||
"port. Cannot attach.\n",
|
"port. Cannot attach.\n",
|
||||||
e_dev->ioconf.slot);
|
eisa_get_slot(dev));
|
||||||
continue;
|
return (ENXIO);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iobase += BT_EISA_SLOT_OFFSET;
|
|
||||||
iosize = BT_EISA_IOSIZE;
|
|
||||||
|
|
||||||
ioconf = inb(iobase + EISA_IOCONF);
|
|
||||||
/* Determine "ISA" I/O port */
|
|
||||||
switch (ioconf & PORTADDR) {
|
|
||||||
case PORT_330:
|
|
||||||
port = 0x330;
|
|
||||||
break;
|
|
||||||
case PORT_334:
|
|
||||||
port = 0x334;
|
|
||||||
break;
|
|
||||||
case PORT_230:
|
|
||||||
port = 0x230;
|
|
||||||
break;
|
|
||||||
case PORT_234:
|
|
||||||
port = 0x234;
|
|
||||||
break;
|
|
||||||
case PORT_130:
|
|
||||||
port = 0x130;
|
|
||||||
break;
|
|
||||||
case PORT_134:
|
|
||||||
port = 0x134;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Disabled */
|
|
||||||
printf("bt: Buslogic EISA Adapter at "
|
|
||||||
"slot %d has a disabled I/O "
|
|
||||||
"port. Cannot attach.\n",
|
|
||||||
e_dev->ioconf.slot);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bt_mark_probed_iop(port);
|
} else {
|
||||||
|
iobase += BT_EISA_SLOT_OFFSET;
|
||||||
|
iosize = BT_EISA_IOSIZE;
|
||||||
|
|
||||||
/* Allocate a softc for use during probing */
|
ioconf = inb(iobase + EISA_IOCONF);
|
||||||
bt = bt_alloc(BT_TEMP_UNIT, I386_BUS_SPACE_IO, port);
|
/* Determine "ISA" I/O port */
|
||||||
|
switch (ioconf & PORTADDR) {
|
||||||
if (bt == NULL) {
|
case PORT_330:
|
||||||
printf("bt_eisa_probe: Could not allocate softc for "
|
port = 0x330;
|
||||||
"card at slot 0x%x\n", e_dev->ioconf.slot);
|
break;
|
||||||
continue;
|
case PORT_334:
|
||||||
|
port = 0x334;
|
||||||
|
break;
|
||||||
|
case PORT_230:
|
||||||
|
port = 0x230;
|
||||||
|
break;
|
||||||
|
case PORT_234:
|
||||||
|
port = 0x234;
|
||||||
|
break;
|
||||||
|
case PORT_130:
|
||||||
|
port = 0x130;
|
||||||
|
break;
|
||||||
|
case PORT_134:
|
||||||
|
port = 0x134;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Disabled */
|
||||||
|
printf("bt: Buslogic EISA Adapter at "
|
||||||
|
"slot %d has a disabled I/O "
|
||||||
|
"port. Cannot attach.\n",
|
||||||
|
eisa_get_slot(dev));
|
||||||
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_port_probe(bt, &info) != 0) {
|
|
||||||
printf("bt_eisa_probe: Probe failed for "
|
|
||||||
"card at slot 0x%x\n", e_dev->ioconf.slot);
|
|
||||||
} else {
|
|
||||||
eisa_add_iospace(e_dev, iobase, iosize, RESVADDR_NONE);
|
|
||||||
eisa_add_iospace(e_dev, port, BT_IOSIZE, RESVADDR_NONE);
|
|
||||||
eisa_add_intr(e_dev, info.irq);
|
|
||||||
|
|
||||||
eisa_registerdev(e_dev, &bt_eisa_driver);
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
bt_free(bt);
|
|
||||||
}
|
}
|
||||||
return count;
|
bt_mark_probed_iop(port);
|
||||||
|
|
||||||
|
/* Tell parent where our resources are going to be */
|
||||||
|
eisa_add_iospace(dev, iobase, iosize, RESVADDR_NONE);
|
||||||
|
eisa_add_iospace(dev, port, BT_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
|
/* And allocate them */
|
||||||
|
bt_eisa_alloc_resources(dev);
|
||||||
|
|
||||||
|
if (bt_port_probe(dev, &info) != 0) {
|
||||||
|
printf("bt_eisa_probe: Probe failed for "
|
||||||
|
"card at slot 0x%x\n", eisa_get_slot(dev));
|
||||||
|
result = ENXIO;
|
||||||
|
} else {
|
||||||
|
eisa_add_intr(dev, info.irq);
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
bt_eisa_release_resources(dev);
|
||||||
|
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bt_eisa_attach(struct eisa_device *e_dev)
|
bt_eisa_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
int unit = e_dev->unit;
|
|
||||||
int irq;
|
|
||||||
resvaddr_t *ioport;
|
|
||||||
resvaddr_t *eisa_ioport;
|
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
/* Allocate resources */
|
||||||
return (-1);
|
bt_eisa_alloc_resources(dev);
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The addresses are sorted in increasing order
|
|
||||||
* so we know the port to pass to the core bt
|
|
||||||
* driver comes first.
|
|
||||||
*/
|
|
||||||
ioport = e_dev->ioconf.ioaddrs.lh_first;
|
|
||||||
|
|
||||||
if (ioport == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
eisa_ioport = ioport->links.le_next;
|
|
||||||
|
|
||||||
if (eisa_ioport == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (eisa_reg_iospace(e_dev, eisa_ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((bt = bt_alloc(unit, I386_BUS_SPACE_IO, ioport->addr)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Allocate a dmatag for our SCB DMA maps */
|
/* Allocate a dmatag for our SCB DMA maps */
|
||||||
/* XXX Should be a child of the PCI bus dma tag */
|
/* XXX Should be a child of the PCI bus dma tag */
|
||||||
@ -297,42 +303,42 @@ bt_eisa_attach(struct eisa_device *e_dev)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_eisa_release_resources(dev);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, bt_intr, (void *)bt, &cam_imask,
|
|
||||||
/*shared ==*/bt->level_trigger_ints ? 1 : 0)) {
|
|
||||||
bt_free(bt);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we know we own the resources we need, do the full
|
* Now that we know we own the resources we need, do the full
|
||||||
* card initialization.
|
* card initialization.
|
||||||
*/
|
*/
|
||||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_eisa_release_resources(dev);
|
||||||
/*
|
|
||||||
* The board's IRQ line will not be left enabled
|
|
||||||
* if we can't intialize correctly, so its safe
|
|
||||||
* to release the irq.
|
|
||||||
*/
|
|
||||||
eisa_release_intr(e_dev, irq, bt_intr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach sub-devices - always succeeds */
|
/* Attach sub-devices - always succeeds (sets up intr) */
|
||||||
bt_attach(bt);
|
bt_attach(dev);
|
||||||
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
|
||||||
bt_free(bt);
|
|
||||||
eisa_release_intr(e_dev, irq, bt_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_eisa_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, eisa, bt_eisa_driver, bt_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -26,33 +26,90 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_isa.c,v 1.6 1999/03/08 21:32:59 gibbs Exp $
|
* $Id: bt_isa.c,v 1.7 1999/04/06 21:15:18 phk Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/isa/isa_device.h>
|
#include <isa/isavar.h>
|
||||||
|
#include <i386/isa/isa_dma.h>
|
||||||
#include <dev/buslogic/btreg.h>
|
#include <dev/buslogic/btreg.h>
|
||||||
|
|
||||||
#include <cam/scsi/scsi_all.h>
|
#include <cam/scsi/scsi_all.h>
|
||||||
|
|
||||||
static int bt_isa_probe __P((struct isa_device *dev));
|
|
||||||
static int bt_isa_attach __P((struct isa_device *dev));
|
|
||||||
static void bt_isa_intr __P((void *unit));
|
|
||||||
|
|
||||||
static bus_dma_filter_t btvlbouncefilter;
|
static bus_dma_filter_t btvlbouncefilter;
|
||||||
static bus_dmamap_callback_t btmapsensebuffers;
|
static bus_dmamap_callback_t btmapsensebuffers;
|
||||||
|
|
||||||
struct isa_driver btdriver =
|
static int
|
||||||
|
bt_isa_alloc_resources(device_t dev)
|
||||||
{
|
{
|
||||||
bt_isa_probe,
|
int rid;
|
||||||
bt_isa_attach,
|
struct resource *port;
|
||||||
"bt"
|
struct resource *irq;
|
||||||
};
|
struct resource *drq;
|
||||||
|
|
||||||
|
rid = 0;
|
||||||
|
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!port)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
if (isa_get_irq(dev) != -1) {
|
||||||
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
irq = 0;
|
||||||
|
|
||||||
|
if (isa_get_drq(dev) != -1) {
|
||||||
|
rid = 0;
|
||||||
|
drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!drq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ,
|
||||||
|
0, irq);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
drq = 0;
|
||||||
|
|
||||||
|
bt_init_softc(dev, port, irq, drq);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_isa_release_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
if (bt->drq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->drq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the device can be found at the port given
|
* Check if the device can be found at the port given
|
||||||
@ -61,35 +118,24 @@ struct isa_driver btdriver =
|
|||||||
* autoconf.c
|
* autoconf.c
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bt_isa_probe(dev)
|
bt_isa_probe(device_t dev)
|
||||||
struct isa_device *dev;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* find unit and check we have that many defined
|
* find unit and check we have that many defined
|
||||||
*/
|
*/
|
||||||
struct bt_softc *bt;
|
|
||||||
int port_index;
|
int port_index;
|
||||||
int max_port_index;
|
int max_port_index;
|
||||||
|
|
||||||
/*
|
|
||||||
* We ignore the unit number assigned by config to allow
|
|
||||||
* consistant numbering between PCI/EISA/ISA devices.
|
|
||||||
* This is a total kludge until we have a configuration
|
|
||||||
* manager.
|
|
||||||
*/
|
|
||||||
dev->id_unit = bt_unit;
|
|
||||||
|
|
||||||
bt = NULL;
|
|
||||||
port_index = 0;
|
port_index = 0;
|
||||||
max_port_index = BT_NUM_ISAPORTS - 1;
|
max_port_index = BT_NUM_ISAPORTS - 1;
|
||||||
/*
|
/*
|
||||||
* Bound our board search if the user has
|
* Bound our board search if the user has
|
||||||
* specified an exact port.
|
* specified an exact port.
|
||||||
*/
|
*/
|
||||||
bt_find_probe_range(dev->id_iobase, &port_index, &max_port_index);
|
bt_find_probe_range(isa_get_port(dev), &port_index, &max_port_index);
|
||||||
|
|
||||||
if (port_index < 0)
|
if (port_index < 0)
|
||||||
return 0;
|
return (ENXIO);
|
||||||
|
|
||||||
/* Attempt to find an adapter */
|
/* Attempt to find an adapter */
|
||||||
for (;port_index <= max_port_index; port_index++) {
|
for (;port_index <= max_port_index; port_index++) {
|
||||||
@ -97,6 +143,8 @@ bt_isa_probe(dev)
|
|||||||
u_int ioport;
|
u_int ioport;
|
||||||
|
|
||||||
ioport = bt_iop_from_bio(port_index);
|
ioport = bt_iop_from_bio(port_index);
|
||||||
|
isa_set_port(dev, ioport);
|
||||||
|
isa_set_portsize(dev, BT_NREGS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure this port has not already been claimed already
|
* Ensure this port has not already been claimed already
|
||||||
@ -104,52 +152,50 @@ bt_isa_probe(dev)
|
|||||||
*/
|
*/
|
||||||
if (bt_check_probed_iop(ioport) != 0)
|
if (bt_check_probed_iop(ioport) != 0)
|
||||||
continue;
|
continue;
|
||||||
dev->id_iobase = ioport;
|
|
||||||
if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET))
|
/* Initialise the softc for use during probing */
|
||||||
|
if (bt_isa_alloc_resources(dev) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Allocate a softc for use during probing */
|
|
||||||
bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
|
|
||||||
|
|
||||||
if (bt == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* We're going to attempt to probe it now, so mark it probed */
|
/* We're going to attempt to probe it now, so mark it probed */
|
||||||
bt_mark_probed_bio(port_index);
|
bt_mark_probed_bio(port_index);
|
||||||
|
|
||||||
if (bt_port_probe(bt, &info) != 0) {
|
if (bt_port_probe(dev, &info) != 0) {
|
||||||
printf("bt_isa_probe: Probe failed for card at 0x%x\n",
|
printf("bt_isa_probe: Probe failed for card at 0x%x\n",
|
||||||
ioport);
|
ioport);
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->id_drq = info.drq;
|
bt_isa_release_resources(dev);
|
||||||
dev->id_irq = 0x1 << info.irq;
|
|
||||||
dev->id_intr = bt_isa_intr;
|
|
||||||
|
|
||||||
bt_unit++;
|
isa_set_drq(dev, info.drq);
|
||||||
return (BT_NREGS);
|
isa_set_irq(dev, info.irq);
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach all the sub-devices we can find
|
* Attach all the sub-devices we can find
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bt_isa_attach(dev)
|
bt_isa_attach(device_t dev)
|
||||||
struct isa_device *dev;
|
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_dma_filter_t *filter;
|
bus_dma_filter_t *filter;
|
||||||
void *filter_arg;
|
void *filter_arg;
|
||||||
bus_addr_t lowaddr;
|
bus_addr_t lowaddr;
|
||||||
|
int error;
|
||||||
|
|
||||||
bt = bt_softcs[dev->id_unit];
|
/* Initialise softc */
|
||||||
if (dev->id_drq != -1)
|
error = bt_isa_alloc_resources(dev);
|
||||||
isa_dmacascade(dev->id_drq);
|
if (error) {
|
||||||
|
device_printf(dev, "can't allocate resources in bt_isa_attach\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate our parent dmatag */
|
/* Allocate our parent dmatag */
|
||||||
filter = NULL;
|
filter = NULL;
|
||||||
@ -186,13 +232,13 @@ bt_isa_attach(dev)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_init(bt)) {
|
if (bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
||||||
@ -207,8 +253,8 @@ bt_isa_attach(dev)
|
|||||||
/*nsegments*/1,
|
/*nsegments*/1,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->sense_dmat) != 0) {
|
/*flags*/0, &bt->sense_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
@ -217,8 +263,8 @@ bt_isa_attach(dev)
|
|||||||
if (bus_dmamem_alloc(bt->sense_dmat,
|
if (bus_dmamem_alloc(bt->sense_dmat,
|
||||||
(void **)&bt->sense_buffers,
|
(void **)&bt->sense_buffers,
|
||||||
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
@ -232,19 +278,13 @@ bt_isa_attach(dev)
|
|||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (bt_attach(bt));
|
error = bt_attach(dev);
|
||||||
}
|
if (error) {
|
||||||
|
bt_isa_release_resources(dev);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
return (0);
|
||||||
* Handle an ISA interrupt.
|
|
||||||
* XXX should go away as soon as ISA interrupt handlers
|
|
||||||
* take a (void *) arg.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
bt_isa_intr(void *unit)
|
|
||||||
{
|
|
||||||
struct bt_softc* arg = bt_softcs[(int)unit];
|
|
||||||
bt_intr((void *)arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BIOS_MAP_SIZE (16 * 1024)
|
#define BIOS_MAP_SIZE (16 * 1024)
|
||||||
@ -273,3 +313,22 @@ btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
|||||||
bt = (struct bt_softc*)arg;
|
bt = (struct bt_softc*)arg;
|
||||||
bt->sense_buffers_physbase = segs->ds_addr;
|
bt->sense_buffers_physbase = segs->ds_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_isa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_isa_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_isa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_isa_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_isa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, isa, bt_isa_driver, bt_devclass, 0, 0);
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_pci.c,v 1.3 1998/11/10 06:45:14 gibbs Exp $
|
* $Id: bt_pci.c,v 1.4 1998/12/14 06:32:54 dillon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <pci/pcireg.h>
|
#include <pci/pcireg.h>
|
||||||
#include <pci/pcivar.h>
|
#include <pci/pcivar.h>
|
||||||
@ -41,6 +42,8 @@
|
|||||||
#include <machine/bus_memio.h>
|
#include <machine/bus_memio.h>
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <dev/buslogic/btreg.h>
|
#include <dev/buslogic/btreg.h>
|
||||||
|
|
||||||
@ -51,72 +54,74 @@
|
|||||||
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul
|
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul
|
||||||
#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul
|
#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul
|
||||||
|
|
||||||
static int btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
|
|
||||||
bus_space_handle_t* bshp);
|
|
||||||
static const char* bt_pci_probe(pcici_t tag, pcidi_t type);
|
|
||||||
static void bt_pci_attach(pcici_t config_id, int unit);
|
|
||||||
|
|
||||||
static struct pci_device bt_pci_driver = {
|
|
||||||
"bt",
|
|
||||||
bt_pci_probe,
|
|
||||||
bt_pci_attach,
|
|
||||||
&bt_unit,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (pcidevice_set, bt_pci_driver);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
|
bt_pci_alloc_resources(device_t dev)
|
||||||
bus_space_handle_t* bshp)
|
|
||||||
{
|
{
|
||||||
vm_offset_t vaddr;
|
int command, type = 0, rid, zero;
|
||||||
vm_offset_t paddr;
|
struct resource *regs = 0;
|
||||||
u_int16_t io_port;
|
struct resource *irq = 0;
|
||||||
int command;
|
|
||||||
|
|
||||||
vaddr = 0;
|
command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
|
||||||
paddr = 0;
|
|
||||||
command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1);
|
|
||||||
/* XXX Memory Mapped I/O seems to cause problems */
|
|
||||||
#if 0
|
#if 0
|
||||||
if ((command & PCIM_CMD_MEMEN) == 0
|
/* XXX Memory Mapped I/O seems to cause problems */
|
||||||
|| (pci_map_mem(config_id, BT_PCI_MEMADDR, &vaddr, &paddr)) == 0)
|
if (command & PCIM_CMD_MEMEN) {
|
||||||
#endif
|
type = SYS_RES_MEMORY;
|
||||||
if ((command & PCIM_CMD_PORTEN) == 0
|
rid = BT_PCI_MEMADDR;
|
||||||
|| (pci_map_port(config_id, BT_PCI_IOADDR, &io_port)) == 0)
|
regs = bus_alloc_resource(dev, type, &rid,
|
||||||
return (-1);
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
|
||||||
if (vaddr != 0) {
|
|
||||||
*tagp = I386_BUS_SPACE_MEM;
|
|
||||||
*bshp = vaddr;
|
|
||||||
} else {
|
|
||||||
*tagp = I386_BUS_SPACE_IO;
|
|
||||||
*bshp = io_port;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (!regs && (command & PCIM_CMD_PORTEN)) {
|
||||||
|
type = SYS_RES_IOPORT;
|
||||||
|
rid = BT_PCI_IOADDR;
|
||||||
|
regs = bus_alloc_resource(dev, type, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!regs)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
zero = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero,
|
||||||
|
0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
if (!irq) {
|
||||||
|
bus_release_resource(dev, type, rid, regs);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_init_softc(dev, regs, irq, 0);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char*
|
static void
|
||||||
bt_pci_probe (pcici_t config_id, pcidi_t type)
|
bt_pci_release_resources(device_t dev)
|
||||||
{
|
{
|
||||||
switch(type) {
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
/* XXX can't cope with memory registers anyway */
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
BT_PCI_IOADDR, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bt_pci_probe(device_t dev)
|
||||||
|
{
|
||||||
|
switch (pci_get_devid(dev)) {
|
||||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
|
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
|
||||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
|
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_space_tag_t tag;
|
|
||||||
bus_space_handle_t bsh;
|
|
||||||
pci_info_data_t pci_info;
|
pci_info_data_t pci_info;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
error = bt_pci_alloc_resources(dev);
|
||||||
break;
|
if (error)
|
||||||
|
return (error);
|
||||||
bt = bt_alloc(BT_TEMP_UNIT, tag, bsh);
|
|
||||||
if (bt == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if an ISA compatible I/O port has been
|
* Determine if an ISA compatible I/O port has been
|
||||||
@ -131,7 +136,7 @@ bt_pci_probe (pcici_t config_id, pcidi_t type)
|
|||||||
if (error == 0
|
if (error == 0
|
||||||
&& pci_info.io_port < BIO_DISABLED) {
|
&& pci_info.io_port < BIO_DISABLED) {
|
||||||
bt_mark_probed_bio(pci_info.io_port);
|
bt_mark_probed_bio(pci_info.io_port);
|
||||||
if (bsh != bt_iop_from_bio(pci_info.io_port)) {
|
if (bt->bsh != bt_iop_from_bio(pci_info.io_port)) {
|
||||||
u_int8_t new_addr;
|
u_int8_t new_addr;
|
||||||
|
|
||||||
new_addr = BIO_DISABLED;
|
new_addr = BIO_DISABLED;
|
||||||
@ -142,30 +147,30 @@ bt_pci_probe (pcici_t config_id, pcidi_t type)
|
|||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bt_free(bt);
|
bt_pci_release_resources(dev);
|
||||||
return ("Buslogic Multi-Master SCSI Host Adapter");
|
device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter");
|
||||||
break;
|
return (0);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
bt_pci_attach(pcici_t config_id, int unit)
|
bt_pci_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_space_tag_t tag;
|
|
||||||
bus_space_handle_t bsh;
|
|
||||||
int opri;
|
int opri;
|
||||||
|
int error;
|
||||||
|
|
||||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
/* Initialise softc */
|
||||||
return;
|
error = bt_pci_alloc_resources(dev);
|
||||||
|
if (error) {
|
||||||
if ((bt = bt_alloc(unit, tag, bsh)) == NULL)
|
device_printf(dev, "can't allocate resources in bt_pci_attach\n");
|
||||||
return; /* XXX PCI code should take return status */
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a dmatag for our CCB DMA maps */
|
/* Allocate a dmatag for our CCB DMA maps */
|
||||||
/* XXX Should be a child of the PCI bus dma tag */
|
/* XXX Should be a child of the PCI bus dma tag */
|
||||||
@ -177,14 +182,10 @@ bt_pci_attach(pcici_t config_id, int unit)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_pci_release_resources(dev);
|
||||||
return;
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pci_map_int(config_id, bt_intr, (void *)bt, &cam_imask)) == 0) {
|
|
||||||
bt_free(bt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Protect ourself from spurrious interrupts during
|
* Protect ourself from spurrious interrupts during
|
||||||
* intialization and attach. We should really rely
|
* intialization and attach. We should really rely
|
||||||
@ -195,16 +196,40 @@ bt_pci_attach(pcici_t config_id, int unit)
|
|||||||
*/
|
*/
|
||||||
opri = splcam();
|
opri = splcam();
|
||||||
|
|
||||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_pci_release_resources(dev);
|
||||||
splx(opri);
|
splx(opri);
|
||||||
return; /* XXX PCI code should take return status */
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_attach(bt);
|
error = bt_attach(dev);
|
||||||
|
|
||||||
splx(opri);
|
splx(opri);
|
||||||
return;
|
|
||||||
|
if (error) {
|
||||||
|
bt_pci_release_resources(dev);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_pci_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_pci_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_pci_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_pci_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_pci_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NPCI > 0 */
|
#endif /* NPCI > 0 */
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: btreg.h,v 1.4 1999/03/08 21:36:34 gibbs Exp $
|
* $Id: btreg.h,v 1.5 1999/04/07 23:01:43 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BTREG_H_
|
#ifndef _BTREG_H_
|
||||||
@ -595,6 +595,11 @@ struct sg_map_node {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct bt_softc {
|
struct bt_softc {
|
||||||
|
struct device *dev;
|
||||||
|
struct resource *port;
|
||||||
|
struct resource *irq;
|
||||||
|
struct resource *drq;
|
||||||
|
void *ih;
|
||||||
bus_space_tag_t tag;
|
bus_space_tag_t tag;
|
||||||
bus_space_handle_t bsh;
|
bus_space_handle_t bsh;
|
||||||
struct cam_sim *sim;
|
struct cam_sim *sim;
|
||||||
@ -663,17 +668,18 @@ extern struct bt_softc *bt_softcs[]; /* XXX Config should handle this */
|
|||||||
extern u_long bt_unit;
|
extern u_long bt_unit;
|
||||||
|
|
||||||
#define BT_TEMP_UNIT 0xFF /* Unit for probes */
|
#define BT_TEMP_UNIT 0xFF /* Unit for probes */
|
||||||
struct bt_softc* bt_alloc(int unit, bus_space_tag_t tag,
|
void bt_init_softc(device_t dev,
|
||||||
bus_space_handle_t bsh);
|
struct resource *port,
|
||||||
void bt_free(struct bt_softc *bt);
|
struct resource *irq,
|
||||||
int bt_port_probe(struct bt_softc *bt,
|
struct resource *drq);
|
||||||
|
void bt_free_softc(device_t dev);
|
||||||
|
int bt_port_probe(device_t dev,
|
||||||
struct bt_probe_info *info);
|
struct bt_probe_info *info);
|
||||||
int bt_probe(struct bt_softc *bt);
|
int bt_probe(device_t dev);
|
||||||
int bt_fetch_adapter_info(struct bt_softc *bt);
|
int bt_fetch_adapter_info(device_t dev);
|
||||||
int bt_init(struct bt_softc *bt);
|
int bt_init(device_t dev);
|
||||||
int bt_attach(struct bt_softc *bt);
|
int bt_attach(device_t dev);
|
||||||
void bt_intr(void *arg);
|
void bt_intr(void *arg);
|
||||||
char * bt_name(struct bt_softc *bt);
|
|
||||||
int bt_check_probed_iop(u_int ioport);
|
int bt_check_probed_iop(u_int ioport);
|
||||||
void bt_mark_probed_bio(isa_compat_io_t port);
|
void bt_mark_probed_bio(isa_compat_io_t port);
|
||||||
void bt_mark_probed_iop(u_int ioport);
|
void bt_mark_probed_iop(u_int ioport);
|
||||||
@ -689,6 +695,8 @@ int bt_cmd(struct bt_softc *bt, bt_op_t opcode,
|
|||||||
u_int8_t *reply_data, u_int reply_len,
|
u_int8_t *reply_data, u_int reply_len,
|
||||||
u_int cmd_timeout);
|
u_int cmd_timeout);
|
||||||
|
|
||||||
|
#define bt_name(bt) device_get_nameunit(bt->dev)
|
||||||
|
|
||||||
#define bt_inb(bt, port) \
|
#define bt_inb(bt, port) \
|
||||||
bus_space_read_1((bt)->tag, (bt)->bsh, port)
|
bus_space_read_1((bt)->tag, (bt)->bsh, port)
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Id: dpt_eisa.c,v 1.3 1998/08/09 02:22:34 jkh Exp $
|
* $Id: dpt_eisa.c,v 1.4 1998/09/15 08:33:35 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -46,9 +46,13 @@
|
|||||||
#include <sys/buf.h>
|
#include <sys/buf.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <cam/scsi/scsi_all.h>
|
#include <cam/scsi/scsi_all.h>
|
||||||
|
|
||||||
@ -65,100 +69,80 @@
|
|||||||
|
|
||||||
/* Function Prototypes */
|
/* Function Prototypes */
|
||||||
|
|
||||||
static int dpt_eisa_probe(void);
|
|
||||||
static int dpt_eisa_attach(struct eisa_device*);
|
|
||||||
|
|
||||||
static const char *dpt_eisa_match(eisa_id_t);
|
static const char *dpt_eisa_match(eisa_id_t);
|
||||||
|
|
||||||
static struct eisa_driver dpt_eisa_driver =
|
|
||||||
{
|
|
||||||
"dpt",
|
|
||||||
dpt_eisa_probe,
|
|
||||||
dpt_eisa_attach,
|
|
||||||
NULL,
|
|
||||||
&dpt_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, dpt_eisa_driver);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dpt_eisa_probe(void)
|
dpt_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
struct eisa_device *e_dev = NULL;
|
const char *desc;
|
||||||
int count;
|
|
||||||
u_int32_t io_base;
|
u_int32_t io_base;
|
||||||
u_int intdef;
|
u_int intdef;
|
||||||
u_int irq;
|
u_int irq;
|
||||||
|
|
||||||
e_dev = NULL;
|
desc = dpt_eisa_match(eisa_get_id(dev));
|
||||||
count = 0;
|
if (!desc)
|
||||||
while ((e_dev = eisa_match_dev(e_dev, dpt_eisa_match))) {
|
return (ENXIO);
|
||||||
io_base = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
|
device_set_desc(dev, desc);
|
||||||
+ DPT_EISA_SLOT_OFFSET;
|
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, io_base,
|
io_base = (eisa_get_slot(dev) * EISA_SLOT_SIZE)
|
||||||
DPT_EISA_IOSIZE, RESVADDR_NONE);
|
+ DPT_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
|
eisa_add_iospace(dev, io_base, DPT_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
intdef = inb(DPT_EISA_INTDEF + io_base);
|
intdef = inb(DPT_EISA_INTDEF + io_base);
|
||||||
|
|
||||||
irq = intdef & DPT_EISA_INT_NUM_MASK;
|
irq = intdef & DPT_EISA_INT_NUM_MASK;
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case DPT_EISA_INT_NUM_11:
|
case DPT_EISA_INT_NUM_11:
|
||||||
irq = 11;
|
irq = 11;
|
||||||
break;
|
break;
|
||||||
case DPT_EISA_INT_NUM_15:
|
case DPT_EISA_INT_NUM_15:
|
||||||
irq = 15;
|
irq = 15;
|
||||||
break;
|
break;
|
||||||
case DPT_EISA_INT_NUM_14:
|
case DPT_EISA_INT_NUM_14:
|
||||||
irq = 14;
|
irq = 14;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("dpt at slot %d: illegal irq setting %d\n",
|
printf("dpt at slot %d: illegal irq setting %d\n",
|
||||||
e_dev->ioconf.slot, irq);
|
eisa_get_slot(dev), irq);
|
||||||
irq = 0;
|
irq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (irq == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &dpt_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
if (irq == 0)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
dpt_eisa_attach(e_dev)
|
dpt_eisa_attach(device_t dev)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
{
|
{
|
||||||
dpt_softc_t *dpt;
|
dpt_softc_t *dpt;
|
||||||
resvaddr_t *io_space;
|
struct resource *io = 0;
|
||||||
int unit = e_dev->unit;
|
struct resource *irq = 0;
|
||||||
int irq;
|
int unit = device_get_unit(dev);
|
||||||
int shared;
|
int shared;
|
||||||
int s;
|
int s;
|
||||||
|
int rid;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL) {
|
rid = 0;
|
||||||
printf("dpt%d: Can't retrieve irq from EISA config struct.\n",
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
unit);
|
0, ~0, 1, RF_ACTIVE);
|
||||||
return -1;
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
shared = (inb(DPT_EISA_INTDEF + rman_get_start(io))
|
||||||
io_space = e_dev->ioconf.ioaddrs.lh_first;
|
& DPT_EISA_INT_LEVEL) ? RF_SHAREABLE : 0;
|
||||||
|
|
||||||
if (!io_space) {
|
dpt = dpt_alloc(unit, rman_get_bustag(io),
|
||||||
printf("dpt%d: No I/O space?!\n", unit);
|
rman_get_bushandle(io) + DPT_EISA_EATA_REG_OFFSET);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared = inb(DPT_EISA_INTDEF + io_space->addr) & DPT_EISA_INT_LEVEL;
|
|
||||||
|
|
||||||
dpt = dpt_alloc(unit, I386_BUS_SPACE_IO,
|
|
||||||
io_space->addr + DPT_EISA_EATA_REG_OFFSET);
|
|
||||||
if (dpt == NULL)
|
if (dpt == NULL)
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
/* Allocate a dmatag representing the capabilities of this attachment */
|
/* Allocate a dmatag representing the capabilities of this attachment */
|
||||||
/* XXX Should be a child of the EISA bus dma tag */
|
/* XXX Should be a child of the EISA bus dma tag */
|
||||||
@ -171,46 +155,37 @@ dpt_eisa_attach(e_dev)
|
|||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &dpt->parent_dmat) != 0) {
|
/*flags*/0, &dpt->parent_dmat) != 0) {
|
||||||
dpt_free(dpt);
|
dpt_free(dpt);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, dpt_intr, (void *)dpt, &cam_imask,
|
rid = 0;
|
||||||
shared)) {
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
printf("dpt%d: eisa_reg_intr() failed.\n", unit);
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
dpt_free(dpt);
|
if (!irq) {
|
||||||
return -1;
|
device_printf(dev, "No irq?!\n");
|
||||||
}
|
goto bad;
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/* Enable our interrupt handler. */
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
|
||||||
#ifdef DPT_DEBUG_ERROR
|
|
||||||
printf("dpt%d: eisa_enable_intr() failed.\n", unit);
|
|
||||||
#endif
|
|
||||||
free(dpt, M_DEVBUF);
|
|
||||||
eisa_release_intr(e_dev, irq, dpt_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Enable our interrupt handler.
|
|
||||||
*/
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
|
||||||
dpt_free(dpt);
|
|
||||||
eisa_release_intr(e_dev, irq, dpt_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s = splcam();
|
s = splcam();
|
||||||
if (dpt_init(dpt) != 0) {
|
if (dpt_init(dpt) != 0) {
|
||||||
dpt_free(dpt);
|
dpt_free(dpt);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register with the XPT */
|
/* Register with the XPT */
|
||||||
dpt_attach(dpt);
|
dpt_attach(dpt);
|
||||||
|
bus_setup_intr(dev, irq, dpt_intr, dpt, &ih);
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
@ -264,4 +239,23 @@ dpt_eisa_match(type)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t dpt_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, dpt_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, dpt_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t dpt_eisa_driver = {
|
||||||
|
"dpt",
|
||||||
|
dpt_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t dpt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(dpt, eisa, dpt_eisa_driver, dpt_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -28,55 +28,64 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: eisaconf.c,v 1.36 1998/12/04 22:54:46 archie Exp $
|
* $Id: eisaconf.c,v 1.37 1999/01/14 06:22:03 jdp Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "opt_eisa.h"
|
#include "opt_eisa.h"
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/linker_set.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/limits.h>
|
#include <machine/limits.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
#include <sys/interrupt.h>
|
#include <sys/interrupt.h>
|
||||||
|
|
||||||
struct eisa_device_node{
|
typedef struct resvaddr {
|
||||||
struct eisa_device dev;
|
u_long addr; /* start address */
|
||||||
struct eisa_device_node *next;
|
u_long size; /* size of reserved area */
|
||||||
|
int flags;
|
||||||
|
struct resource *res; /* resource manager handle */
|
||||||
|
LIST_ENTRY(resvaddr) links; /* List links */
|
||||||
|
} resvaddr_t;
|
||||||
|
|
||||||
|
LIST_HEAD(resvlist, resvaddr);
|
||||||
|
|
||||||
|
struct irq_node {
|
||||||
|
int irq_no;
|
||||||
|
void *idesc;
|
||||||
|
TAILQ_ENTRY(irq_node) links;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
TAILQ_HEAD(irqlist, irq_node);
|
||||||
* This should probably be a list of "struct device" once it exists.
|
|
||||||
* A struct device will incorperate ioconf and driver entry point data
|
|
||||||
* regardless of how its attached to the system (via unions) as well
|
|
||||||
* as more generic information that all device types should support (unit
|
|
||||||
* number, if its installed, etc).
|
|
||||||
*/
|
|
||||||
static struct eisa_device_node *eisa_dev_list;
|
|
||||||
static struct eisa_device_node **eisa_dev_list_tail = &eisa_dev_list;
|
|
||||||
static u_long eisa_unit;
|
|
||||||
|
|
||||||
static struct eisa_driver mainboard_drv = {
|
struct eisa_ioconf {
|
||||||
"eisa",
|
int slot;
|
||||||
NULL,
|
struct resvlist ioaddrs; /* list of reserved I/O ranges */
|
||||||
NULL,
|
struct resvlist maddrs; /* list of reserved memory ranges */
|
||||||
NULL,
|
struct irqlist irqs; /* list of reserved irqs */
|
||||||
&eisa_unit
|
};
|
||||||
};
|
|
||||||
|
/* To be replaced by the "super device" generic device structure... */
|
||||||
|
struct eisa_device {
|
||||||
|
eisa_id_t id;
|
||||||
|
struct eisa_ioconf ioconf;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the mainboard_drv to the eisa driver linkerset so that it is
|
|
||||||
* defined even if no EISA drivers are linked into the kernel.
|
|
||||||
*/
|
|
||||||
DATA_SET (eisadriver_set, mainboard_drv);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local function declarations and static variables
|
* Local function declarations and static variables
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
static void eisa_reg_print __P((struct eisa_device *e_dev,
|
static void eisa_reg_print __P((struct eisa_device *e_dev,
|
||||||
char *string, char *separator));
|
char *string, char *separator));
|
||||||
static int eisa_add_resvaddr __P((struct eisa_device *e_dev,
|
static int eisa_add_resvaddr __P((struct eisa_device *e_dev,
|
||||||
@ -85,7 +94,9 @@ static int eisa_add_resvaddr __P((struct eisa_device *e_dev,
|
|||||||
static int eisa_reg_resvaddr __P((struct eisa_device *e_dev,
|
static int eisa_reg_resvaddr __P((struct eisa_device *e_dev,
|
||||||
struct resvlist *head, resvaddr_t *resvaddr,
|
struct resvlist *head, resvaddr_t *resvaddr,
|
||||||
int *reg_count));
|
int *reg_count));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
* Keep some state about what we've printed so far
|
* Keep some state about what we've printed so far
|
||||||
* to make probe output pretty.
|
* to make probe output pretty.
|
||||||
@ -98,29 +109,77 @@ static struct {
|
|||||||
int column; /* How much we have output so far. */
|
int column; /* How much we have output so far. */
|
||||||
#define MAX_COL 80
|
#define MAX_COL 80
|
||||||
} reg_state;
|
} reg_state;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Global variable, so UserConfig can change it. */
|
/* Global variable, so UserConfig can change it. */
|
||||||
#ifndef EISA_SLOTS
|
#ifndef EISA_SLOTS
|
||||||
#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
|
#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
|
||||||
#endif
|
#endif
|
||||||
int num_eisa_slots = EISA_SLOTS;
|
int num_eisa_slots = EISA_SLOTS;
|
||||||
|
|
||||||
|
static devclass_t eisa_devclass;
|
||||||
|
|
||||||
|
static int
|
||||||
|
mainboard_probe(device_t dev)
|
||||||
|
{
|
||||||
|
char *idstring;
|
||||||
|
eisa_id_t id = eisa_get_id(dev);
|
||||||
|
|
||||||
|
if (eisa_get_slot(dev) != 0)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,
|
||||||
|
M_DEVBUF, M_NOWAIT);
|
||||||
|
if (idstring == NULL) {
|
||||||
|
panic("Eisa probe unable to malloc");
|
||||||
|
}
|
||||||
|
sprintf(idstring, "%c%c%c%x%x (System Board)",
|
||||||
|
EISA_MFCTR_CHAR0(id),
|
||||||
|
EISA_MFCTR_CHAR1(id),
|
||||||
|
EISA_MFCTR_CHAR2(id),
|
||||||
|
EISA_PRODUCT_ID(id),
|
||||||
|
EISA_REVISION_ID(id));
|
||||||
|
device_set_desc(dev, idstring);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mainboard_attach(device_t dev)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t mainboard_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, mainboard_probe),
|
||||||
|
DEVMETHOD(device_attach, mainboard_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t mainboard_driver = {
|
||||||
|
"mainboard",
|
||||||
|
mainboard_methods,
|
||||||
|
DRIVER_TYPE_MISC,
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t mainboard_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** probe for EISA devices
|
** probe for EISA devices
|
||||||
*/
|
*/
|
||||||
void
|
static int
|
||||||
eisa_configure()
|
eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
int i,slot;
|
int i,slot;
|
||||||
struct eisa_device_node *dev_node;
|
|
||||||
struct eisa_driver **e_drvp;
|
|
||||||
struct eisa_driver *e_drv;
|
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
int eisaBase = 0xc80;
|
int eisaBase = 0xc80;
|
||||||
eisa_id_t eisa_id;
|
eisa_id_t eisa_id;
|
||||||
|
|
||||||
e_drvp = (struct eisa_driver**)eisadriver_set.ls_items;
|
|
||||||
|
|
||||||
for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) {
|
for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) {
|
||||||
int id_size = sizeof(eisa_id);
|
int id_size = sizeof(eisa_id);
|
||||||
eisa_id = 0;
|
eisa_id = 0;
|
||||||
@ -132,19 +191,16 @@ eisa_configure()
|
|||||||
continue; /* no EISA card in slot */
|
continue; /* no EISA card in slot */
|
||||||
|
|
||||||
/* Prepare an eisa_device_node for this slot */
|
/* Prepare an eisa_device_node for this slot */
|
||||||
dev_node = (struct eisa_device_node *)malloc(sizeof(*dev_node),
|
e_dev = (struct eisa_device *)malloc(sizeof(*e_dev),
|
||||||
M_DEVBUF, M_NOWAIT);
|
M_DEVBUF, M_NOWAIT);
|
||||||
if (!dev_node) {
|
if (!e_dev) {
|
||||||
printf("eisa0: cannot malloc eisa_device_node");
|
printf("eisa0: cannot malloc eisa_device");
|
||||||
break; /* Try to attach what we have already */
|
break; /* Try to attach what we have already */
|
||||||
}
|
}
|
||||||
bzero(dev_node, sizeof(*dev_node));
|
bzero(e_dev, sizeof(*e_dev));
|
||||||
e_dev = &(dev_node->dev);
|
|
||||||
|
|
||||||
e_dev->id = eisa_id;
|
e_dev->id = eisa_id;
|
||||||
|
|
||||||
e_dev->full_name = "Unattached Device";
|
|
||||||
|
|
||||||
e_dev->ioconf.slot = slot;
|
e_dev->ioconf.slot = slot;
|
||||||
|
|
||||||
/* Initialize our lists of reserved addresses */
|
/* Initialize our lists of reserved addresses */
|
||||||
@ -152,134 +208,202 @@ eisa_configure()
|
|||||||
LIST_INIT(&(e_dev->ioconf.maddrs));
|
LIST_INIT(&(e_dev->ioconf.maddrs));
|
||||||
TAILQ_INIT(&(e_dev->ioconf.irqs));
|
TAILQ_INIT(&(e_dev->ioconf.irqs));
|
||||||
|
|
||||||
*eisa_dev_list_tail = dev_node;
|
device_add_child(dev, NULL, -1, e_dev);
|
||||||
eisa_dev_list_tail = &dev_node->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_node = eisa_dev_list;
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* "Attach" the system board
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The first will be the motherboard in a true EISA system */
|
|
||||||
if (dev_node && (dev_node->dev.ioconf.slot == 0)) {
|
|
||||||
char *idstring;
|
|
||||||
|
|
||||||
e_dev = &dev_node->dev;
|
|
||||||
e_dev->driver = &mainboard_drv;
|
|
||||||
e_dev->unit = (*e_dev->driver->unit)++;
|
|
||||||
idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,
|
|
||||||
M_DEVBUF, M_NOWAIT);
|
|
||||||
if (idstring == NULL) {
|
|
||||||
panic("Eisa probe unable to malloc");
|
|
||||||
}
|
|
||||||
sprintf(idstring, "%c%c%c%x%x (System Board)",
|
|
||||||
EISA_MFCTR_CHAR0(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR1(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR2(e_dev->id),
|
|
||||||
EISA_PRODUCT_ID(e_dev->id),
|
|
||||||
EISA_REVISION_ID(e_dev->id));
|
|
||||||
e_dev->full_name = idstring;
|
|
||||||
|
|
||||||
printf("%s%ld: <%s>\n",
|
|
||||||
e_dev->driver->name,
|
|
||||||
e_dev->unit,
|
|
||||||
e_dev->full_name);
|
|
||||||
|
|
||||||
/* Should set the iosize, but I don't have a spec handy */
|
|
||||||
printf("Probing for devices on the EISA bus\n");
|
|
||||||
dev_node = dev_node->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!eisa_dev_list) {
|
|
||||||
/*
|
|
||||||
* No devices.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* See what devices we recognize.
|
|
||||||
*/
|
|
||||||
while((e_drv = *e_drvp++)) {
|
|
||||||
if (e_drv->probe)
|
|
||||||
(*e_drv->probe)();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Attach the devices we found in slot order
|
|
||||||
*/
|
|
||||||
for (; dev_node; dev_node=dev_node->next) {
|
|
||||||
e_dev = &dev_node->dev;
|
|
||||||
e_drv = e_dev->driver;
|
|
||||||
|
|
||||||
if (e_drv) {
|
|
||||||
/*
|
|
||||||
* Determine the proper unit number for this device.
|
|
||||||
* Here we should look in the device table generated
|
|
||||||
* by config to see if this type of device is enabled
|
|
||||||
* either generically or for this particular address
|
|
||||||
* as well as determine if a reserved unit number
|
|
||||||
* should be used. We should also ensure that the
|
|
||||||
* "next availible unit number" skips over "wired" unit
|
|
||||||
* numbers. This will be done after config is fixed or
|
|
||||||
* some other configuration method is chosen.
|
|
||||||
*/
|
|
||||||
e_dev->unit = (*e_drv->unit)++;
|
|
||||||
if ((*e_drv->attach)(e_dev) < 0) {
|
|
||||||
/* Ensure registration has ended */
|
|
||||||
reg_state.in_registration = 0;
|
|
||||||
printf("\n%s0:%d <%s> attach failed\n",
|
|
||||||
mainboard_drv.name,
|
|
||||||
e_dev->ioconf.slot,
|
|
||||||
e_dev->full_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Ensure registration has ended */
|
|
||||||
reg_state.in_registration = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Announce unattached device */
|
|
||||||
printf("%s0:%d <%c%c%c%x%x=0x%x> unknown device\n",
|
|
||||||
mainboard_drv.name,
|
|
||||||
e_dev->ioconf.slot,
|
|
||||||
EISA_MFCTR_CHAR0(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR1(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR2(e_dev->id),
|
|
||||||
EISA_PRODUCT_ID(e_dev->id),
|
|
||||||
EISA_REVISION_ID(e_dev->id),
|
|
||||||
e_dev->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct eisa_device *
|
static void
|
||||||
eisa_match_dev(e_dev, match_func)
|
eisa_print_child(device_t dev, device_t child)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
const char* (*match_func)(eisa_id_t);
|
|
||||||
{
|
{
|
||||||
struct eisa_device_node *e_node = eisa_dev_list;
|
/* XXX print resource descriptions? */
|
||||||
|
printf(" at slot %d", eisa_get_slot(child));
|
||||||
if (e_dev) {
|
printf(" on %s", device_get_nameunit(dev));
|
||||||
/* Start our search from the last successful match */
|
|
||||||
e_node = ((struct eisa_device_node *)e_dev)->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(; e_node; e_node = e_node->next) {
|
|
||||||
const char *result;
|
|
||||||
if (e_node->dev.driver) {
|
|
||||||
/* Already claimed */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result = (*match_func)(e_node->dev.id);
|
|
||||||
if (result) {
|
|
||||||
e_node->dev.full_name = result;
|
|
||||||
return (&(e_node->dev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_find_irq(struct eisa_device *e_dev, int rid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct irq_node *irq;
|
||||||
|
|
||||||
|
for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs);
|
||||||
|
i < rid && irq;
|
||||||
|
i++, irq = TAILQ_NEXT(irq, links))
|
||||||
|
;
|
||||||
|
|
||||||
|
if (irq)
|
||||||
|
return irq->irq_no;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resvaddr *
|
||||||
|
eisa_find_maddr(struct eisa_device *e_dev, int rid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs);
|
||||||
|
i < rid && resv;
|
||||||
|
i++, resv = LIST_NEXT(resv, links))
|
||||||
|
;
|
||||||
|
|
||||||
|
return resv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resvaddr *
|
||||||
|
eisa_find_ioaddr(struct eisa_device *e_dev, int rid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs);
|
||||||
|
i < rid && resv;
|
||||||
|
i++, resv = LIST_NEXT(resv, links))
|
||||||
|
;
|
||||||
|
|
||||||
|
return resv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_read_ivar(device_t dev, device_t child, int which, u_long *result)
|
||||||
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(child);
|
||||||
|
|
||||||
|
switch (which) {
|
||||||
|
case EISA_IVAR_SLOT:
|
||||||
|
*result = e_dev->ioconf.slot;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EISA_IVAR_ID:
|
||||||
|
*result = e_dev->id;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EISA_IVAR_IRQ:
|
||||||
|
/* XXX only first irq */
|
||||||
|
*result = eisa_find_irq(e_dev, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
|
||||||
|
{
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resource *
|
||||||
|
eisa_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||||
|
u_long start, u_long end, u_long count, u_int flags)
|
||||||
|
{
|
||||||
|
int isdefault;
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(child);
|
||||||
|
struct resource *rv, **rvp = 0;
|
||||||
|
|
||||||
|
isdefault = (device_get_parent(child) == dev
|
||||||
|
&& start == 0UL && end == ~0UL && count == 1);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SYS_RES_IRQ:
|
||||||
|
if (isdefault) {
|
||||||
|
int irq = eisa_find_irq(e_dev, *rid);
|
||||||
|
if (irq == -1)
|
||||||
|
return 0;
|
||||||
|
start = end = irq;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_RES_MEMORY:
|
||||||
|
if (isdefault) {
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
resv = eisa_find_maddr(e_dev, *rid);
|
||||||
|
if (!resv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
start = resv->addr;
|
||||||
|
end = resv->size - 1;
|
||||||
|
count = resv->size;
|
||||||
|
rvp = &resv->res;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_RES_IOPORT:
|
||||||
|
if (isdefault) {
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
resv = eisa_find_ioaddr(e_dev, *rid);
|
||||||
|
if (!resv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
start = resv->addr;
|
||||||
|
end = resv->size - 1;
|
||||||
|
count = resv->size;
|
||||||
|
rvp = &resv->res;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
|
||||||
|
type, rid, start, end, count, flags);
|
||||||
|
if (rvp)
|
||||||
|
*rvp = rv;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_release_resource(device_t dev, device_t child, int type, int rid,
|
||||||
|
struct resource *r)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(child);
|
||||||
|
struct resvaddr *resv = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SYS_RES_IRQ:
|
||||||
|
if (eisa_find_irq(e_dev, rid) == -1)
|
||||||
|
return EINVAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_RES_MEMORY:
|
||||||
|
if (device_get_parent(child) == dev)
|
||||||
|
resv = eisa_find_maddr(e_dev, rid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case SYS_RES_IOPORT:
|
||||||
|
if (device_get_parent(child) == dev)
|
||||||
|
resv = eisa_find_ioaddr(e_dev, rid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r);
|
||||||
|
|
||||||
|
if (rv == 0) {
|
||||||
|
if (resv)
|
||||||
|
resv->res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
/* Interrupt and I/O space registration facitlities */
|
/* Interrupt and I/O space registration facitlities */
|
||||||
void
|
void
|
||||||
eisa_reg_start(e_dev)
|
eisa_reg_start(e_dev)
|
||||||
@ -362,11 +486,14 @@ eisa_reg_end(e_dev)
|
|||||||
"registration session\n");
|
"registration session\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_add_intr(e_dev, irq)
|
eisa_add_intr(dev, irq)
|
||||||
struct eisa_device *e_dev;
|
device_t dev;
|
||||||
int irq;
|
int irq;
|
||||||
{
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(dev);
|
||||||
struct irq_node *irq_info;
|
struct irq_node *irq_info;
|
||||||
|
|
||||||
irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF,
|
irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF,
|
||||||
@ -380,6 +507,8 @@ eisa_add_intr(e_dev, irq)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
|
eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
@ -494,6 +623,8 @@ eisa_enable_intr(e_dev, irq)
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eisa_add_resvaddr(e_dev, head, base, size, flags)
|
eisa_add_resvaddr(e_dev, head, base, size, flags)
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
@ -548,27 +679,31 @@ eisa_add_resvaddr(e_dev, head, base, size, flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_add_mspace(e_dev, mbase, msize, flags)
|
eisa_add_mspace(dev, mbase, msize, flags)
|
||||||
struct eisa_device *e_dev;
|
device_t dev;
|
||||||
u_long mbase;
|
u_long mbase;
|
||||||
u_long msize;
|
u_long msize;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(dev);
|
||||||
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
|
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
|
||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_add_iospace(e_dev, iobase, iosize, flags)
|
eisa_add_iospace(dev, iobase, iosize, flags)
|
||||||
struct eisa_device *e_dev;
|
device_t dev;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
u_long iosize;
|
u_long iosize;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(dev);
|
||||||
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
|
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
|
||||||
iosize, flags);
|
iosize, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eisa_reg_resvaddr(e_dev, head, resvaddr, reg_count)
|
eisa_reg_resvaddr(e_dev, head, resvaddr, reg_count)
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
@ -650,12 +785,35 @@ eisa_reg_iospace(e_dev, resvaddr)
|
|||||||
&(reg_state.num_ioaddrs)));
|
&(reg_state.num_ioaddrs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
#endif
|
||||||
eisa_registerdev(e_dev, driver)
|
|
||||||
struct eisa_device *e_dev;
|
static device_method_t eisa_methods[] = {
|
||||||
struct eisa_driver *driver;
|
/* Device interface */
|
||||||
{
|
DEVMETHOD(device_probe, eisa_probe),
|
||||||
e_dev->driver = driver; /* Driver now owns this device */
|
DEVMETHOD(device_attach, bus_generic_attach),
|
||||||
return (0);
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||||
}
|
|
||||||
|
/* Bus interface */
|
||||||
|
DEVMETHOD(bus_print_child, eisa_print_child),
|
||||||
|
DEVMETHOD(bus_read_ivar, eisa_read_ivar),
|
||||||
|
DEVMETHOD(bus_write_ivar, eisa_write_ivar),
|
||||||
|
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
||||||
|
DEVMETHOD(bus_alloc_resource, eisa_alloc_resource),
|
||||||
|
DEVMETHOD(bus_release_resource, eisa_release_resource),
|
||||||
|
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||||
|
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||||
|
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||||
|
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t eisa_driver = {
|
||||||
|
"eisa",
|
||||||
|
eisa_methods,
|
||||||
|
DRIVER_TYPE_MISC,
|
||||||
|
1, /* no softc */
|
||||||
|
};
|
||||||
|
|
||||||
|
DRIVER_MODULE(eisa, isab, eisa_driver, eisa_devclass, 0, 0);
|
||||||
|
|
||||||
|
@ -28,14 +28,12 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: eisaconf.h,v 1.16 1997/03/13 18:04:05 joerg Exp $
|
* $Id: eisaconf.h,v 1.17 1997/09/21 21:35:23 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _I386_EISA_EISACONF_H_
|
#ifndef _I386_EISA_EISACONF_H_
|
||||||
#define _I386_EISA_EISACONF_H_ 1
|
#define _I386_EISA_EISACONF_H_ 1
|
||||||
|
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
#define EISA_SLOT_SIZE 0x1000
|
#define EISA_SLOT_SIZE 0x1000
|
||||||
|
|
||||||
#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
|
#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
|
||||||
@ -45,79 +43,46 @@
|
|||||||
#define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */
|
#define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */
|
||||||
#define EISA_REVISION_ID(ID) (u_char)(ID & 0x0F) /* Bits 0-3 */
|
#define EISA_REVISION_ID(ID) (u_char)(ID & 0x0F) /* Bits 0-3 */
|
||||||
|
|
||||||
extern struct linker_set eisadriver_set;
|
|
||||||
extern int num_eisa_slots;
|
extern int num_eisa_slots;
|
||||||
|
|
||||||
typedef u_int32_t eisa_id_t;
|
typedef u_int32_t eisa_id_t;
|
||||||
|
|
||||||
typedef struct resvaddr {
|
enum eisa_device_ivars {
|
||||||
u_long addr; /* start address */
|
EISA_IVAR_SLOT,
|
||||||
u_long size; /* size of reserved area */
|
EISA_IVAR_ID,
|
||||||
int flags;
|
EISA_IVAR_IRQ
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified accessors for isa devices
|
||||||
|
*/
|
||||||
|
#define EISA_ACCESSOR(A, B, T) \
|
||||||
|
\
|
||||||
|
static __inline T eisa_get_ ## A(device_t dev) \
|
||||||
|
{ \
|
||||||
|
uintptr_t v; \
|
||||||
|
BUS_READ_IVAR(device_get_parent(dev), dev, EISA_IVAR_ ## B, &v); \
|
||||||
|
return (T) v; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static __inline void eisa_set_ ## A(device_t dev, T t) \
|
||||||
|
{ \
|
||||||
|
u_long v = (u_long) t; \
|
||||||
|
BUS_WRITE_IVAR(device_get_parent(dev), dev, EISA_IVAR_ ## B, v); \
|
||||||
|
}
|
||||||
|
|
||||||
|
EISA_ACCESSOR(slot, SLOT, int)
|
||||||
|
EISA_ACCESSOR(id, ID, eisa_id_t)
|
||||||
|
EISA_ACCESSOR(irq, IRQ, eisa_id_t)
|
||||||
|
|
||||||
|
int eisa_add_intr __P((device_t, int));
|
||||||
|
|
||||||
#define RESVADDR_NONE 0x00
|
#define RESVADDR_NONE 0x00
|
||||||
#define RESVADDR_BITMASK 0x01 /* size is a mask of reserved
|
#define RESVADDR_BITMASK 0x01 /* size is a mask of reserved
|
||||||
* bits at addr
|
* bits at addr
|
||||||
*/
|
*/
|
||||||
#define RESVADDR_RELOCATABLE 0x02
|
#define RESVADDR_RELOCATABLE 0x02
|
||||||
LIST_ENTRY(resvaddr) links; /* List links */
|
int eisa_add_iospace __P((device_t, u_long, u_long, int));
|
||||||
} resvaddr_t;
|
int eisa_add_mspace __P((device_t, u_long, u_long, int));
|
||||||
|
|
||||||
LIST_HEAD(resvlist, resvaddr);
|
|
||||||
|
|
||||||
struct irq_node {
|
|
||||||
int irq_no;
|
|
||||||
void *idesc;
|
|
||||||
TAILQ_ENTRY(irq_node) links;
|
|
||||||
};
|
|
||||||
|
|
||||||
TAILQ_HEAD(irqlist, irq_node);
|
|
||||||
|
|
||||||
struct eisa_ioconf {
|
|
||||||
int slot;
|
|
||||||
struct resvlist ioaddrs; /* list of reserved I/O ranges */
|
|
||||||
struct resvlist maddrs; /* list of reserved memory ranges */
|
|
||||||
struct irqlist irqs; /* list of reserved irqs */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct eisa_device;
|
|
||||||
|
|
||||||
struct eisa_driver {
|
|
||||||
char* name; /* device name */
|
|
||||||
int (*probe) __P((void));
|
|
||||||
/* test whether device is present */
|
|
||||||
int (*attach) __P((struct eisa_device *));
|
|
||||||
/* setup driver for a device */
|
|
||||||
int (*shutdown) __P((int));
|
|
||||||
/* Return the device to a safe
|
|
||||||
* state before shutdown
|
|
||||||
*/
|
|
||||||
u_long *unit; /* Next available unit */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* To be replaced by the "super device" generic device structure... */
|
|
||||||
struct eisa_device {
|
|
||||||
eisa_id_t id;
|
|
||||||
u_long unit;
|
|
||||||
const char* full_name; /* for use in the probe message */
|
|
||||||
struct eisa_ioconf ioconf;
|
|
||||||
struct eisa_driver* driver;
|
|
||||||
};
|
|
||||||
|
|
||||||
void eisa_configure __P((void));
|
|
||||||
struct eisa_device *eisa_match_dev __P((struct eisa_device *,
|
|
||||||
const char * (*)(eisa_id_t)));
|
|
||||||
|
|
||||||
void eisa_reg_start __P((struct eisa_device *));
|
|
||||||
void eisa_reg_end __P((struct eisa_device *));
|
|
||||||
int eisa_add_intr __P((struct eisa_device *, int));
|
|
||||||
int eisa_reg_intr __P((struct eisa_device *, int, void (*)(void *),
|
|
||||||
void *, u_int *, int));
|
|
||||||
int eisa_release_intr __P((struct eisa_device *, int, void (*)(void *)));
|
|
||||||
int eisa_enable_intr __P((struct eisa_device *, int));
|
|
||||||
int eisa_add_iospace __P((struct eisa_device *, u_long, u_long, int));
|
|
||||||
int eisa_reg_iospace __P((struct eisa_device *, resvaddr_t *));
|
|
||||||
int eisa_add_mspace __P((struct eisa_device *, u_long, u_long, int));
|
|
||||||
int eisa_reg_mspace __P((struct eisa_device *, resvaddr_t *));
|
|
||||||
int eisa_registerdev __P((struct eisa_device *, struct eisa_driver *));
|
|
||||||
|
|
||||||
#endif /* _I386_EISA_EISACONF_H_ */
|
#endif /* _I386_EISA_EISACONF_H_ */
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* 4. Modifications may be freely made to this file if the above conditions
|
* 4. Modifications may be freely made to this file if the above conditions
|
||||||
* are met.
|
* are met.
|
||||||
*
|
*
|
||||||
* $Id: 3c5x9.c,v 1.9 1997/02/22 09:31:52 peter Exp $
|
* $Id: 3c5x9.c,v 1.10 1997/09/21 21:35:21 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -29,8 +29,13 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
@ -66,24 +71,10 @@
|
|||||||
#define TRANS_AUI 0x4000
|
#define TRANS_AUI 0x4000
|
||||||
#define TRANS_BNC 0xc000
|
#define TRANS_BNC 0xc000
|
||||||
|
|
||||||
static int ep_eisa_probe __P((void));
|
|
||||||
static int ep_eisa_attach __P((struct eisa_device *e_dev));
|
|
||||||
|
|
||||||
static struct eisa_driver ep_eisa_driver = {
|
|
||||||
"ep",
|
|
||||||
ep_eisa_probe,
|
|
||||||
ep_eisa_attach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&ep_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, ep_eisa_driver);
|
|
||||||
|
|
||||||
static const char *ep_match __P((eisa_id_t type));
|
static const char *ep_match __P((eisa_id_t type));
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
ep_match(type)
|
ep_match(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case EISA_DEVICE_ID_3COM_3C509_TP:
|
case EISA_DEVICE_ID_3COM_3C509_TP:
|
||||||
@ -111,122 +102,116 @@ ep_match(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ep_eisa_probe(void)
|
ep_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
struct eisa_device *e_dev = NULL;
|
u_short conf;
|
||||||
int count;
|
u_long port;
|
||||||
|
int irq;
|
||||||
|
|
||||||
count = 0;
|
desc = ep_match(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, ep_match))) {
|
if (!desc)
|
||||||
u_short conf;
|
return (ENXIO);
|
||||||
u_long port;
|
device_set_desc(dev, desc);
|
||||||
int irq;
|
|
||||||
|
|
||||||
port = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
|
port = (eisa_get_slot(dev) * EISA_SLOT_SIZE);
|
||||||
iobase = port + EP_EISA_SLOT_OFFSET;
|
iobase = port + EP_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
/* We must be in EISA configuration mode */
|
/* We must be in EISA configuration mode */
|
||||||
if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
|
if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
|
||||||
continue;
|
return ENXIO;
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
eisa_add_iospace(e_dev, port, EP_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, port, EP_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
conf = inw(iobase + EISA_IOCONF);
|
conf = inw(iobase + EISA_IOCONF);
|
||||||
/* Determine our IRQ */
|
/* Determine our IRQ */
|
||||||
switch (conf & IRQ_CHANNEL) {
|
switch (conf & IRQ_CHANNEL) {
|
||||||
case INT_3:
|
case INT_3:
|
||||||
irq = 3;
|
irq = 3;
|
||||||
break;
|
break;
|
||||||
case INT_5:
|
case INT_5:
|
||||||
irq = 5;
|
irq = 5;
|
||||||
break;
|
break;
|
||||||
case INT_7:
|
case INT_7:
|
||||||
irq = 7;
|
irq = 7;
|
||||||
break;
|
break;
|
||||||
case INT_9:
|
case INT_9:
|
||||||
irq = 9;
|
irq = 9;
|
||||||
break;
|
break;
|
||||||
case INT_10:
|
case INT_10:
|
||||||
irq = 10;
|
irq = 10;
|
||||||
break;
|
break;
|
||||||
case INT_11:
|
case INT_11:
|
||||||
irq = 11;
|
irq = 11;
|
||||||
break;
|
break;
|
||||||
case INT_12:
|
case INT_12:
|
||||||
irq = 12;
|
irq = 12;
|
||||||
break;
|
break;
|
||||||
case INT_15:
|
case INT_15:
|
||||||
irq = 15;
|
irq = 15;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Disabled */
|
/* Disabled */
|
||||||
printf("ep: 3COM Network Adapter at "
|
printf("ep: 3COM Network Adapter at "
|
||||||
"slot %d has its IRQ disabled. "
|
"slot %d has its IRQ disabled. "
|
||||||
"Probe failed.\n",
|
"Probe failed.\n",
|
||||||
e_dev->ioconf.slot);
|
eisa_get_slot(dev));
|
||||||
continue;
|
return ENXIO;
|
||||||
}
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &ep_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ep_eisa_attach(e_dev)
|
ep_eisa_attach(device_t dev)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
{
|
{
|
||||||
struct ep_softc *sc;
|
struct ep_softc *sc;
|
||||||
struct ep_board *epb;
|
struct ep_board *epb;
|
||||||
int unit = e_dev->unit;
|
struct resource *io = 0;
|
||||||
int irq;
|
struct resource *eisa_io = 0;
|
||||||
resvaddr_t *ioport;
|
struct resource *irq = 0;
|
||||||
resvaddr_t *eisa_ioport;
|
int unit = device_get_unit(dev);
|
||||||
u_char level_intr;
|
u_char level_intr;
|
||||||
int i;
|
int i, rid, shared;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
|
||||||
/*
|
/*
|
||||||
* The addresses are sorted in increasing order
|
* The addresses are sorted in increasing order
|
||||||
* so we know the port to pass to the core ep
|
* so we know the port to pass to the core ep
|
||||||
* driver comes first.
|
* driver comes first.
|
||||||
*/
|
*/
|
||||||
ioport = e_dev->ioconf.ioaddrs.lh_first;
|
rid = 0;
|
||||||
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
if(!ioport)
|
rid = 1;
|
||||||
return -1;
|
eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
eisa_ioport = ioport->links.le_next;
|
if (!eisa_io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
if(!eisa_ioport)
|
goto bad;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if(eisa_reg_iospace(e_dev, ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(eisa_reg_iospace(e_dev, eisa_ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
epb = &ep_board[ep_boards];
|
epb = &ep_board[ep_boards];
|
||||||
|
|
||||||
epb->epb_addr = ioport->addr;
|
epb->epb_addr = rman_get_start(io);
|
||||||
epb->epb_used = 1;
|
epb->epb_used = 1;
|
||||||
|
|
||||||
if(!(sc = ep_alloc(unit, epb)))
|
if(!(sc = ep_alloc(unit, epb)))
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
ep_boards++;
|
ep_boards++;
|
||||||
|
|
||||||
sc->stat = 0;
|
sc->stat = 0;
|
||||||
level_intr = FALSE;
|
level_intr = FALSE;
|
||||||
switch(e_dev->id) {
|
switch(eisa_get_id(dev)) {
|
||||||
case EISA_DEVICE_ID_3COM_3C509_TP:
|
case EISA_DEVICE_ID_3COM_3C509_TP:
|
||||||
sc->ep_connectors = UTP|AUI;
|
sc->ep_connectors = UTP|AUI;
|
||||||
break;
|
break;
|
||||||
@ -255,45 +240,71 @@ ep_eisa_attach(e_dev)
|
|||||||
/*
|
/*
|
||||||
* Set the eisa config selected media type
|
* Set the eisa config selected media type
|
||||||
*/
|
*/
|
||||||
sc->ep_connector = inw(eisa_ioport->addr + EISA_BPROM_MEDIA_CONF)
|
sc->ep_connector = inw(rman_get_start(eisa_io) + EISA_BPROM_MEDIA_CONF)
|
||||||
>> ACF_CONNECTOR_BITS;
|
>> ACF_CONNECTOR_BITS;
|
||||||
|
|
||||||
if(eisa_reg_intr(e_dev, irq, ep_intr, (void *)sc, &net_imask,
|
shared = level_intr ? RF_SHAREABLE : 0;
|
||||||
/*shared ==*/level_intr)) {
|
rid = 0;
|
||||||
ep_free(sc);
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
return -1;
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "No irq?!\n");
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/* Reset and Enable the card */
|
/* Reset and Enable the card */
|
||||||
outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
|
outb(rman_get_start(eisa_io) + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
|
||||||
DELAY(1000); /* we must wait at least 1 ms */
|
DELAY(1000); /* we must wait at least 1 ms */
|
||||||
outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
|
outb(rman_get_start(eisa_io) + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
|
||||||
|
|
||||||
/* Now the registers are availible through the lower ioport */
|
/* Now the registers are availible through the lower ioport */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve our ethernet address
|
* Retrieve our ethernet address
|
||||||
*/
|
*/
|
||||||
GO_WINDOW(0);
|
GO_WINDOW(0);
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < 3; i++)
|
||||||
sc->epb->eth_addr[i] = get_e(sc, i);
|
sc->epb->eth_addr[i] = get_e(sc, i);
|
||||||
|
|
||||||
/* Even we get irq number from board, we should tell him..
|
/* Even we get irq number from board, we should tell him..
|
||||||
Otherwise we never get a H/W interrupt anymore...*/
|
Otherwise we never get a H/W interrupt anymore...*/
|
||||||
if ( irq == 9 )
|
if ( rman_get_start(irq) == 9 )
|
||||||
irq = 2;
|
rman_get_start(irq) = 2;
|
||||||
SET_IRQ(eisa_ioport->addr, irq);
|
SET_IRQ(rman_get_start(eisa_io), rman_get_start(irq));
|
||||||
|
|
||||||
ep_attach(sc);
|
ep_attach(sc);
|
||||||
|
|
||||||
if(eisa_enable_intr(e_dev, irq)) {
|
bus_setup_intr(dev, irq, ep_intr, sc, &ih);
|
||||||
ep_free(sc);
|
|
||||||
eisa_release_intr(e_dev, irq, ep_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (eisa_io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t ep_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, ep_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, ep_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ep_eisa_driver = {
|
||||||
|
"ep",
|
||||||
|
ep_eisa_methods,
|
||||||
|
DRIVER_TYPE_NET,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ep_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -38,6 +38,12 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
@ -58,22 +64,9 @@
|
|||||||
|
|
||||||
|
|
||||||
static const char *vx_match __P((eisa_id_t type));
|
static const char *vx_match __P((eisa_id_t type));
|
||||||
static int vx_eisa_probe __P((void));
|
|
||||||
static int vx_eisa_attach __P((struct eisa_device *));
|
|
||||||
|
|
||||||
static struct eisa_driver vx_eisa_driver = {
|
|
||||||
"vx",
|
|
||||||
vx_eisa_probe,
|
|
||||||
vx_eisa_attach,
|
|
||||||
/* shutdown */ NULL,
|
|
||||||
&vx_count
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET(eisadriver_set, vx_eisa_driver);
|
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
vx_match(type)
|
vx_match(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EISA_DEVICE_ID_3COM_3C592:
|
case EISA_DEVICE_ID_3COM_3C592:
|
||||||
@ -95,88 +88,117 @@ vx_match(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vx_eisa_probe(void)
|
vx_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
struct eisa_device *e_dev = NULL;
|
u_long port;
|
||||||
int count;
|
|
||||||
|
|
||||||
count = 0;
|
desc = vx_match(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, vx_match))) {
|
if (!desc)
|
||||||
u_long port;
|
return (ENXIO);
|
||||||
|
device_set_desc(dev, desc);
|
||||||
|
|
||||||
port = e_dev->ioconf.slot * EISA_SLOT_SIZE;
|
port = eisa_get_slot(dev) * EISA_SLOT_SIZE;
|
||||||
iobase = port + VX_EISA_SLOT_OFFSET;
|
iobase = port + VX_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
eisa_add_iospace(e_dev, port, VX_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, port, VX_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
/* Set irq */
|
/* Set irq */
|
||||||
eisa_add_intr(e_dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12);
|
eisa_add_intr(dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12);
|
||||||
eisa_registerdev(e_dev, &vx_eisa_driver);
|
|
||||||
count++;
|
return (0);
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vx_eisa_attach(e_dev)
|
vx_eisa_attach(device_t dev)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
{
|
{
|
||||||
struct vx_softc *sc;
|
struct vx_softc *sc;
|
||||||
int unit = e_dev->unit;
|
int unit = device_get_unit(dev);
|
||||||
int irq;
|
struct resource *io = 0;
|
||||||
resvaddr_t *ioport;
|
struct resource *eisa_io = 0;
|
||||||
resvaddr_t *eisa_ioport;
|
struct resource *irq = 0;
|
||||||
u_char level_intr;
|
u_char level_intr;
|
||||||
|
int rid;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
/*
|
||||||
return (-1);
|
* The addresses are sorted in increasing order
|
||||||
|
* so we know the port to pass to the core ep
|
||||||
|
* driver comes first.
|
||||||
|
*/
|
||||||
|
rid = 0;
|
||||||
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
rid = 1;
|
||||||
|
eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
ioport = e_dev->ioconf.ioaddrs.lh_first;
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!eisa_io) {
|
||||||
if (!ioport)
|
device_printf(dev, "No I/O space?!\n");
|
||||||
return -1;
|
goto bad;
|
||||||
|
}
|
||||||
eisa_ioport = ioport->links.le_next;
|
|
||||||
|
|
||||||
if (!eisa_ioport)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (eisa_reg_iospace(e_dev, eisa_ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((sc = vxalloc(unit)) == NULL)
|
if ((sc = vxalloc(unit)) == NULL)
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
sc->vx_io_addr = ioport->addr;
|
sc->vx_io_addr = rman_get_start(io);
|
||||||
|
|
||||||
level_intr = FALSE;
|
level_intr = FALSE;
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, vxintr, (void *) sc, &net_imask,
|
rid = 0;
|
||||||
/* shared == */ level_intr)) {
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "No irq?!\n");
|
||||||
vxfree(sc);
|
vxfree(sc);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/* Now the registers are availible through the lower ioport */
|
/* Now the registers are availible through the lower ioport */
|
||||||
|
|
||||||
vxattach(sc);
|
vxattach(sc);
|
||||||
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
if (bus_setup_intr(dev, irq, vxintr, sc, &ih)) {
|
||||||
vxfree(sc);
|
vxfree(sc);
|
||||||
eisa_release_intr(e_dev, irq, vxintr);
|
goto bad;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (eisa_io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t vx_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, vx_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, vx_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t vx_eisa_driver = {
|
||||||
|
"vx",
|
||||||
|
vx_eisa_methods,
|
||||||
|
DRIVER_TYPE_NET,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t vx_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(vx, eisa, vx_eisa_driver, vx_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NVX > 0 */
|
#endif /* NVX > 0 */
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* 4. Modifications may be freely made to this file if the above conditions
|
* 4. Modifications may be freely made to this file if the above conditions
|
||||||
* are met.
|
* are met.
|
||||||
*
|
*
|
||||||
* $Id: 3c5x9.c,v 1.9 1997/02/22 09:31:52 peter Exp $
|
* $Id: 3c5x9.c,v 1.10 1997/09/21 21:35:21 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -29,8 +29,13 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
@ -66,24 +71,10 @@
|
|||||||
#define TRANS_AUI 0x4000
|
#define TRANS_AUI 0x4000
|
||||||
#define TRANS_BNC 0xc000
|
#define TRANS_BNC 0xc000
|
||||||
|
|
||||||
static int ep_eisa_probe __P((void));
|
|
||||||
static int ep_eisa_attach __P((struct eisa_device *e_dev));
|
|
||||||
|
|
||||||
static struct eisa_driver ep_eisa_driver = {
|
|
||||||
"ep",
|
|
||||||
ep_eisa_probe,
|
|
||||||
ep_eisa_attach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&ep_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, ep_eisa_driver);
|
|
||||||
|
|
||||||
static const char *ep_match __P((eisa_id_t type));
|
static const char *ep_match __P((eisa_id_t type));
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
ep_match(type)
|
ep_match(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case EISA_DEVICE_ID_3COM_3C509_TP:
|
case EISA_DEVICE_ID_3COM_3C509_TP:
|
||||||
@ -111,122 +102,116 @@ ep_match(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ep_eisa_probe(void)
|
ep_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
struct eisa_device *e_dev = NULL;
|
u_short conf;
|
||||||
int count;
|
u_long port;
|
||||||
|
int irq;
|
||||||
|
|
||||||
count = 0;
|
desc = ep_match(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, ep_match))) {
|
if (!desc)
|
||||||
u_short conf;
|
return (ENXIO);
|
||||||
u_long port;
|
device_set_desc(dev, desc);
|
||||||
int irq;
|
|
||||||
|
|
||||||
port = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
|
port = (eisa_get_slot(dev) * EISA_SLOT_SIZE);
|
||||||
iobase = port + EP_EISA_SLOT_OFFSET;
|
iobase = port + EP_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
/* We must be in EISA configuration mode */
|
/* We must be in EISA configuration mode */
|
||||||
if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
|
if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
|
||||||
continue;
|
return ENXIO;
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
eisa_add_iospace(e_dev, port, EP_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, port, EP_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
conf = inw(iobase + EISA_IOCONF);
|
conf = inw(iobase + EISA_IOCONF);
|
||||||
/* Determine our IRQ */
|
/* Determine our IRQ */
|
||||||
switch (conf & IRQ_CHANNEL) {
|
switch (conf & IRQ_CHANNEL) {
|
||||||
case INT_3:
|
case INT_3:
|
||||||
irq = 3;
|
irq = 3;
|
||||||
break;
|
break;
|
||||||
case INT_5:
|
case INT_5:
|
||||||
irq = 5;
|
irq = 5;
|
||||||
break;
|
break;
|
||||||
case INT_7:
|
case INT_7:
|
||||||
irq = 7;
|
irq = 7;
|
||||||
break;
|
break;
|
||||||
case INT_9:
|
case INT_9:
|
||||||
irq = 9;
|
irq = 9;
|
||||||
break;
|
break;
|
||||||
case INT_10:
|
case INT_10:
|
||||||
irq = 10;
|
irq = 10;
|
||||||
break;
|
break;
|
||||||
case INT_11:
|
case INT_11:
|
||||||
irq = 11;
|
irq = 11;
|
||||||
break;
|
break;
|
||||||
case INT_12:
|
case INT_12:
|
||||||
irq = 12;
|
irq = 12;
|
||||||
break;
|
break;
|
||||||
case INT_15:
|
case INT_15:
|
||||||
irq = 15;
|
irq = 15;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Disabled */
|
/* Disabled */
|
||||||
printf("ep: 3COM Network Adapter at "
|
printf("ep: 3COM Network Adapter at "
|
||||||
"slot %d has its IRQ disabled. "
|
"slot %d has its IRQ disabled. "
|
||||||
"Probe failed.\n",
|
"Probe failed.\n",
|
||||||
e_dev->ioconf.slot);
|
eisa_get_slot(dev));
|
||||||
continue;
|
return ENXIO;
|
||||||
}
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &ep_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ep_eisa_attach(e_dev)
|
ep_eisa_attach(device_t dev)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
{
|
{
|
||||||
struct ep_softc *sc;
|
struct ep_softc *sc;
|
||||||
struct ep_board *epb;
|
struct ep_board *epb;
|
||||||
int unit = e_dev->unit;
|
struct resource *io = 0;
|
||||||
int irq;
|
struct resource *eisa_io = 0;
|
||||||
resvaddr_t *ioport;
|
struct resource *irq = 0;
|
||||||
resvaddr_t *eisa_ioport;
|
int unit = device_get_unit(dev);
|
||||||
u_char level_intr;
|
u_char level_intr;
|
||||||
int i;
|
int i, rid, shared;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
|
||||||
/*
|
/*
|
||||||
* The addresses are sorted in increasing order
|
* The addresses are sorted in increasing order
|
||||||
* so we know the port to pass to the core ep
|
* so we know the port to pass to the core ep
|
||||||
* driver comes first.
|
* driver comes first.
|
||||||
*/
|
*/
|
||||||
ioport = e_dev->ioconf.ioaddrs.lh_first;
|
rid = 0;
|
||||||
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
if(!ioport)
|
rid = 1;
|
||||||
return -1;
|
eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
eisa_ioport = ioport->links.le_next;
|
if (!eisa_io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
if(!eisa_ioport)
|
goto bad;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if(eisa_reg_iospace(e_dev, ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(eisa_reg_iospace(e_dev, eisa_ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
epb = &ep_board[ep_boards];
|
epb = &ep_board[ep_boards];
|
||||||
|
|
||||||
epb->epb_addr = ioport->addr;
|
epb->epb_addr = rman_get_start(io);
|
||||||
epb->epb_used = 1;
|
epb->epb_used = 1;
|
||||||
|
|
||||||
if(!(sc = ep_alloc(unit, epb)))
|
if(!(sc = ep_alloc(unit, epb)))
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
ep_boards++;
|
ep_boards++;
|
||||||
|
|
||||||
sc->stat = 0;
|
sc->stat = 0;
|
||||||
level_intr = FALSE;
|
level_intr = FALSE;
|
||||||
switch(e_dev->id) {
|
switch(eisa_get_id(dev)) {
|
||||||
case EISA_DEVICE_ID_3COM_3C509_TP:
|
case EISA_DEVICE_ID_3COM_3C509_TP:
|
||||||
sc->ep_connectors = UTP|AUI;
|
sc->ep_connectors = UTP|AUI;
|
||||||
break;
|
break;
|
||||||
@ -255,45 +240,71 @@ ep_eisa_attach(e_dev)
|
|||||||
/*
|
/*
|
||||||
* Set the eisa config selected media type
|
* Set the eisa config selected media type
|
||||||
*/
|
*/
|
||||||
sc->ep_connector = inw(eisa_ioport->addr + EISA_BPROM_MEDIA_CONF)
|
sc->ep_connector = inw(rman_get_start(eisa_io) + EISA_BPROM_MEDIA_CONF)
|
||||||
>> ACF_CONNECTOR_BITS;
|
>> ACF_CONNECTOR_BITS;
|
||||||
|
|
||||||
if(eisa_reg_intr(e_dev, irq, ep_intr, (void *)sc, &net_imask,
|
shared = level_intr ? RF_SHAREABLE : 0;
|
||||||
/*shared ==*/level_intr)) {
|
rid = 0;
|
||||||
ep_free(sc);
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
return -1;
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "No irq?!\n");
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/* Reset and Enable the card */
|
/* Reset and Enable the card */
|
||||||
outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
|
outb(rman_get_start(eisa_io) + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
|
||||||
DELAY(1000); /* we must wait at least 1 ms */
|
DELAY(1000); /* we must wait at least 1 ms */
|
||||||
outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
|
outb(rman_get_start(eisa_io) + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
|
||||||
|
|
||||||
/* Now the registers are availible through the lower ioport */
|
/* Now the registers are availible through the lower ioport */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve our ethernet address
|
* Retrieve our ethernet address
|
||||||
*/
|
*/
|
||||||
GO_WINDOW(0);
|
GO_WINDOW(0);
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < 3; i++)
|
||||||
sc->epb->eth_addr[i] = get_e(sc, i);
|
sc->epb->eth_addr[i] = get_e(sc, i);
|
||||||
|
|
||||||
/* Even we get irq number from board, we should tell him..
|
/* Even we get irq number from board, we should tell him..
|
||||||
Otherwise we never get a H/W interrupt anymore...*/
|
Otherwise we never get a H/W interrupt anymore...*/
|
||||||
if ( irq == 9 )
|
if ( rman_get_start(irq) == 9 )
|
||||||
irq = 2;
|
rman_get_start(irq) = 2;
|
||||||
SET_IRQ(eisa_ioport->addr, irq);
|
SET_IRQ(rman_get_start(eisa_io), rman_get_start(irq));
|
||||||
|
|
||||||
ep_attach(sc);
|
ep_attach(sc);
|
||||||
|
|
||||||
if(eisa_enable_intr(e_dev, irq)) {
|
bus_setup_intr(dev, irq, ep_intr, sc, &ih);
|
||||||
ep_free(sc);
|
|
||||||
eisa_release_intr(e_dev, irq, ep_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (eisa_io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t ep_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, ep_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, ep_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ep_eisa_driver = {
|
||||||
|
"ep",
|
||||||
|
ep_eisa_methods,
|
||||||
|
DRIVER_TYPE_NET,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ep_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: adv_eisa.c,v 1.1 1998/09/15 07:05:39 gibbs Exp $
|
* $Id: adv_eisa.c,v 1.2 1998/12/22 18:14:09 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -41,9 +41,13 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
@ -69,9 +73,6 @@
|
|||||||
#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL)
|
#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL)
|
||||||
#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL)
|
#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL)
|
||||||
|
|
||||||
static int adveisaprobe(void);
|
|
||||||
static int adveisaattach(struct eisa_device *e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The overrun buffer shared amongst all EISA adapters.
|
* The overrun buffer shared amongst all EISA adapters.
|
||||||
*/
|
*/
|
||||||
@ -80,22 +81,10 @@ static bus_dma_tag_t overrun_dmat;
|
|||||||
static bus_dmamap_t overrun_dmamap;
|
static bus_dmamap_t overrun_dmamap;
|
||||||
static bus_addr_t overrun_physbase;
|
static bus_addr_t overrun_physbase;
|
||||||
|
|
||||||
static struct eisa_driver adv_eisa_driver =
|
|
||||||
{
|
|
||||||
"adv",
|
|
||||||
adveisaprobe,
|
|
||||||
adveisaattach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&adv_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, adv_eisa_driver);
|
|
||||||
|
|
||||||
static const char *adveisamatch(eisa_id_t type);
|
static const char *adveisamatch(eisa_id_t type);
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
adveisamatch(type)
|
adveisamatch(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch (type & ~0xF) {
|
switch (type & ~0xF) {
|
||||||
case EISA_DEVICE_ID_ADVANSYS_740:
|
case EISA_DEVICE_ID_ADVANSYS_740:
|
||||||
@ -111,69 +100,78 @@ adveisamatch(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
adveisaprobe(void)
|
adveisaprobe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_int32_t iobase;
|
u_int32_t iobase;
|
||||||
u_int8_t irq;
|
u_int8_t irq;
|
||||||
struct eisa_device *e_dev = NULL;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count = 0;
|
desc = adveisamatch(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, adveisamatch))) {
|
if (!desc)
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
|
return (ENXIO);
|
||||||
+ ADV_EISA_SLOT_OFFSET;
|
device_set_desc(dev, desc);
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE)
|
||||||
irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
|
+ ADV_EISA_SLOT_OFFSET;
|
||||||
irq &= ADV_EISA_IRQ_MASK;
|
|
||||||
switch (irq) {
|
eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
case 0:
|
irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
|
||||||
case 1:
|
irq &= ADV_EISA_IRQ_MASK;
|
||||||
case 2:
|
switch (irq) {
|
||||||
case 4:
|
case 0:
|
||||||
case 5:
|
case 1:
|
||||||
break;
|
case 2:
|
||||||
default:
|
case 4:
|
||||||
printf("adv at slot %d: illegal "
|
case 5:
|
||||||
"irq setting %d\n", e_dev->ioconf.slot,
|
break;
|
||||||
irq);
|
default:
|
||||||
continue;
|
printf("adv at slot %d: illegal "
|
||||||
}
|
"irq setting %d\n", eisa_get_slot(dev),
|
||||||
eisa_add_intr(e_dev, irq + 10);
|
irq);
|
||||||
eisa_registerdev(e_dev, &adv_eisa_driver);
|
return ENXIO;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
eisa_add_intr(dev, irq + 10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
adveisaattach(struct eisa_device *e_dev)
|
adveisaattach(device_t dev)
|
||||||
{
|
{
|
||||||
struct adv_softc *adv;
|
struct adv_softc *adv;
|
||||||
struct adv_softc *adv_b;
|
struct adv_softc *adv_b;
|
||||||
resvaddr_t *iospace;
|
struct resource *io;
|
||||||
int unit;
|
struct resource *irq;
|
||||||
int irq;
|
int unit = device_get_unit(dev);
|
||||||
int error;
|
int rid, error;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
adv_b = NULL;
|
adv_b = NULL;
|
||||||
unit = e_dev->unit;
|
|
||||||
iospace = e_dev->ioconf.ioaddrs.lh_first;
|
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
rid = 0;
|
||||||
return (-1);
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "No irq?!\n");
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
if (!iospace)
|
}
|
||||||
return (-1);
|
|
||||||
|
|
||||||
switch (e_dev->id & ~0xF) {
|
switch (eisa_get_id(dev) & ~0xF) {
|
||||||
case EISA_DEVICE_ID_ADVANSYS_750:
|
case EISA_DEVICE_ID_ADVANSYS_750:
|
||||||
adv_b = adv_alloc(unit, I386_BUS_SPACE_IO,
|
adv_b = adv_alloc(unit, rman_get_bustag(io),
|
||||||
iospace->addr + ADV_EISA_OFFSET_CHAN2);
|
rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2);
|
||||||
if (adv_b == NULL)
|
if (adv_b == NULL)
|
||||||
return (-1);
|
goto bad;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a parent dmatag for all tags created
|
* Allocate a parent dmatag for all tags created
|
||||||
@ -195,19 +193,19 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
printf("%s: Could not allocate DMA tag - error %d\n",
|
printf("%s: Could not allocate DMA tag - error %d\n",
|
||||||
adv_name(adv_b), error);
|
adv_name(adv_b), error);
|
||||||
adv_free(adv_b);
|
adv_free(adv_b);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
adv_b->init_level++;
|
adv_b->init_level++;
|
||||||
|
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case EISA_DEVICE_ID_ADVANSYS_740:
|
case EISA_DEVICE_ID_ADVANSYS_740:
|
||||||
adv = adv_alloc(unit, I386_BUS_SPACE_IO,
|
adv = adv_alloc(unit, rman_get_bustag(io),
|
||||||
iospace->addr + ADV_EISA_OFFSET_CHAN1);
|
rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1);
|
||||||
if (adv == NULL) {
|
if (adv == NULL) {
|
||||||
if (adv_b != NULL)
|
if (adv_b != NULL)
|
||||||
adv_free(adv_b);
|
adv_free(adv_b);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -230,14 +228,14 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
printf("%s: Could not allocate DMA tag - error %d\n",
|
printf("%s: Could not allocate DMA tag - error %d\n",
|
||||||
adv_name(adv), error);
|
adv_name(adv), error);
|
||||||
adv_free(adv);
|
adv_free(adv);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
adv->init_level++;
|
adv->init_level++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("adveisaattach: Unknown device type!\n");
|
printf("adveisaattach: Unknown device type!\n");
|
||||||
return (-1);
|
goto bad;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +254,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
/*flags*/0,
|
/*flags*/0,
|
||||||
&overrun_dmat) != 0) {
|
&overrun_dmat) != 0) {
|
||||||
adv_free(adv);
|
adv_free(adv);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
if (bus_dmamem_alloc(overrun_dmat,
|
if (bus_dmamem_alloc(overrun_dmat,
|
||||||
(void **)&overrun_buf,
|
(void **)&overrun_buf,
|
||||||
@ -264,7 +262,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
&overrun_dmamap) != 0) {
|
&overrun_dmamap) != 0) {
|
||||||
bus_dma_tag_destroy(overrun_dmat);
|
bus_dma_tag_destroy(overrun_dmat);
|
||||||
adv_free(adv);
|
adv_free(adv);
|
||||||
return (-1);
|
goto bad;
|
||||||
}
|
}
|
||||||
/* And permanently map it in */
|
/* And permanently map it in */
|
||||||
bus_dmamap_load(overrun_dmat, overrun_dmamap,
|
bus_dmamap_load(overrun_dmat, overrun_dmamap,
|
||||||
@ -273,23 +271,6 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
/*flags*/0);
|
/*flags*/0);
|
||||||
}
|
}
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, iospace)) {
|
|
||||||
adv_free(adv);
|
|
||||||
if (adv_b != NULL)
|
|
||||||
adv_free(adv_b);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, adv_intr, (void *)adv, &cam_imask,
|
|
||||||
/*shared ==*/TRUE)) {
|
|
||||||
adv_free(adv);
|
|
||||||
if (adv_b != NULL)
|
|
||||||
adv_free(adv_b);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we know we own the resources we need, do the
|
* Now that we know we own the resources we need, do the
|
||||||
* card initialization.
|
* card initialization.
|
||||||
@ -301,7 +282,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
|
ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
|
||||||
ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
|
ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
|
||||||
|
|
||||||
adv->chip_version = EISA_REVISION_ID(e_dev->id)
|
adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
|
||||||
+ ADV_CHIP_MIN_VER_EISA - 1;
|
+ ADV_CHIP_MIN_VER_EISA - 1;
|
||||||
|
|
||||||
if (adv_init(adv) != 0) {
|
if (adv_init(adv) != 0) {
|
||||||
@ -321,7 +302,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
|
ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
|
||||||
ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
|
ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
|
||||||
|
|
||||||
adv_b->chip_version = EISA_REVISION_ID(e_dev->id)
|
adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
|
||||||
+ ADV_CHIP_MIN_VER_EISA - 1;
|
+ ADV_CHIP_MIN_VER_EISA - 1;
|
||||||
|
|
||||||
if (adv_init(adv_b) != 0) {
|
if (adv_init(adv_b) != 0) {
|
||||||
@ -335,13 +316,7 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
/*
|
/*
|
||||||
* Enable our interrupt handler.
|
* Enable our interrupt handler.
|
||||||
*/
|
*/
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
bus_setup_intr(dev, irq, adv_intr, adv, &ih);
|
||||||
adv_free(adv);
|
|
||||||
if (adv_b != NULL)
|
|
||||||
adv_free(adv_b);
|
|
||||||
eisa_release_intr(e_dev, irq, adv_intr);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attach sub-devices - always succeeds */
|
/* Attach sub-devices - always succeeds */
|
||||||
adv_attach(adv);
|
adv_attach(adv);
|
||||||
@ -349,6 +324,30 @@ adveisaattach(struct eisa_device *e_dev)
|
|||||||
adv_attach(adv_b);
|
adv_attach(adv_b);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t adv_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, adveisaprobe),
|
||||||
|
DEVMETHOD(device_attach, adveisaattach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t adv_eisa_driver = {
|
||||||
|
"adv",
|
||||||
|
adv_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t adv_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: ahb.c,v 1.7 1999/03/05 23:37:07 gibbs Exp $
|
* $Id: ahb.c,v 1.8 1999/04/11 03:06:05 eivind Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -36,10 +36,14 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <cam/cam.h>
|
#include <cam/cam.h>
|
||||||
#include <cam/cam_ccb.h>
|
#include <cam/cam_ccb.h>
|
||||||
@ -71,9 +75,7 @@
|
|||||||
bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value)
|
bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value)
|
||||||
|
|
||||||
static const char *ahbmatch(eisa_id_t type);
|
static const char *ahbmatch(eisa_id_t type);
|
||||||
static int ahbprobe(void);
|
static struct ahb_softc *ahballoc(u_long unit, u_int iobase);
|
||||||
static int ahbattach(struct eisa_device *dev);
|
|
||||||
static struct ahb_softc *ahballoc(u_long unit, u_int iobase, u_int irq);
|
|
||||||
static void ahbfree(struct ahb_softc *ahb);
|
static void ahbfree(struct ahb_softc *ahb);
|
||||||
static int ahbreset(struct ahb_softc *ahb);
|
static int ahbreset(struct ahb_softc *ahb);
|
||||||
static void ahbmapecbs(void *arg, bus_dma_segment_t *segs,
|
static void ahbmapecbs(void *arg, bus_dma_segment_t *segs,
|
||||||
@ -184,19 +186,6 @@ ahbqueuembox(struct ahb_softc *ahb, u_int32_t mboxval, u_int attn_code)
|
|||||||
ahb_outb(ahb, ATTN, attn_code);
|
ahb_outb(ahb, ATTN, attn_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u_long ahbunit;
|
|
||||||
|
|
||||||
static struct eisa_driver ahb_eisa_driver =
|
|
||||||
{
|
|
||||||
"ahb",
|
|
||||||
ahbprobe,
|
|
||||||
ahbattach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&ahbunit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, ahb_eisa_driver);
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
ahbmatch(eisa_id_t type)
|
ahbmatch(eisa_id_t type)
|
||||||
{
|
{
|
||||||
@ -211,98 +200,93 @@ ahbmatch(eisa_id_t type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ahbprobe(void)
|
ahbprobe(device_t dev)
|
||||||
{
|
{
|
||||||
struct eisa_device *e_dev = NULL;
|
const char *desc;
|
||||||
u_int32_t iobase;
|
u_int32_t iobase;
|
||||||
u_int32_t irq;
|
u_int32_t irq;
|
||||||
int count;
|
u_int8_t intdef;
|
||||||
|
|
||||||
count = 0;
|
desc = ahbmatch(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, ahbmatch))) {
|
if (!desc)
|
||||||
u_int8_t intdef;
|
return (ENXIO);
|
||||||
|
device_set_desc(dev, desc);
|
||||||
|
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE) +
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) +
|
||||||
AHB_EISA_SLOT_OFFSET;
|
AHB_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
intdef = inb(INTDEF + iobase);
|
intdef = inb(INTDEF + iobase);
|
||||||
switch (intdef & 0x7) {
|
switch (intdef & 0x7) {
|
||||||
case INT9:
|
case INT9:
|
||||||
irq = 9;
|
irq = 9;
|
||||||
break;
|
break;
|
||||||
case INT10:
|
case INT10:
|
||||||
irq = 10;
|
irq = 10;
|
||||||
break;
|
break;
|
||||||
case INT11:
|
case INT11:
|
||||||
irq = 11;
|
irq = 11;
|
||||||
break;
|
break;
|
||||||
case INT12:
|
case INT12:
|
||||||
irq = 12;
|
irq = 12;
|
||||||
break;
|
break;
|
||||||
case INT14:
|
case INT14:
|
||||||
irq = 14;
|
irq = 14;
|
||||||
break;
|
break;
|
||||||
case INT15:
|
case INT15:
|
||||||
irq = 15;
|
irq = 15;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Adaptec 174X at slot %d: illegal "
|
printf("Adaptec 174X at slot %d: illegal "
|
||||||
"irq setting %d\n", e_dev->ioconf.slot,
|
"irq setting %d\n", eisa_get_slot(dev),
|
||||||
(intdef & 0x7));
|
(intdef & 0x7));
|
||||||
irq = 0;
|
irq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (irq == 0)
|
|
||||||
continue;
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &ahb_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
if (irq == 0)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ahbattach(struct eisa_device *e_dev)
|
ahbattach(device_t dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* find unit and check we have that many defined
|
* find unit and check we have that many defined
|
||||||
*/
|
*/
|
||||||
struct ahb_softc *ahb;
|
struct ahb_softc *ahb;
|
||||||
struct ecb* next_ecb;
|
struct ecb* next_ecb;
|
||||||
resvaddr_t *iospace;
|
struct resource *io = 0;
|
||||||
u_int irq;
|
struct resource *irq = 0;
|
||||||
|
int shared, rid;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
rid = 0;
|
||||||
return (-1);
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
iospace = e_dev->ioconf.ioaddrs.lh_first;
|
return ENOMEM;
|
||||||
|
|
||||||
if (iospace == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, iospace)) {
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ahb = ahballoc(e_dev->unit, iospace->addr, irq)) == NULL) {
|
if ((ahb = ahballoc(device_get_unit(dev), rman_get_start(io))) == NULL) {
|
||||||
eisa_reg_end(e_dev);
|
goto error_exit2;
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ahbreset(ahb) != 0)
|
if (ahbreset(ahb) != 0)
|
||||||
return (-1);
|
goto error_exit;
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, ahbintr, (void *)ahb, &cam_imask,
|
shared = (ahb_inb(ahb, INTDEF) & INTLEVEL) ? RF_SHAREABLE : 0;
|
||||||
(ahb_inb(ahb, INTDEF) & INTLEVEL) ? TRUE : FALSE)) {
|
rid = 0;
|
||||||
eisa_reg_end(e_dev);
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
ahbfree(ahb);
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
return (-1);
|
if (!irq) {
|
||||||
|
device_printf(dev, "Can't allocate interrupt\n");
|
||||||
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -377,8 +361,6 @@ ahbattach(struct eisa_device *e_dev)
|
|||||||
|
|
||||||
ahb->init_level++;
|
ahb->init_level++;
|
||||||
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we know we own the resources we need, register
|
* Now that we know we own the resources we need, register
|
||||||
* our bus with the XPT.
|
* our bus with the XPT.
|
||||||
@ -387,21 +369,26 @@ ahbattach(struct eisa_device *e_dev)
|
|||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
/* Enable our interrupt */
|
/* Enable our interrupt */
|
||||||
eisa_enable_intr(e_dev, irq);
|
bus_setup_intr(dev, irq, ahbintr, ahb, &ih);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error_exit:
|
error_exit:
|
||||||
/*
|
/*
|
||||||
* The board's IRQ line will not be left enabled
|
* The board's IRQ line will not be left enabled
|
||||||
* if we can't intialize correctly, so its safe
|
* if we can't intialize correctly, so its safe
|
||||||
* to release the irq.
|
* to release the irq.
|
||||||
*/
|
*/
|
||||||
eisa_release_intr(e_dev, irq, ahbintr);
|
|
||||||
ahbfree(ahb);
|
ahbfree(ahb);
|
||||||
|
error_exit2:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ahb_softc *
|
static struct ahb_softc *
|
||||||
ahballoc(u_long unit, u_int iobase, u_int irq)
|
ahballoc(u_long unit, u_int iobase)
|
||||||
{
|
{
|
||||||
struct ahb_softc *ahb;
|
struct ahb_softc *ahb;
|
||||||
|
|
||||||
@ -1348,4 +1335,23 @@ ahbtimeout(void *arg)
|
|||||||
splx(s);
|
splx(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t ahb_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, ahbprobe),
|
||||||
|
DEVMETHOD(device_attach, ahbattach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ahb_eisa_driver = {
|
||||||
|
"ahb",
|
||||||
|
ahb_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ahb_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(ahb, eisa, ahb_eisa_driver, ahb_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA */
|
#endif /* NEISA */
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: ahc_eisa.c,v 1.4 1998/12/15 08:24:45 gibbs Exp $
|
* $Id: ahc_eisa.c,v 1.5 1999/03/05 23:28:42 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -35,9 +35,13 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
@ -61,26 +65,12 @@
|
|||||||
#define AHC_EISA_IOSIZE 0x100
|
#define AHC_EISA_IOSIZE 0x100
|
||||||
#define INTDEF 0x5cul /* Interrupt Definition Register */
|
#define INTDEF 0x5cul /* Interrupt Definition Register */
|
||||||
|
|
||||||
static int aic7770probe(void);
|
|
||||||
static int aic7770_attach(struct eisa_device *e_dev);
|
|
||||||
static void aha2840_load_seeprom(struct ahc_softc *ahc);
|
static void aha2840_load_seeprom(struct ahc_softc *ahc);
|
||||||
|
|
||||||
static struct eisa_driver ahc_eisa_driver =
|
|
||||||
{
|
|
||||||
"ahc",
|
|
||||||
aic7770probe,
|
|
||||||
aic7770_attach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&ahc_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, ahc_eisa_driver);
|
|
||||||
|
|
||||||
static const char *aic7770_match(eisa_id_t type);
|
static const char *aic7770_match(eisa_id_t type);
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
aic7770_match(type)
|
aic7770_match(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
||||||
@ -100,75 +90,75 @@ aic7770_match(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
aic7770probe(void)
|
aic7770_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_int32_t iobase;
|
u_int32_t iobase;
|
||||||
u_int32_t irq;
|
u_int32_t irq;
|
||||||
u_int8_t intdef;
|
u_int8_t intdef;
|
||||||
u_int8_t hcntrl;
|
u_int8_t hcntrl;
|
||||||
struct eisa_device *e_dev;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
e_dev = NULL;
|
desc = aic7770_match(eisa_get_id(dev));
|
||||||
count = 0;
|
if (!desc)
|
||||||
while ((e_dev = eisa_match_dev(e_dev, aic7770_match))) {
|
return (ENXIO);
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
|
device_set_desc(dev, desc);
|
||||||
+ AHC_EISA_SLOT_OFFSET;
|
|
||||||
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE)
|
||||||
|
+ AHC_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
/* Pause the card preseving the IRQ type */
|
/* Pause the card preseving the IRQ type */
|
||||||
hcntrl = inb(iobase + HCNTRL) & IRQMS;
|
hcntrl = inb(iobase + HCNTRL) & IRQMS;
|
||||||
|
|
||||||
outb(iobase + HCNTRL, hcntrl | PAUSE);
|
outb(iobase + HCNTRL, hcntrl | PAUSE);
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
intdef = inb(INTDEF + iobase);
|
intdef = inb(INTDEF + iobase);
|
||||||
irq = intdef & 0xf;
|
irq = intdef & 0xf;
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case 9:
|
case 9:
|
||||||
case 10:
|
case 10:
|
||||||
case 11:
|
case 11:
|
||||||
case 12:
|
case 12:
|
||||||
case 14:
|
case 14:
|
||||||
case 15:
|
case 15:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("aic7770 at slot %d: illegal "
|
printf("aic7770 at slot %d: illegal "
|
||||||
"irq setting %d\n", e_dev->ioconf.slot,
|
"irq setting %d\n", eisa_get_slot(dev),
|
||||||
intdef);
|
intdef);
|
||||||
irq = 0;
|
irq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (irq == 0)
|
|
||||||
continue;
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &ahc_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
if (irq == 0)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
aic7770_attach(struct eisa_device *e_dev)
|
aic7770_attach(device_t dev)
|
||||||
{
|
{
|
||||||
ahc_chip chip;
|
ahc_chip chip;
|
||||||
|
|
||||||
struct ahc_softc *ahc;
|
struct ahc_softc *ahc;
|
||||||
resvaddr_t *iospace;
|
struct resource *io = 0;
|
||||||
int unit = e_dev->unit;
|
struct resource *irq = 0;
|
||||||
int irq;
|
int unit = device_get_unit(dev);
|
||||||
int error;
|
int error, rid;
|
||||||
|
int shared;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
rid = 0;
|
||||||
return (-1);
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
switch (eisa_get_id(dev)) {
|
||||||
|
|
||||||
iospace = e_dev->ioconf.ioaddrs.lh_first;
|
|
||||||
|
|
||||||
if (!iospace)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
switch (e_dev->id) {
|
|
||||||
case EISA_DEVICE_ID_ADAPTEC_274x:
|
case EISA_DEVICE_ID_ADAPTEC_274x:
|
||||||
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
|
||||||
chip = AHC_AIC7770|AHC_EISA;
|
chip = AHC_AIC7770|AHC_EISA;
|
||||||
@ -179,13 +169,12 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("aic7770_attach: Unknown device type!\n");
|
printf("aic7770_attach: Unknown device type!\n");
|
||||||
return -1;
|
goto bad;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ahc = ahc_alloc(unit, iospace->addr, NULL,
|
if (!(ahc = ahc_alloc(unit, rman_get_start(io), NULL,
|
||||||
chip, AHC_AIC7770_FE, AHC_FNONE, NULL)))
|
chip, AHC_AIC7770_FE, AHC_FNONE, NULL)))
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
ahc->channel = 'A';
|
ahc->channel = 'A';
|
||||||
ahc->channel_b = 'B';
|
ahc->channel_b = 'B';
|
||||||
@ -204,31 +193,27 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
printf("%s: Could not allocate DMA tag - error %d\n",
|
printf("%s: Could not allocate DMA tag - error %d\n",
|
||||||
ahc_name(ahc), error);
|
ahc_name(ahc), error);
|
||||||
ahc_free(ahc);
|
ahc_free(ahc);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, iospace)) {
|
|
||||||
ahc_free(ahc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ahc_reset(ahc) != 0) {
|
if (ahc_reset(ahc) != 0) {
|
||||||
ahc_free(ahc);
|
ahc_free(ahc);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The IRQMS bit enables level sensitive interrupts. Only allow
|
* The IRQMS bit enables level sensitive interrupts. Only allow
|
||||||
* IRQ sharing if it's set.
|
* IRQ sharing if it's set.
|
||||||
*/
|
*/
|
||||||
if (eisa_reg_intr(e_dev, irq, ahc_intr, (void *)ahc, &cam_imask,
|
shared = (ahc->pause & IRQMS) ? RF_SHAREABLE : 0;
|
||||||
/*shared ==*/ahc->pause & IRQMS)) {
|
rid = 0;
|
||||||
ahc_free(ahc);
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
return -1;
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "Can't allocate interrupt\n");
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the user what type of interrupts we're using.
|
* Tell the user what type of interrupts we're using.
|
||||||
@ -355,8 +340,7 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
* The board's IRQ line is not yet enabled so it's safe
|
* The board's IRQ line is not yet enabled so it's safe
|
||||||
* to release the irq.
|
* to release the irq.
|
||||||
*/
|
*/
|
||||||
eisa_release_intr(e_dev, irq, ahc_intr);
|
goto bad;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -367,16 +351,20 @@ aic7770_attach(struct eisa_device *e_dev)
|
|||||||
/*
|
/*
|
||||||
* Enable our interrupt handler.
|
* Enable our interrupt handler.
|
||||||
*/
|
*/
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
if (bus_setup_intr(dev, irq, ahc_intr, ahc, &ih))
|
||||||
ahc_free(ahc);
|
goto bad;
|
||||||
eisa_release_intr(e_dev, irq, ahc_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attach sub-devices - always succeeds */
|
/* Attach sub-devices - always succeeds */
|
||||||
ahc_attach(ahc);
|
ahc_attach(ahc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -474,4 +462,23 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t ahc_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, aic7770_probe),
|
||||||
|
DEVMETHOD(device_attach, aic7770_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ahc_eisa_driver = {
|
||||||
|
"ahc",
|
||||||
|
ahc_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ahc_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(ahc, eisa, ahc_eisa_driver, ahc_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_eisa.c,v 1.2 1999/03/08 21:35:03 gibbs Exp $
|
* $Id: bt_eisa.c,v 1.3 1999/03/23 07:27:38 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -35,9 +35,13 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
@ -99,21 +103,59 @@
|
|||||||
#define AMI_MISC2_OPTIONS 0x49E
|
#define AMI_MISC2_OPTIONS 0x49E
|
||||||
#define AMI_ENABLE_ISA_DMA 0x08
|
#define AMI_ENABLE_ISA_DMA 0x08
|
||||||
|
|
||||||
static int bt_eisa_probe(void);
|
|
||||||
static int bt_eisa_attach(struct eisa_device *e_dev);
|
|
||||||
|
|
||||||
static struct eisa_driver bt_eisa_driver = {
|
|
||||||
"bt",
|
|
||||||
bt_eisa_probe,
|
|
||||||
bt_eisa_attach,
|
|
||||||
/*shutdown*/NULL,
|
|
||||||
&bt_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, bt_eisa_driver);
|
|
||||||
|
|
||||||
static const char *bt_match(eisa_id_t type);
|
static const char *bt_match(eisa_id_t type);
|
||||||
|
|
||||||
|
static int
|
||||||
|
bt_eisa_alloc_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
int rid;
|
||||||
|
struct resource *port;
|
||||||
|
struct resource *irq;
|
||||||
|
int shared;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX assumes that the iospace ranges are sorted in increasing
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
rid = 1;
|
||||||
|
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!port)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
bt_init_softc(dev, port, 0, 0);
|
||||||
|
|
||||||
|
if (eisa_get_irq(dev) != -1) {
|
||||||
|
shared = bt->level_trigger_ints ? RF_SHAREABLE : 0;
|
||||||
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
irq = 0;
|
||||||
|
bt->irq = irq;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_eisa_release_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
bt_match(eisa_id_t type)
|
bt_match(eisa_id_t type)
|
||||||
{
|
{
|
||||||
@ -137,155 +179,119 @@ bt_match(eisa_id_t type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bt_eisa_probe(void)
|
bt_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
struct eisa_device *e_dev = NULL;
|
struct bt_probe_info info;
|
||||||
int count;
|
u_long port;
|
||||||
|
u_long iosize;
|
||||||
|
u_int ioconf;
|
||||||
|
int result;
|
||||||
|
|
||||||
count = 0;
|
desc = bt_match(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, bt_match))) {
|
if (!desc)
|
||||||
struct bt_softc *bt;
|
return (ENXIO);
|
||||||
struct bt_probe_info info;
|
device_set_desc(dev, desc);
|
||||||
u_long port;
|
|
||||||
u_long iosize;
|
|
||||||
u_int ioconf;
|
|
||||||
|
|
||||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
|
iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE);
|
||||||
if (e_dev->id == EISA_DEVICE_ID_AMI_4801) {
|
if (eisa_get_id(dev) == EISA_DEVICE_ID_AMI_4801) {
|
||||||
u_int ioconf1;
|
u_int ioconf1;
|
||||||
|
|
||||||
iobase += AMI_EISA_SLOT_OFFSET;
|
iobase += AMI_EISA_SLOT_OFFSET;
|
||||||
iosize = AMI_EISA_IOSIZE;
|
iosize = AMI_EISA_IOSIZE;
|
||||||
ioconf1 = inb(iobase + AMI_EISA_IOCONF1);
|
ioconf1 = inb(iobase + AMI_EISA_IOCONF1);
|
||||||
/* Determine "ISA" I/O port */
|
/* Determine "ISA" I/O port */
|
||||||
switch (ioconf1 & AMI_PORTADDR) {
|
switch (ioconf1 & AMI_PORTADDR) {
|
||||||
case AMI_PORT_330:
|
case AMI_PORT_330:
|
||||||
port = 0x330;
|
port = 0x330;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_334:
|
case AMI_PORT_334:
|
||||||
port = 0x334;
|
port = 0x334;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_230:
|
case AMI_PORT_230:
|
||||||
port = 0x230;
|
port = 0x230;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_234:
|
case AMI_PORT_234:
|
||||||
port = 0x234;
|
port = 0x234;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_134:
|
case AMI_PORT_134:
|
||||||
port = 0x134;
|
port = 0x134;
|
||||||
break;
|
break;
|
||||||
case AMI_PORT_130:
|
case AMI_PORT_130:
|
||||||
port = 0x130;
|
port = 0x130;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Disabled */
|
/* Disabled */
|
||||||
printf("bt: AMI EISA Adapter at "
|
printf("bt: AMI EISA Adapter at "
|
||||||
"slot %d has a disabled I/O "
|
"slot %d has a disabled I/O "
|
||||||
"port. Cannot attach.\n",
|
"port. Cannot attach.\n",
|
||||||
e_dev->ioconf.slot);
|
eisa_get_slot(dev));
|
||||||
continue;
|
return (ENXIO);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iobase += BT_EISA_SLOT_OFFSET;
|
|
||||||
iosize = BT_EISA_IOSIZE;
|
|
||||||
|
|
||||||
ioconf = inb(iobase + EISA_IOCONF);
|
|
||||||
/* Determine "ISA" I/O port */
|
|
||||||
switch (ioconf & PORTADDR) {
|
|
||||||
case PORT_330:
|
|
||||||
port = 0x330;
|
|
||||||
break;
|
|
||||||
case PORT_334:
|
|
||||||
port = 0x334;
|
|
||||||
break;
|
|
||||||
case PORT_230:
|
|
||||||
port = 0x230;
|
|
||||||
break;
|
|
||||||
case PORT_234:
|
|
||||||
port = 0x234;
|
|
||||||
break;
|
|
||||||
case PORT_130:
|
|
||||||
port = 0x130;
|
|
||||||
break;
|
|
||||||
case PORT_134:
|
|
||||||
port = 0x134;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Disabled */
|
|
||||||
printf("bt: Buslogic EISA Adapter at "
|
|
||||||
"slot %d has a disabled I/O "
|
|
||||||
"port. Cannot attach.\n",
|
|
||||||
e_dev->ioconf.slot);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bt_mark_probed_iop(port);
|
} else {
|
||||||
|
iobase += BT_EISA_SLOT_OFFSET;
|
||||||
|
iosize = BT_EISA_IOSIZE;
|
||||||
|
|
||||||
/* Allocate a softc for use during probing */
|
ioconf = inb(iobase + EISA_IOCONF);
|
||||||
bt = bt_alloc(BT_TEMP_UNIT, I386_BUS_SPACE_IO, port);
|
/* Determine "ISA" I/O port */
|
||||||
|
switch (ioconf & PORTADDR) {
|
||||||
if (bt == NULL) {
|
case PORT_330:
|
||||||
printf("bt_eisa_probe: Could not allocate softc for "
|
port = 0x330;
|
||||||
"card at slot 0x%x\n", e_dev->ioconf.slot);
|
break;
|
||||||
continue;
|
case PORT_334:
|
||||||
|
port = 0x334;
|
||||||
|
break;
|
||||||
|
case PORT_230:
|
||||||
|
port = 0x230;
|
||||||
|
break;
|
||||||
|
case PORT_234:
|
||||||
|
port = 0x234;
|
||||||
|
break;
|
||||||
|
case PORT_130:
|
||||||
|
port = 0x130;
|
||||||
|
break;
|
||||||
|
case PORT_134:
|
||||||
|
port = 0x134;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Disabled */
|
||||||
|
printf("bt: Buslogic EISA Adapter at "
|
||||||
|
"slot %d has a disabled I/O "
|
||||||
|
"port. Cannot attach.\n",
|
||||||
|
eisa_get_slot(dev));
|
||||||
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_port_probe(bt, &info) != 0) {
|
|
||||||
printf("bt_eisa_probe: Probe failed for "
|
|
||||||
"card at slot 0x%x\n", e_dev->ioconf.slot);
|
|
||||||
} else {
|
|
||||||
eisa_add_iospace(e_dev, iobase, iosize, RESVADDR_NONE);
|
|
||||||
eisa_add_iospace(e_dev, port, BT_IOSIZE, RESVADDR_NONE);
|
|
||||||
eisa_add_intr(e_dev, info.irq);
|
|
||||||
|
|
||||||
eisa_registerdev(e_dev, &bt_eisa_driver);
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
bt_free(bt);
|
|
||||||
}
|
}
|
||||||
return count;
|
bt_mark_probed_iop(port);
|
||||||
|
|
||||||
|
/* Tell parent where our resources are going to be */
|
||||||
|
eisa_add_iospace(dev, iobase, iosize, RESVADDR_NONE);
|
||||||
|
eisa_add_iospace(dev, port, BT_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
|
/* And allocate them */
|
||||||
|
bt_eisa_alloc_resources(dev);
|
||||||
|
|
||||||
|
if (bt_port_probe(dev, &info) != 0) {
|
||||||
|
printf("bt_eisa_probe: Probe failed for "
|
||||||
|
"card at slot 0x%x\n", eisa_get_slot(dev));
|
||||||
|
result = ENXIO;
|
||||||
|
} else {
|
||||||
|
eisa_add_intr(dev, info.irq);
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
bt_eisa_release_resources(dev);
|
||||||
|
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bt_eisa_attach(struct eisa_device *e_dev)
|
bt_eisa_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
int unit = e_dev->unit;
|
|
||||||
int irq;
|
|
||||||
resvaddr_t *ioport;
|
|
||||||
resvaddr_t *eisa_ioport;
|
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
/* Allocate resources */
|
||||||
return (-1);
|
bt_eisa_alloc_resources(dev);
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The addresses are sorted in increasing order
|
|
||||||
* so we know the port to pass to the core bt
|
|
||||||
* driver comes first.
|
|
||||||
*/
|
|
||||||
ioport = e_dev->ioconf.ioaddrs.lh_first;
|
|
||||||
|
|
||||||
if (ioport == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
eisa_ioport = ioport->links.le_next;
|
|
||||||
|
|
||||||
if (eisa_ioport == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (eisa_reg_iospace(e_dev, eisa_ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((bt = bt_alloc(unit, I386_BUS_SPACE_IO, ioport->addr)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Allocate a dmatag for our SCB DMA maps */
|
/* Allocate a dmatag for our SCB DMA maps */
|
||||||
/* XXX Should be a child of the PCI bus dma tag */
|
/* XXX Should be a child of the PCI bus dma tag */
|
||||||
@ -297,42 +303,42 @@ bt_eisa_attach(struct eisa_device *e_dev)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_eisa_release_resources(dev);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, bt_intr, (void *)bt, &cam_imask,
|
|
||||||
/*shared ==*/bt->level_trigger_ints ? 1 : 0)) {
|
|
||||||
bt_free(bt);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we know we own the resources we need, do the full
|
* Now that we know we own the resources we need, do the full
|
||||||
* card initialization.
|
* card initialization.
|
||||||
*/
|
*/
|
||||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_eisa_release_resources(dev);
|
||||||
/*
|
|
||||||
* The board's IRQ line will not be left enabled
|
|
||||||
* if we can't intialize correctly, so its safe
|
|
||||||
* to release the irq.
|
|
||||||
*/
|
|
||||||
eisa_release_intr(e_dev, irq, bt_intr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach sub-devices - always succeeds */
|
/* Attach sub-devices - always succeeds (sets up intr) */
|
||||||
bt_attach(bt);
|
bt_attach(dev);
|
||||||
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
|
||||||
bt_free(bt);
|
|
||||||
eisa_release_intr(e_dev, irq, bt_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_eisa_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, eisa, bt_eisa_driver, bt_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Id: dpt_eisa.c,v 1.3 1998/08/09 02:22:34 jkh Exp $
|
* $Id: dpt_eisa.c,v 1.4 1998/09/15 08:33:35 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eisa.h"
|
#include "eisa.h"
|
||||||
@ -46,9 +46,13 @@
|
|||||||
#include <sys/buf.h>
|
#include <sys/buf.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <cam/scsi/scsi_all.h>
|
#include <cam/scsi/scsi_all.h>
|
||||||
|
|
||||||
@ -65,100 +69,80 @@
|
|||||||
|
|
||||||
/* Function Prototypes */
|
/* Function Prototypes */
|
||||||
|
|
||||||
static int dpt_eisa_probe(void);
|
|
||||||
static int dpt_eisa_attach(struct eisa_device*);
|
|
||||||
|
|
||||||
static const char *dpt_eisa_match(eisa_id_t);
|
static const char *dpt_eisa_match(eisa_id_t);
|
||||||
|
|
||||||
static struct eisa_driver dpt_eisa_driver =
|
|
||||||
{
|
|
||||||
"dpt",
|
|
||||||
dpt_eisa_probe,
|
|
||||||
dpt_eisa_attach,
|
|
||||||
NULL,
|
|
||||||
&dpt_unit
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (eisadriver_set, dpt_eisa_driver);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dpt_eisa_probe(void)
|
dpt_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
struct eisa_device *e_dev = NULL;
|
const char *desc;
|
||||||
int count;
|
|
||||||
u_int32_t io_base;
|
u_int32_t io_base;
|
||||||
u_int intdef;
|
u_int intdef;
|
||||||
u_int irq;
|
u_int irq;
|
||||||
|
|
||||||
e_dev = NULL;
|
desc = dpt_eisa_match(eisa_get_id(dev));
|
||||||
count = 0;
|
if (!desc)
|
||||||
while ((e_dev = eisa_match_dev(e_dev, dpt_eisa_match))) {
|
return (ENXIO);
|
||||||
io_base = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
|
device_set_desc(dev, desc);
|
||||||
+ DPT_EISA_SLOT_OFFSET;
|
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, io_base,
|
io_base = (eisa_get_slot(dev) * EISA_SLOT_SIZE)
|
||||||
DPT_EISA_IOSIZE, RESVADDR_NONE);
|
+ DPT_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
|
eisa_add_iospace(dev, io_base, DPT_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
intdef = inb(DPT_EISA_INTDEF + io_base);
|
intdef = inb(DPT_EISA_INTDEF + io_base);
|
||||||
|
|
||||||
irq = intdef & DPT_EISA_INT_NUM_MASK;
|
irq = intdef & DPT_EISA_INT_NUM_MASK;
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case DPT_EISA_INT_NUM_11:
|
case DPT_EISA_INT_NUM_11:
|
||||||
irq = 11;
|
irq = 11;
|
||||||
break;
|
break;
|
||||||
case DPT_EISA_INT_NUM_15:
|
case DPT_EISA_INT_NUM_15:
|
||||||
irq = 15;
|
irq = 15;
|
||||||
break;
|
break;
|
||||||
case DPT_EISA_INT_NUM_14:
|
case DPT_EISA_INT_NUM_14:
|
||||||
irq = 14;
|
irq = 14;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("dpt at slot %d: illegal irq setting %d\n",
|
printf("dpt at slot %d: illegal irq setting %d\n",
|
||||||
e_dev->ioconf.slot, irq);
|
eisa_get_slot(dev), irq);
|
||||||
irq = 0;
|
irq = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (irq == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
eisa_add_intr(e_dev, irq);
|
|
||||||
eisa_registerdev(e_dev, &dpt_eisa_driver);
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
if (irq == 0)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
eisa_add_intr(dev, irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
dpt_eisa_attach(e_dev)
|
dpt_eisa_attach(device_t dev)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
{
|
{
|
||||||
dpt_softc_t *dpt;
|
dpt_softc_t *dpt;
|
||||||
resvaddr_t *io_space;
|
struct resource *io = 0;
|
||||||
int unit = e_dev->unit;
|
struct resource *irq = 0;
|
||||||
int irq;
|
int unit = device_get_unit(dev);
|
||||||
int shared;
|
int shared;
|
||||||
int s;
|
int s;
|
||||||
|
int rid;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL) {
|
rid = 0;
|
||||||
printf("dpt%d: Can't retrieve irq from EISA config struct.\n",
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
unit);
|
0, ~0, 1, RF_ACTIVE);
|
||||||
return -1;
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
shared = (inb(DPT_EISA_INTDEF + rman_get_start(io))
|
||||||
io_space = e_dev->ioconf.ioaddrs.lh_first;
|
& DPT_EISA_INT_LEVEL) ? RF_SHAREABLE : 0;
|
||||||
|
|
||||||
if (!io_space) {
|
dpt = dpt_alloc(unit, rman_get_bustag(io),
|
||||||
printf("dpt%d: No I/O space?!\n", unit);
|
rman_get_bushandle(io) + DPT_EISA_EATA_REG_OFFSET);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared = inb(DPT_EISA_INTDEF + io_space->addr) & DPT_EISA_INT_LEVEL;
|
|
||||||
|
|
||||||
dpt = dpt_alloc(unit, I386_BUS_SPACE_IO,
|
|
||||||
io_space->addr + DPT_EISA_EATA_REG_OFFSET);
|
|
||||||
if (dpt == NULL)
|
if (dpt == NULL)
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
/* Allocate a dmatag representing the capabilities of this attachment */
|
/* Allocate a dmatag representing the capabilities of this attachment */
|
||||||
/* XXX Should be a child of the EISA bus dma tag */
|
/* XXX Should be a child of the EISA bus dma tag */
|
||||||
@ -171,46 +155,37 @@ dpt_eisa_attach(e_dev)
|
|||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &dpt->parent_dmat) != 0) {
|
/*flags*/0, &dpt->parent_dmat) != 0) {
|
||||||
dpt_free(dpt);
|
dpt_free(dpt);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, dpt_intr, (void *)dpt, &cam_imask,
|
rid = 0;
|
||||||
shared)) {
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
printf("dpt%d: eisa_reg_intr() failed.\n", unit);
|
0, ~0, 1, shared | RF_ACTIVE);
|
||||||
dpt_free(dpt);
|
if (!irq) {
|
||||||
return -1;
|
device_printf(dev, "No irq?!\n");
|
||||||
}
|
goto bad;
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/* Enable our interrupt handler. */
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
|
||||||
#ifdef DPT_DEBUG_ERROR
|
|
||||||
printf("dpt%d: eisa_enable_intr() failed.\n", unit);
|
|
||||||
#endif
|
|
||||||
free(dpt, M_DEVBUF);
|
|
||||||
eisa_release_intr(e_dev, irq, dpt_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Enable our interrupt handler.
|
|
||||||
*/
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
|
||||||
dpt_free(dpt);
|
|
||||||
eisa_release_intr(e_dev, irq, dpt_intr);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s = splcam();
|
s = splcam();
|
||||||
if (dpt_init(dpt) != 0) {
|
if (dpt_init(dpt) != 0) {
|
||||||
dpt_free(dpt);
|
dpt_free(dpt);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register with the XPT */
|
/* Register with the XPT */
|
||||||
dpt_attach(dpt);
|
dpt_attach(dpt);
|
||||||
|
bus_setup_intr(dev, irq, dpt_intr, dpt, &ih);
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
@ -264,4 +239,23 @@ dpt_eisa_match(type)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t dpt_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, dpt_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, dpt_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t dpt_eisa_driver = {
|
||||||
|
"dpt",
|
||||||
|
dpt_eisa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t dpt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(dpt, eisa, dpt_eisa_driver, dpt_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -28,55 +28,64 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: eisaconf.c,v 1.36 1998/12/04 22:54:46 archie Exp $
|
* $Id: eisaconf.c,v 1.37 1999/01/14 06:22:03 jdp Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "opt_eisa.h"
|
#include "opt_eisa.h"
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/linker_set.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/limits.h>
|
#include <machine/limits.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/eisa/eisaconf.h>
|
#include <i386/eisa/eisaconf.h>
|
||||||
|
|
||||||
#include <sys/interrupt.h>
|
#include <sys/interrupt.h>
|
||||||
|
|
||||||
struct eisa_device_node{
|
typedef struct resvaddr {
|
||||||
struct eisa_device dev;
|
u_long addr; /* start address */
|
||||||
struct eisa_device_node *next;
|
u_long size; /* size of reserved area */
|
||||||
|
int flags;
|
||||||
|
struct resource *res; /* resource manager handle */
|
||||||
|
LIST_ENTRY(resvaddr) links; /* List links */
|
||||||
|
} resvaddr_t;
|
||||||
|
|
||||||
|
LIST_HEAD(resvlist, resvaddr);
|
||||||
|
|
||||||
|
struct irq_node {
|
||||||
|
int irq_no;
|
||||||
|
void *idesc;
|
||||||
|
TAILQ_ENTRY(irq_node) links;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
TAILQ_HEAD(irqlist, irq_node);
|
||||||
* This should probably be a list of "struct device" once it exists.
|
|
||||||
* A struct device will incorperate ioconf and driver entry point data
|
|
||||||
* regardless of how its attached to the system (via unions) as well
|
|
||||||
* as more generic information that all device types should support (unit
|
|
||||||
* number, if its installed, etc).
|
|
||||||
*/
|
|
||||||
static struct eisa_device_node *eisa_dev_list;
|
|
||||||
static struct eisa_device_node **eisa_dev_list_tail = &eisa_dev_list;
|
|
||||||
static u_long eisa_unit;
|
|
||||||
|
|
||||||
static struct eisa_driver mainboard_drv = {
|
struct eisa_ioconf {
|
||||||
"eisa",
|
int slot;
|
||||||
NULL,
|
struct resvlist ioaddrs; /* list of reserved I/O ranges */
|
||||||
NULL,
|
struct resvlist maddrs; /* list of reserved memory ranges */
|
||||||
NULL,
|
struct irqlist irqs; /* list of reserved irqs */
|
||||||
&eisa_unit
|
};
|
||||||
};
|
|
||||||
|
/* To be replaced by the "super device" generic device structure... */
|
||||||
|
struct eisa_device {
|
||||||
|
eisa_id_t id;
|
||||||
|
struct eisa_ioconf ioconf;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the mainboard_drv to the eisa driver linkerset so that it is
|
|
||||||
* defined even if no EISA drivers are linked into the kernel.
|
|
||||||
*/
|
|
||||||
DATA_SET (eisadriver_set, mainboard_drv);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local function declarations and static variables
|
* Local function declarations and static variables
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
static void eisa_reg_print __P((struct eisa_device *e_dev,
|
static void eisa_reg_print __P((struct eisa_device *e_dev,
|
||||||
char *string, char *separator));
|
char *string, char *separator));
|
||||||
static int eisa_add_resvaddr __P((struct eisa_device *e_dev,
|
static int eisa_add_resvaddr __P((struct eisa_device *e_dev,
|
||||||
@ -85,7 +94,9 @@ static int eisa_add_resvaddr __P((struct eisa_device *e_dev,
|
|||||||
static int eisa_reg_resvaddr __P((struct eisa_device *e_dev,
|
static int eisa_reg_resvaddr __P((struct eisa_device *e_dev,
|
||||||
struct resvlist *head, resvaddr_t *resvaddr,
|
struct resvlist *head, resvaddr_t *resvaddr,
|
||||||
int *reg_count));
|
int *reg_count));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
* Keep some state about what we've printed so far
|
* Keep some state about what we've printed so far
|
||||||
* to make probe output pretty.
|
* to make probe output pretty.
|
||||||
@ -98,29 +109,77 @@ static struct {
|
|||||||
int column; /* How much we have output so far. */
|
int column; /* How much we have output so far. */
|
||||||
#define MAX_COL 80
|
#define MAX_COL 80
|
||||||
} reg_state;
|
} reg_state;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Global variable, so UserConfig can change it. */
|
/* Global variable, so UserConfig can change it. */
|
||||||
#ifndef EISA_SLOTS
|
#ifndef EISA_SLOTS
|
||||||
#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
|
#define EISA_SLOTS 10 /* PCI clashes with higher ones.. fix later */
|
||||||
#endif
|
#endif
|
||||||
int num_eisa_slots = EISA_SLOTS;
|
int num_eisa_slots = EISA_SLOTS;
|
||||||
|
|
||||||
|
static devclass_t eisa_devclass;
|
||||||
|
|
||||||
|
static int
|
||||||
|
mainboard_probe(device_t dev)
|
||||||
|
{
|
||||||
|
char *idstring;
|
||||||
|
eisa_id_t id = eisa_get_id(dev);
|
||||||
|
|
||||||
|
if (eisa_get_slot(dev) != 0)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,
|
||||||
|
M_DEVBUF, M_NOWAIT);
|
||||||
|
if (idstring == NULL) {
|
||||||
|
panic("Eisa probe unable to malloc");
|
||||||
|
}
|
||||||
|
sprintf(idstring, "%c%c%c%x%x (System Board)",
|
||||||
|
EISA_MFCTR_CHAR0(id),
|
||||||
|
EISA_MFCTR_CHAR1(id),
|
||||||
|
EISA_MFCTR_CHAR2(id),
|
||||||
|
EISA_PRODUCT_ID(id),
|
||||||
|
EISA_REVISION_ID(id));
|
||||||
|
device_set_desc(dev, idstring);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mainboard_attach(device_t dev)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t mainboard_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, mainboard_probe),
|
||||||
|
DEVMETHOD(device_attach, mainboard_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t mainboard_driver = {
|
||||||
|
"mainboard",
|
||||||
|
mainboard_methods,
|
||||||
|
DRIVER_TYPE_MISC,
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t mainboard_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** probe for EISA devices
|
** probe for EISA devices
|
||||||
*/
|
*/
|
||||||
void
|
static int
|
||||||
eisa_configure()
|
eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
int i,slot;
|
int i,slot;
|
||||||
struct eisa_device_node *dev_node;
|
|
||||||
struct eisa_driver **e_drvp;
|
|
||||||
struct eisa_driver *e_drv;
|
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
int eisaBase = 0xc80;
|
int eisaBase = 0xc80;
|
||||||
eisa_id_t eisa_id;
|
eisa_id_t eisa_id;
|
||||||
|
|
||||||
e_drvp = (struct eisa_driver**)eisadriver_set.ls_items;
|
|
||||||
|
|
||||||
for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) {
|
for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) {
|
||||||
int id_size = sizeof(eisa_id);
|
int id_size = sizeof(eisa_id);
|
||||||
eisa_id = 0;
|
eisa_id = 0;
|
||||||
@ -132,19 +191,16 @@ eisa_configure()
|
|||||||
continue; /* no EISA card in slot */
|
continue; /* no EISA card in slot */
|
||||||
|
|
||||||
/* Prepare an eisa_device_node for this slot */
|
/* Prepare an eisa_device_node for this slot */
|
||||||
dev_node = (struct eisa_device_node *)malloc(sizeof(*dev_node),
|
e_dev = (struct eisa_device *)malloc(sizeof(*e_dev),
|
||||||
M_DEVBUF, M_NOWAIT);
|
M_DEVBUF, M_NOWAIT);
|
||||||
if (!dev_node) {
|
if (!e_dev) {
|
||||||
printf("eisa0: cannot malloc eisa_device_node");
|
printf("eisa0: cannot malloc eisa_device");
|
||||||
break; /* Try to attach what we have already */
|
break; /* Try to attach what we have already */
|
||||||
}
|
}
|
||||||
bzero(dev_node, sizeof(*dev_node));
|
bzero(e_dev, sizeof(*e_dev));
|
||||||
e_dev = &(dev_node->dev);
|
|
||||||
|
|
||||||
e_dev->id = eisa_id;
|
e_dev->id = eisa_id;
|
||||||
|
|
||||||
e_dev->full_name = "Unattached Device";
|
|
||||||
|
|
||||||
e_dev->ioconf.slot = slot;
|
e_dev->ioconf.slot = slot;
|
||||||
|
|
||||||
/* Initialize our lists of reserved addresses */
|
/* Initialize our lists of reserved addresses */
|
||||||
@ -152,134 +208,202 @@ eisa_configure()
|
|||||||
LIST_INIT(&(e_dev->ioconf.maddrs));
|
LIST_INIT(&(e_dev->ioconf.maddrs));
|
||||||
TAILQ_INIT(&(e_dev->ioconf.irqs));
|
TAILQ_INIT(&(e_dev->ioconf.irqs));
|
||||||
|
|
||||||
*eisa_dev_list_tail = dev_node;
|
device_add_child(dev, NULL, -1, e_dev);
|
||||||
eisa_dev_list_tail = &dev_node->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_node = eisa_dev_list;
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* "Attach" the system board
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The first will be the motherboard in a true EISA system */
|
|
||||||
if (dev_node && (dev_node->dev.ioconf.slot == 0)) {
|
|
||||||
char *idstring;
|
|
||||||
|
|
||||||
e_dev = &dev_node->dev;
|
|
||||||
e_dev->driver = &mainboard_drv;
|
|
||||||
e_dev->unit = (*e_dev->driver->unit)++;
|
|
||||||
idstring = (char *)malloc(8 + sizeof(" (System Board)") + 1,
|
|
||||||
M_DEVBUF, M_NOWAIT);
|
|
||||||
if (idstring == NULL) {
|
|
||||||
panic("Eisa probe unable to malloc");
|
|
||||||
}
|
|
||||||
sprintf(idstring, "%c%c%c%x%x (System Board)",
|
|
||||||
EISA_MFCTR_CHAR0(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR1(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR2(e_dev->id),
|
|
||||||
EISA_PRODUCT_ID(e_dev->id),
|
|
||||||
EISA_REVISION_ID(e_dev->id));
|
|
||||||
e_dev->full_name = idstring;
|
|
||||||
|
|
||||||
printf("%s%ld: <%s>\n",
|
|
||||||
e_dev->driver->name,
|
|
||||||
e_dev->unit,
|
|
||||||
e_dev->full_name);
|
|
||||||
|
|
||||||
/* Should set the iosize, but I don't have a spec handy */
|
|
||||||
printf("Probing for devices on the EISA bus\n");
|
|
||||||
dev_node = dev_node->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!eisa_dev_list) {
|
|
||||||
/*
|
|
||||||
* No devices.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* See what devices we recognize.
|
|
||||||
*/
|
|
||||||
while((e_drv = *e_drvp++)) {
|
|
||||||
if (e_drv->probe)
|
|
||||||
(*e_drv->probe)();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Attach the devices we found in slot order
|
|
||||||
*/
|
|
||||||
for (; dev_node; dev_node=dev_node->next) {
|
|
||||||
e_dev = &dev_node->dev;
|
|
||||||
e_drv = e_dev->driver;
|
|
||||||
|
|
||||||
if (e_drv) {
|
|
||||||
/*
|
|
||||||
* Determine the proper unit number for this device.
|
|
||||||
* Here we should look in the device table generated
|
|
||||||
* by config to see if this type of device is enabled
|
|
||||||
* either generically or for this particular address
|
|
||||||
* as well as determine if a reserved unit number
|
|
||||||
* should be used. We should also ensure that the
|
|
||||||
* "next availible unit number" skips over "wired" unit
|
|
||||||
* numbers. This will be done after config is fixed or
|
|
||||||
* some other configuration method is chosen.
|
|
||||||
*/
|
|
||||||
e_dev->unit = (*e_drv->unit)++;
|
|
||||||
if ((*e_drv->attach)(e_dev) < 0) {
|
|
||||||
/* Ensure registration has ended */
|
|
||||||
reg_state.in_registration = 0;
|
|
||||||
printf("\n%s0:%d <%s> attach failed\n",
|
|
||||||
mainboard_drv.name,
|
|
||||||
e_dev->ioconf.slot,
|
|
||||||
e_dev->full_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Ensure registration has ended */
|
|
||||||
reg_state.in_registration = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Announce unattached device */
|
|
||||||
printf("%s0:%d <%c%c%c%x%x=0x%x> unknown device\n",
|
|
||||||
mainboard_drv.name,
|
|
||||||
e_dev->ioconf.slot,
|
|
||||||
EISA_MFCTR_CHAR0(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR1(e_dev->id),
|
|
||||||
EISA_MFCTR_CHAR2(e_dev->id),
|
|
||||||
EISA_PRODUCT_ID(e_dev->id),
|
|
||||||
EISA_REVISION_ID(e_dev->id),
|
|
||||||
e_dev->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct eisa_device *
|
static void
|
||||||
eisa_match_dev(e_dev, match_func)
|
eisa_print_child(device_t dev, device_t child)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
const char* (*match_func)(eisa_id_t);
|
|
||||||
{
|
{
|
||||||
struct eisa_device_node *e_node = eisa_dev_list;
|
/* XXX print resource descriptions? */
|
||||||
|
printf(" at slot %d", eisa_get_slot(child));
|
||||||
if (e_dev) {
|
printf(" on %s", device_get_nameunit(dev));
|
||||||
/* Start our search from the last successful match */
|
|
||||||
e_node = ((struct eisa_device_node *)e_dev)->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(; e_node; e_node = e_node->next) {
|
|
||||||
const char *result;
|
|
||||||
if (e_node->dev.driver) {
|
|
||||||
/* Already claimed */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result = (*match_func)(e_node->dev.id);
|
|
||||||
if (result) {
|
|
||||||
e_node->dev.full_name = result;
|
|
||||||
return (&(e_node->dev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_find_irq(struct eisa_device *e_dev, int rid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct irq_node *irq;
|
||||||
|
|
||||||
|
for (i = 0, irq = TAILQ_FIRST(&e_dev->ioconf.irqs);
|
||||||
|
i < rid && irq;
|
||||||
|
i++, irq = TAILQ_NEXT(irq, links))
|
||||||
|
;
|
||||||
|
|
||||||
|
if (irq)
|
||||||
|
return irq->irq_no;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resvaddr *
|
||||||
|
eisa_find_maddr(struct eisa_device *e_dev, int rid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.maddrs);
|
||||||
|
i < rid && resv;
|
||||||
|
i++, resv = LIST_NEXT(resv, links))
|
||||||
|
;
|
||||||
|
|
||||||
|
return resv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resvaddr *
|
||||||
|
eisa_find_ioaddr(struct eisa_device *e_dev, int rid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
for (i = 0, resv = LIST_FIRST(&e_dev->ioconf.ioaddrs);
|
||||||
|
i < rid && resv;
|
||||||
|
i++, resv = LIST_NEXT(resv, links))
|
||||||
|
;
|
||||||
|
|
||||||
|
return resv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_read_ivar(device_t dev, device_t child, int which, u_long *result)
|
||||||
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(child);
|
||||||
|
|
||||||
|
switch (which) {
|
||||||
|
case EISA_IVAR_SLOT:
|
||||||
|
*result = e_dev->ioconf.slot;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EISA_IVAR_ID:
|
||||||
|
*result = e_dev->id;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EISA_IVAR_IRQ:
|
||||||
|
/* XXX only first irq */
|
||||||
|
*result = eisa_find_irq(e_dev, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
|
||||||
|
{
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resource *
|
||||||
|
eisa_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||||
|
u_long start, u_long end, u_long count, u_int flags)
|
||||||
|
{
|
||||||
|
int isdefault;
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(child);
|
||||||
|
struct resource *rv, **rvp = 0;
|
||||||
|
|
||||||
|
isdefault = (device_get_parent(child) == dev
|
||||||
|
&& start == 0UL && end == ~0UL && count == 1);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SYS_RES_IRQ:
|
||||||
|
if (isdefault) {
|
||||||
|
int irq = eisa_find_irq(e_dev, *rid);
|
||||||
|
if (irq == -1)
|
||||||
|
return 0;
|
||||||
|
start = end = irq;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_RES_MEMORY:
|
||||||
|
if (isdefault) {
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
resv = eisa_find_maddr(e_dev, *rid);
|
||||||
|
if (!resv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
start = resv->addr;
|
||||||
|
end = resv->size - 1;
|
||||||
|
count = resv->size;
|
||||||
|
rvp = &resv->res;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_RES_IOPORT:
|
||||||
|
if (isdefault) {
|
||||||
|
struct resvaddr *resv;
|
||||||
|
|
||||||
|
resv = eisa_find_ioaddr(e_dev, *rid);
|
||||||
|
if (!resv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
start = resv->addr;
|
||||||
|
end = resv->size - 1;
|
||||||
|
count = resv->size;
|
||||||
|
rvp = &resv->res;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
|
||||||
|
type, rid, start, end, count, flags);
|
||||||
|
if (rvp)
|
||||||
|
*rvp = rv;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
eisa_release_resource(device_t dev, device_t child, int type, int rid,
|
||||||
|
struct resource *r)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(child);
|
||||||
|
struct resvaddr *resv = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SYS_RES_IRQ:
|
||||||
|
if (eisa_find_irq(e_dev, rid) == -1)
|
||||||
|
return EINVAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_RES_MEMORY:
|
||||||
|
if (device_get_parent(child) == dev)
|
||||||
|
resv = eisa_find_maddr(e_dev, rid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case SYS_RES_IOPORT:
|
||||||
|
if (device_get_parent(child) == dev)
|
||||||
|
resv = eisa_find_ioaddr(e_dev, rid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r);
|
||||||
|
|
||||||
|
if (rv == 0) {
|
||||||
|
if (resv)
|
||||||
|
resv->res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
/* Interrupt and I/O space registration facitlities */
|
/* Interrupt and I/O space registration facitlities */
|
||||||
void
|
void
|
||||||
eisa_reg_start(e_dev)
|
eisa_reg_start(e_dev)
|
||||||
@ -362,11 +486,14 @@ eisa_reg_end(e_dev)
|
|||||||
"registration session\n");
|
"registration session\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_add_intr(e_dev, irq)
|
eisa_add_intr(dev, irq)
|
||||||
struct eisa_device *e_dev;
|
device_t dev;
|
||||||
int irq;
|
int irq;
|
||||||
{
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(dev);
|
||||||
struct irq_node *irq_info;
|
struct irq_node *irq_info;
|
||||||
|
|
||||||
irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF,
|
irq_info = (struct irq_node *)malloc(sizeof(*irq_info), M_DEVBUF,
|
||||||
@ -380,6 +507,8 @@ eisa_add_intr(e_dev, irq)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
|
eisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
@ -494,6 +623,8 @@ eisa_enable_intr(e_dev, irq)
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eisa_add_resvaddr(e_dev, head, base, size, flags)
|
eisa_add_resvaddr(e_dev, head, base, size, flags)
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
@ -548,27 +679,31 @@ eisa_add_resvaddr(e_dev, head, base, size, flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_add_mspace(e_dev, mbase, msize, flags)
|
eisa_add_mspace(dev, mbase, msize, flags)
|
||||||
struct eisa_device *e_dev;
|
device_t dev;
|
||||||
u_long mbase;
|
u_long mbase;
|
||||||
u_long msize;
|
u_long msize;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(dev);
|
||||||
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
|
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
|
||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
eisa_add_iospace(e_dev, iobase, iosize, flags)
|
eisa_add_iospace(dev, iobase, iosize, flags)
|
||||||
struct eisa_device *e_dev;
|
device_t dev;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
u_long iosize;
|
u_long iosize;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
|
struct eisa_device *e_dev = device_get_ivars(dev);
|
||||||
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
|
return eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
|
||||||
iosize, flags);
|
iosize, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eisa_reg_resvaddr(e_dev, head, resvaddr, reg_count)
|
eisa_reg_resvaddr(e_dev, head, resvaddr, reg_count)
|
||||||
struct eisa_device *e_dev;
|
struct eisa_device *e_dev;
|
||||||
@ -650,12 +785,35 @@ eisa_reg_iospace(e_dev, resvaddr)
|
|||||||
&(reg_state.num_ioaddrs)));
|
&(reg_state.num_ioaddrs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
#endif
|
||||||
eisa_registerdev(e_dev, driver)
|
|
||||||
struct eisa_device *e_dev;
|
static device_method_t eisa_methods[] = {
|
||||||
struct eisa_driver *driver;
|
/* Device interface */
|
||||||
{
|
DEVMETHOD(device_probe, eisa_probe),
|
||||||
e_dev->driver = driver; /* Driver now owns this device */
|
DEVMETHOD(device_attach, bus_generic_attach),
|
||||||
return (0);
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||||
}
|
|
||||||
|
/* Bus interface */
|
||||||
|
DEVMETHOD(bus_print_child, eisa_print_child),
|
||||||
|
DEVMETHOD(bus_read_ivar, eisa_read_ivar),
|
||||||
|
DEVMETHOD(bus_write_ivar, eisa_write_ivar),
|
||||||
|
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
||||||
|
DEVMETHOD(bus_alloc_resource, eisa_alloc_resource),
|
||||||
|
DEVMETHOD(bus_release_resource, eisa_release_resource),
|
||||||
|
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||||
|
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||||
|
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||||
|
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t eisa_driver = {
|
||||||
|
"eisa",
|
||||||
|
eisa_methods,
|
||||||
|
DRIVER_TYPE_MISC,
|
||||||
|
1, /* no softc */
|
||||||
|
};
|
||||||
|
|
||||||
|
DRIVER_MODULE(eisa, isab, eisa_driver, eisa_devclass, 0, 0);
|
||||||
|
|
||||||
|
@ -28,14 +28,12 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: eisaconf.h,v 1.16 1997/03/13 18:04:05 joerg Exp $
|
* $Id: eisaconf.h,v 1.17 1997/09/21 21:35:23 gibbs Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _I386_EISA_EISACONF_H_
|
#ifndef _I386_EISA_EISACONF_H_
|
||||||
#define _I386_EISA_EISACONF_H_ 1
|
#define _I386_EISA_EISACONF_H_ 1
|
||||||
|
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
#define EISA_SLOT_SIZE 0x1000
|
#define EISA_SLOT_SIZE 0x1000
|
||||||
|
|
||||||
#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
|
#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
|
||||||
@ -45,79 +43,46 @@
|
|||||||
#define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */
|
#define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */
|
||||||
#define EISA_REVISION_ID(ID) (u_char)(ID & 0x0F) /* Bits 0-3 */
|
#define EISA_REVISION_ID(ID) (u_char)(ID & 0x0F) /* Bits 0-3 */
|
||||||
|
|
||||||
extern struct linker_set eisadriver_set;
|
|
||||||
extern int num_eisa_slots;
|
extern int num_eisa_slots;
|
||||||
|
|
||||||
typedef u_int32_t eisa_id_t;
|
typedef u_int32_t eisa_id_t;
|
||||||
|
|
||||||
typedef struct resvaddr {
|
enum eisa_device_ivars {
|
||||||
u_long addr; /* start address */
|
EISA_IVAR_SLOT,
|
||||||
u_long size; /* size of reserved area */
|
EISA_IVAR_ID,
|
||||||
int flags;
|
EISA_IVAR_IRQ
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simplified accessors for isa devices
|
||||||
|
*/
|
||||||
|
#define EISA_ACCESSOR(A, B, T) \
|
||||||
|
\
|
||||||
|
static __inline T eisa_get_ ## A(device_t dev) \
|
||||||
|
{ \
|
||||||
|
uintptr_t v; \
|
||||||
|
BUS_READ_IVAR(device_get_parent(dev), dev, EISA_IVAR_ ## B, &v); \
|
||||||
|
return (T) v; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static __inline void eisa_set_ ## A(device_t dev, T t) \
|
||||||
|
{ \
|
||||||
|
u_long v = (u_long) t; \
|
||||||
|
BUS_WRITE_IVAR(device_get_parent(dev), dev, EISA_IVAR_ ## B, v); \
|
||||||
|
}
|
||||||
|
|
||||||
|
EISA_ACCESSOR(slot, SLOT, int)
|
||||||
|
EISA_ACCESSOR(id, ID, eisa_id_t)
|
||||||
|
EISA_ACCESSOR(irq, IRQ, eisa_id_t)
|
||||||
|
|
||||||
|
int eisa_add_intr __P((device_t, int));
|
||||||
|
|
||||||
#define RESVADDR_NONE 0x00
|
#define RESVADDR_NONE 0x00
|
||||||
#define RESVADDR_BITMASK 0x01 /* size is a mask of reserved
|
#define RESVADDR_BITMASK 0x01 /* size is a mask of reserved
|
||||||
* bits at addr
|
* bits at addr
|
||||||
*/
|
*/
|
||||||
#define RESVADDR_RELOCATABLE 0x02
|
#define RESVADDR_RELOCATABLE 0x02
|
||||||
LIST_ENTRY(resvaddr) links; /* List links */
|
int eisa_add_iospace __P((device_t, u_long, u_long, int));
|
||||||
} resvaddr_t;
|
int eisa_add_mspace __P((device_t, u_long, u_long, int));
|
||||||
|
|
||||||
LIST_HEAD(resvlist, resvaddr);
|
|
||||||
|
|
||||||
struct irq_node {
|
|
||||||
int irq_no;
|
|
||||||
void *idesc;
|
|
||||||
TAILQ_ENTRY(irq_node) links;
|
|
||||||
};
|
|
||||||
|
|
||||||
TAILQ_HEAD(irqlist, irq_node);
|
|
||||||
|
|
||||||
struct eisa_ioconf {
|
|
||||||
int slot;
|
|
||||||
struct resvlist ioaddrs; /* list of reserved I/O ranges */
|
|
||||||
struct resvlist maddrs; /* list of reserved memory ranges */
|
|
||||||
struct irqlist irqs; /* list of reserved irqs */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct eisa_device;
|
|
||||||
|
|
||||||
struct eisa_driver {
|
|
||||||
char* name; /* device name */
|
|
||||||
int (*probe) __P((void));
|
|
||||||
/* test whether device is present */
|
|
||||||
int (*attach) __P((struct eisa_device *));
|
|
||||||
/* setup driver for a device */
|
|
||||||
int (*shutdown) __P((int));
|
|
||||||
/* Return the device to a safe
|
|
||||||
* state before shutdown
|
|
||||||
*/
|
|
||||||
u_long *unit; /* Next available unit */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* To be replaced by the "super device" generic device structure... */
|
|
||||||
struct eisa_device {
|
|
||||||
eisa_id_t id;
|
|
||||||
u_long unit;
|
|
||||||
const char* full_name; /* for use in the probe message */
|
|
||||||
struct eisa_ioconf ioconf;
|
|
||||||
struct eisa_driver* driver;
|
|
||||||
};
|
|
||||||
|
|
||||||
void eisa_configure __P((void));
|
|
||||||
struct eisa_device *eisa_match_dev __P((struct eisa_device *,
|
|
||||||
const char * (*)(eisa_id_t)));
|
|
||||||
|
|
||||||
void eisa_reg_start __P((struct eisa_device *));
|
|
||||||
void eisa_reg_end __P((struct eisa_device *));
|
|
||||||
int eisa_add_intr __P((struct eisa_device *, int));
|
|
||||||
int eisa_reg_intr __P((struct eisa_device *, int, void (*)(void *),
|
|
||||||
void *, u_int *, int));
|
|
||||||
int eisa_release_intr __P((struct eisa_device *, int, void (*)(void *)));
|
|
||||||
int eisa_enable_intr __P((struct eisa_device *, int));
|
|
||||||
int eisa_add_iospace __P((struct eisa_device *, u_long, u_long, int));
|
|
||||||
int eisa_reg_iospace __P((struct eisa_device *, resvaddr_t *));
|
|
||||||
int eisa_add_mspace __P((struct eisa_device *, u_long, u_long, int));
|
|
||||||
int eisa_reg_mspace __P((struct eisa_device *, resvaddr_t *));
|
|
||||||
int eisa_registerdev __P((struct eisa_device *, struct eisa_driver *));
|
|
||||||
|
|
||||||
#endif /* _I386_EISA_EISACONF_H_ */
|
#endif /* _I386_EISA_EISACONF_H_ */
|
||||||
|
@ -38,6 +38,12 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
@ -58,22 +64,9 @@
|
|||||||
|
|
||||||
|
|
||||||
static const char *vx_match __P((eisa_id_t type));
|
static const char *vx_match __P((eisa_id_t type));
|
||||||
static int vx_eisa_probe __P((void));
|
|
||||||
static int vx_eisa_attach __P((struct eisa_device *));
|
|
||||||
|
|
||||||
static struct eisa_driver vx_eisa_driver = {
|
|
||||||
"vx",
|
|
||||||
vx_eisa_probe,
|
|
||||||
vx_eisa_attach,
|
|
||||||
/* shutdown */ NULL,
|
|
||||||
&vx_count
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET(eisadriver_set, vx_eisa_driver);
|
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
vx_match(type)
|
vx_match(eisa_id_t type)
|
||||||
eisa_id_t type;
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EISA_DEVICE_ID_3COM_3C592:
|
case EISA_DEVICE_ID_3COM_3C592:
|
||||||
@ -95,88 +88,117 @@ vx_match(type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vx_eisa_probe(void)
|
vx_eisa_probe(device_t dev)
|
||||||
{
|
{
|
||||||
|
const char *desc;
|
||||||
u_long iobase;
|
u_long iobase;
|
||||||
struct eisa_device *e_dev = NULL;
|
u_long port;
|
||||||
int count;
|
|
||||||
|
|
||||||
count = 0;
|
desc = vx_match(eisa_get_id(dev));
|
||||||
while ((e_dev = eisa_match_dev(e_dev, vx_match))) {
|
if (!desc)
|
||||||
u_long port;
|
return (ENXIO);
|
||||||
|
device_set_desc(dev, desc);
|
||||||
|
|
||||||
port = e_dev->ioconf.slot * EISA_SLOT_SIZE;
|
port = eisa_get_slot(dev) * EISA_SLOT_SIZE;
|
||||||
iobase = port + VX_EISA_SLOT_OFFSET;
|
iobase = port + VX_EISA_SLOT_OFFSET;
|
||||||
|
|
||||||
eisa_add_iospace(e_dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
|
||||||
eisa_add_iospace(e_dev, port, VX_IOSIZE, RESVADDR_NONE);
|
eisa_add_iospace(dev, port, VX_IOSIZE, RESVADDR_NONE);
|
||||||
|
|
||||||
/* Set irq */
|
/* Set irq */
|
||||||
eisa_add_intr(e_dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12);
|
eisa_add_intr(dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12);
|
||||||
eisa_registerdev(e_dev, &vx_eisa_driver);
|
|
||||||
count++;
|
return (0);
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vx_eisa_attach(e_dev)
|
vx_eisa_attach(device_t dev)
|
||||||
struct eisa_device *e_dev;
|
|
||||||
{
|
{
|
||||||
struct vx_softc *sc;
|
struct vx_softc *sc;
|
||||||
int unit = e_dev->unit;
|
int unit = device_get_unit(dev);
|
||||||
int irq;
|
struct resource *io = 0;
|
||||||
resvaddr_t *ioport;
|
struct resource *eisa_io = 0;
|
||||||
resvaddr_t *eisa_ioport;
|
struct resource *irq = 0;
|
||||||
u_char level_intr;
|
u_char level_intr;
|
||||||
|
int rid;
|
||||||
|
void *ih;
|
||||||
|
|
||||||
if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
|
/*
|
||||||
return (-1);
|
* The addresses are sorted in increasing order
|
||||||
|
* so we know the port to pass to the core ep
|
||||||
|
* driver comes first.
|
||||||
|
*/
|
||||||
|
rid = 0;
|
||||||
|
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!io) {
|
||||||
|
device_printf(dev, "No I/O space?!\n");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
|
rid = 1;
|
||||||
|
eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
ioport = e_dev->ioconf.ioaddrs.lh_first;
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!eisa_io) {
|
||||||
if (!ioport)
|
device_printf(dev, "No I/O space?!\n");
|
||||||
return -1;
|
goto bad;
|
||||||
|
}
|
||||||
eisa_ioport = ioport->links.le_next;
|
|
||||||
|
|
||||||
if (!eisa_ioport)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
eisa_reg_start(e_dev);
|
|
||||||
if (eisa_reg_iospace(e_dev, ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (eisa_reg_iospace(e_dev, eisa_ioport))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((sc = vxalloc(unit)) == NULL)
|
if ((sc = vxalloc(unit)) == NULL)
|
||||||
return -1;
|
goto bad;
|
||||||
|
|
||||||
sc->vx_io_addr = ioport->addr;
|
sc->vx_io_addr = rman_get_start(io);
|
||||||
|
|
||||||
level_intr = FALSE;
|
level_intr = FALSE;
|
||||||
|
|
||||||
if (eisa_reg_intr(e_dev, irq, vxintr, (void *) sc, &net_imask,
|
rid = 0;
|
||||||
/* shared == */ level_intr)) {
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
device_printf(dev, "No irq?!\n");
|
||||||
vxfree(sc);
|
vxfree(sc);
|
||||||
return -1;
|
goto bad;
|
||||||
}
|
}
|
||||||
eisa_reg_end(e_dev);
|
|
||||||
|
|
||||||
/* Now the registers are availible through the lower ioport */
|
/* Now the registers are availible through the lower ioport */
|
||||||
|
|
||||||
vxattach(sc);
|
vxattach(sc);
|
||||||
|
|
||||||
if (eisa_enable_intr(e_dev, irq)) {
|
if (bus_setup_intr(dev, irq, vxintr, sc, &ih)) {
|
||||||
vxfree(sc);
|
vxfree(sc);
|
||||||
eisa_release_intr(e_dev, irq, vxintr);
|
goto bad;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
if (io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
|
||||||
|
if (eisa_io)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t vx_eisa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, vx_eisa_probe),
|
||||||
|
DEVMETHOD(device_attach, vx_eisa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t vx_eisa_driver = {
|
||||||
|
"vx",
|
||||||
|
vx_eisa_methods,
|
||||||
|
DRIVER_TYPE_NET,
|
||||||
|
1, /* unused */
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t vx_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(vx, eisa, vx_eisa_driver, vx_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NVX > 0 */
|
#endif /* NVX > 0 */
|
||||||
#endif /* NEISA > 0 */
|
#endif /* NEISA > 0 */
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
|
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
|
||||||
* $Id: autoconf.c,v 1.112 1999/04/15 14:52:24 bde Exp $
|
* $Id: autoconf.c,v 1.113 1999/04/16 21:22:11 peter Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -232,10 +232,6 @@ configure(dummy)
|
|||||||
INTREN(IRQ_SLAVE);
|
INTREN(IRQ_SLAVE);
|
||||||
#endif /* APIC_IO */
|
#endif /* APIC_IO */
|
||||||
|
|
||||||
#if NEISA > 0
|
|
||||||
eisa_configure();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if NPNP > 0
|
#if NPNP > 0
|
||||||
pnp_configure();
|
pnp_configure();
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,33 +26,90 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_isa.c,v 1.6 1999/03/08 21:32:59 gibbs Exp $
|
* $Id: bt_isa.c,v 1.7 1999/04/06 21:15:18 phk Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/isa/isa_device.h>
|
#include <isa/isavar.h>
|
||||||
|
#include <i386/isa/isa_dma.h>
|
||||||
#include <dev/buslogic/btreg.h>
|
#include <dev/buslogic/btreg.h>
|
||||||
|
|
||||||
#include <cam/scsi/scsi_all.h>
|
#include <cam/scsi/scsi_all.h>
|
||||||
|
|
||||||
static int bt_isa_probe __P((struct isa_device *dev));
|
|
||||||
static int bt_isa_attach __P((struct isa_device *dev));
|
|
||||||
static void bt_isa_intr __P((void *unit));
|
|
||||||
|
|
||||||
static bus_dma_filter_t btvlbouncefilter;
|
static bus_dma_filter_t btvlbouncefilter;
|
||||||
static bus_dmamap_callback_t btmapsensebuffers;
|
static bus_dmamap_callback_t btmapsensebuffers;
|
||||||
|
|
||||||
struct isa_driver btdriver =
|
static int
|
||||||
|
bt_isa_alloc_resources(device_t dev)
|
||||||
{
|
{
|
||||||
bt_isa_probe,
|
int rid;
|
||||||
bt_isa_attach,
|
struct resource *port;
|
||||||
"bt"
|
struct resource *irq;
|
||||||
};
|
struct resource *drq;
|
||||||
|
|
||||||
|
rid = 0;
|
||||||
|
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!port)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
if (isa_get_irq(dev) != -1) {
|
||||||
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
irq = 0;
|
||||||
|
|
||||||
|
if (isa_get_drq(dev) != -1) {
|
||||||
|
rid = 0;
|
||||||
|
drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!drq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ,
|
||||||
|
0, irq);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
drq = 0;
|
||||||
|
|
||||||
|
bt_init_softc(dev, port, irq, drq);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_isa_release_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
if (bt->drq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->drq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the device can be found at the port given
|
* Check if the device can be found at the port given
|
||||||
@ -61,35 +118,24 @@ struct isa_driver btdriver =
|
|||||||
* autoconf.c
|
* autoconf.c
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bt_isa_probe(dev)
|
bt_isa_probe(device_t dev)
|
||||||
struct isa_device *dev;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* find unit and check we have that many defined
|
* find unit and check we have that many defined
|
||||||
*/
|
*/
|
||||||
struct bt_softc *bt;
|
|
||||||
int port_index;
|
int port_index;
|
||||||
int max_port_index;
|
int max_port_index;
|
||||||
|
|
||||||
/*
|
|
||||||
* We ignore the unit number assigned by config to allow
|
|
||||||
* consistant numbering between PCI/EISA/ISA devices.
|
|
||||||
* This is a total kludge until we have a configuration
|
|
||||||
* manager.
|
|
||||||
*/
|
|
||||||
dev->id_unit = bt_unit;
|
|
||||||
|
|
||||||
bt = NULL;
|
|
||||||
port_index = 0;
|
port_index = 0;
|
||||||
max_port_index = BT_NUM_ISAPORTS - 1;
|
max_port_index = BT_NUM_ISAPORTS - 1;
|
||||||
/*
|
/*
|
||||||
* Bound our board search if the user has
|
* Bound our board search if the user has
|
||||||
* specified an exact port.
|
* specified an exact port.
|
||||||
*/
|
*/
|
||||||
bt_find_probe_range(dev->id_iobase, &port_index, &max_port_index);
|
bt_find_probe_range(isa_get_port(dev), &port_index, &max_port_index);
|
||||||
|
|
||||||
if (port_index < 0)
|
if (port_index < 0)
|
||||||
return 0;
|
return (ENXIO);
|
||||||
|
|
||||||
/* Attempt to find an adapter */
|
/* Attempt to find an adapter */
|
||||||
for (;port_index <= max_port_index; port_index++) {
|
for (;port_index <= max_port_index; port_index++) {
|
||||||
@ -97,6 +143,8 @@ bt_isa_probe(dev)
|
|||||||
u_int ioport;
|
u_int ioport;
|
||||||
|
|
||||||
ioport = bt_iop_from_bio(port_index);
|
ioport = bt_iop_from_bio(port_index);
|
||||||
|
isa_set_port(dev, ioport);
|
||||||
|
isa_set_portsize(dev, BT_NREGS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure this port has not already been claimed already
|
* Ensure this port has not already been claimed already
|
||||||
@ -104,52 +152,50 @@ bt_isa_probe(dev)
|
|||||||
*/
|
*/
|
||||||
if (bt_check_probed_iop(ioport) != 0)
|
if (bt_check_probed_iop(ioport) != 0)
|
||||||
continue;
|
continue;
|
||||||
dev->id_iobase = ioport;
|
|
||||||
if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET))
|
/* Initialise the softc for use during probing */
|
||||||
|
if (bt_isa_alloc_resources(dev) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Allocate a softc for use during probing */
|
|
||||||
bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
|
|
||||||
|
|
||||||
if (bt == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* We're going to attempt to probe it now, so mark it probed */
|
/* We're going to attempt to probe it now, so mark it probed */
|
||||||
bt_mark_probed_bio(port_index);
|
bt_mark_probed_bio(port_index);
|
||||||
|
|
||||||
if (bt_port_probe(bt, &info) != 0) {
|
if (bt_port_probe(dev, &info) != 0) {
|
||||||
printf("bt_isa_probe: Probe failed for card at 0x%x\n",
|
printf("bt_isa_probe: Probe failed for card at 0x%x\n",
|
||||||
ioport);
|
ioport);
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->id_drq = info.drq;
|
bt_isa_release_resources(dev);
|
||||||
dev->id_irq = 0x1 << info.irq;
|
|
||||||
dev->id_intr = bt_isa_intr;
|
|
||||||
|
|
||||||
bt_unit++;
|
isa_set_drq(dev, info.drq);
|
||||||
return (BT_NREGS);
|
isa_set_irq(dev, info.irq);
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach all the sub-devices we can find
|
* Attach all the sub-devices we can find
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bt_isa_attach(dev)
|
bt_isa_attach(device_t dev)
|
||||||
struct isa_device *dev;
|
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_dma_filter_t *filter;
|
bus_dma_filter_t *filter;
|
||||||
void *filter_arg;
|
void *filter_arg;
|
||||||
bus_addr_t lowaddr;
|
bus_addr_t lowaddr;
|
||||||
|
int error;
|
||||||
|
|
||||||
bt = bt_softcs[dev->id_unit];
|
/* Initialise softc */
|
||||||
if (dev->id_drq != -1)
|
error = bt_isa_alloc_resources(dev);
|
||||||
isa_dmacascade(dev->id_drq);
|
if (error) {
|
||||||
|
device_printf(dev, "can't allocate resources in bt_isa_attach\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate our parent dmatag */
|
/* Allocate our parent dmatag */
|
||||||
filter = NULL;
|
filter = NULL;
|
||||||
@ -186,13 +232,13 @@ bt_isa_attach(dev)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_init(bt)) {
|
if (bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
||||||
@ -207,8 +253,8 @@ bt_isa_attach(dev)
|
|||||||
/*nsegments*/1,
|
/*nsegments*/1,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->sense_dmat) != 0) {
|
/*flags*/0, &bt->sense_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
@ -217,8 +263,8 @@ bt_isa_attach(dev)
|
|||||||
if (bus_dmamem_alloc(bt->sense_dmat,
|
if (bus_dmamem_alloc(bt->sense_dmat,
|
||||||
(void **)&bt->sense_buffers,
|
(void **)&bt->sense_buffers,
|
||||||
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
@ -232,19 +278,13 @@ bt_isa_attach(dev)
|
|||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (bt_attach(bt));
|
error = bt_attach(dev);
|
||||||
}
|
if (error) {
|
||||||
|
bt_isa_release_resources(dev);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
return (0);
|
||||||
* Handle an ISA interrupt.
|
|
||||||
* XXX should go away as soon as ISA interrupt handlers
|
|
||||||
* take a (void *) arg.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
bt_isa_intr(void *unit)
|
|
||||||
{
|
|
||||||
struct bt_softc* arg = bt_softcs[(int)unit];
|
|
||||||
bt_intr((void *)arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BIOS_MAP_SIZE (16 * 1024)
|
#define BIOS_MAP_SIZE (16 * 1024)
|
||||||
@ -273,3 +313,22 @@ btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
|||||||
bt = (struct bt_softc*)arg;
|
bt = (struct bt_softc*)arg;
|
||||||
bt->sense_buffers_physbase = segs->ds_addr;
|
bt->sense_buffers_physbase = segs->ds_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_isa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_isa_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_isa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_isa_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_isa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, isa, bt_isa_driver, bt_devclass, 0, 0);
|
||||||
|
@ -23,11 +23,10 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: isa_compat.h,v 1.1 1999/04/16 21:22:23 peter Exp $
|
* $Id: isa_compat.h,v 1.2 1999/04/17 19:38:38 peter Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "bt.h"
|
|
||||||
#include "adv.h"
|
#include "adv.h"
|
||||||
#include "aha.h"
|
#include "aha.h"
|
||||||
#include "wdc.h"
|
#include "wdc.h"
|
||||||
@ -96,7 +95,6 @@ struct old_isa_driver {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern struct isa_driver vtdriver;
|
extern struct isa_driver vtdriver;
|
||||||
extern struct isa_driver btdriver;
|
|
||||||
extern struct isa_driver advdriver;
|
extern struct isa_driver advdriver;
|
||||||
extern struct isa_driver ahadriver;
|
extern struct isa_driver ahadriver;
|
||||||
extern struct isa_driver wdcdriver;
|
extern struct isa_driver wdcdriver;
|
||||||
@ -308,9 +306,6 @@ static struct old_isa_driver old_drivers[] = {
|
|||||||
|
|
||||||
/* CAM */
|
/* CAM */
|
||||||
|
|
||||||
#if NBT > 0
|
|
||||||
{ DRIVER_TYPE_CAM, &btdriver },
|
|
||||||
#endif
|
|
||||||
#if NADV > 0
|
#if NADV > 0
|
||||||
{ DRIVER_TYPE_CAM, &advdriver },
|
{ DRIVER_TYPE_CAM, &advdriver },
|
||||||
#endif
|
#endif
|
||||||
|
195
sys/isa/bt_isa.c
195
sys/isa/bt_isa.c
@ -26,33 +26,90 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_isa.c,v 1.6 1999/03/08 21:32:59 gibbs Exp $
|
* $Id: bt_isa.c,v 1.7 1999/04/06 21:15:18 phk Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <i386/isa/isa_device.h>
|
#include <isa/isavar.h>
|
||||||
|
#include <i386/isa/isa_dma.h>
|
||||||
#include <dev/buslogic/btreg.h>
|
#include <dev/buslogic/btreg.h>
|
||||||
|
|
||||||
#include <cam/scsi/scsi_all.h>
|
#include <cam/scsi/scsi_all.h>
|
||||||
|
|
||||||
static int bt_isa_probe __P((struct isa_device *dev));
|
|
||||||
static int bt_isa_attach __P((struct isa_device *dev));
|
|
||||||
static void bt_isa_intr __P((void *unit));
|
|
||||||
|
|
||||||
static bus_dma_filter_t btvlbouncefilter;
|
static bus_dma_filter_t btvlbouncefilter;
|
||||||
static bus_dmamap_callback_t btmapsensebuffers;
|
static bus_dmamap_callback_t btmapsensebuffers;
|
||||||
|
|
||||||
struct isa_driver btdriver =
|
static int
|
||||||
|
bt_isa_alloc_resources(device_t dev)
|
||||||
{
|
{
|
||||||
bt_isa_probe,
|
int rid;
|
||||||
bt_isa_attach,
|
struct resource *port;
|
||||||
"bt"
|
struct resource *irq;
|
||||||
};
|
struct resource *drq;
|
||||||
|
|
||||||
|
rid = 0;
|
||||||
|
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!port)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
if (isa_get_irq(dev) != -1) {
|
||||||
|
rid = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!irq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
irq = 0;
|
||||||
|
|
||||||
|
if (isa_get_drq(dev) != -1) {
|
||||||
|
rid = 0;
|
||||||
|
drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
if (!drq) {
|
||||||
|
if (port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
0, port);
|
||||||
|
if (irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ,
|
||||||
|
0, irq);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
drq = 0;
|
||||||
|
|
||||||
|
bt_init_softc(dev, port, irq, drq);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_isa_release_resources(device_t dev)
|
||||||
|
{
|
||||||
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
if (bt->drq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->drq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the device can be found at the port given
|
* Check if the device can be found at the port given
|
||||||
@ -61,35 +118,24 @@ struct isa_driver btdriver =
|
|||||||
* autoconf.c
|
* autoconf.c
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bt_isa_probe(dev)
|
bt_isa_probe(device_t dev)
|
||||||
struct isa_device *dev;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* find unit and check we have that many defined
|
* find unit and check we have that many defined
|
||||||
*/
|
*/
|
||||||
struct bt_softc *bt;
|
|
||||||
int port_index;
|
int port_index;
|
||||||
int max_port_index;
|
int max_port_index;
|
||||||
|
|
||||||
/*
|
|
||||||
* We ignore the unit number assigned by config to allow
|
|
||||||
* consistant numbering between PCI/EISA/ISA devices.
|
|
||||||
* This is a total kludge until we have a configuration
|
|
||||||
* manager.
|
|
||||||
*/
|
|
||||||
dev->id_unit = bt_unit;
|
|
||||||
|
|
||||||
bt = NULL;
|
|
||||||
port_index = 0;
|
port_index = 0;
|
||||||
max_port_index = BT_NUM_ISAPORTS - 1;
|
max_port_index = BT_NUM_ISAPORTS - 1;
|
||||||
/*
|
/*
|
||||||
* Bound our board search if the user has
|
* Bound our board search if the user has
|
||||||
* specified an exact port.
|
* specified an exact port.
|
||||||
*/
|
*/
|
||||||
bt_find_probe_range(dev->id_iobase, &port_index, &max_port_index);
|
bt_find_probe_range(isa_get_port(dev), &port_index, &max_port_index);
|
||||||
|
|
||||||
if (port_index < 0)
|
if (port_index < 0)
|
||||||
return 0;
|
return (ENXIO);
|
||||||
|
|
||||||
/* Attempt to find an adapter */
|
/* Attempt to find an adapter */
|
||||||
for (;port_index <= max_port_index; port_index++) {
|
for (;port_index <= max_port_index; port_index++) {
|
||||||
@ -97,6 +143,8 @@ bt_isa_probe(dev)
|
|||||||
u_int ioport;
|
u_int ioport;
|
||||||
|
|
||||||
ioport = bt_iop_from_bio(port_index);
|
ioport = bt_iop_from_bio(port_index);
|
||||||
|
isa_set_port(dev, ioport);
|
||||||
|
isa_set_portsize(dev, BT_NREGS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure this port has not already been claimed already
|
* Ensure this port has not already been claimed already
|
||||||
@ -104,52 +152,50 @@ bt_isa_probe(dev)
|
|||||||
*/
|
*/
|
||||||
if (bt_check_probed_iop(ioport) != 0)
|
if (bt_check_probed_iop(ioport) != 0)
|
||||||
continue;
|
continue;
|
||||||
dev->id_iobase = ioport;
|
|
||||||
if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET))
|
/* Initialise the softc for use during probing */
|
||||||
|
if (bt_isa_alloc_resources(dev) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Allocate a softc for use during probing */
|
|
||||||
bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
|
|
||||||
|
|
||||||
if (bt == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* We're going to attempt to probe it now, so mark it probed */
|
/* We're going to attempt to probe it now, so mark it probed */
|
||||||
bt_mark_probed_bio(port_index);
|
bt_mark_probed_bio(port_index);
|
||||||
|
|
||||||
if (bt_port_probe(bt, &info) != 0) {
|
if (bt_port_probe(dev, &info) != 0) {
|
||||||
printf("bt_isa_probe: Probe failed for card at 0x%x\n",
|
printf("bt_isa_probe: Probe failed for card at 0x%x\n",
|
||||||
ioport);
|
ioport);
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->id_drq = info.drq;
|
bt_isa_release_resources(dev);
|
||||||
dev->id_irq = 0x1 << info.irq;
|
|
||||||
dev->id_intr = bt_isa_intr;
|
|
||||||
|
|
||||||
bt_unit++;
|
isa_set_drq(dev, info.drq);
|
||||||
return (BT_NREGS);
|
isa_set_irq(dev, info.irq);
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach all the sub-devices we can find
|
* Attach all the sub-devices we can find
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bt_isa_attach(dev)
|
bt_isa_attach(device_t dev)
|
||||||
struct isa_device *dev;
|
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_dma_filter_t *filter;
|
bus_dma_filter_t *filter;
|
||||||
void *filter_arg;
|
void *filter_arg;
|
||||||
bus_addr_t lowaddr;
|
bus_addr_t lowaddr;
|
||||||
|
int error;
|
||||||
|
|
||||||
bt = bt_softcs[dev->id_unit];
|
/* Initialise softc */
|
||||||
if (dev->id_drq != -1)
|
error = bt_isa_alloc_resources(dev);
|
||||||
isa_dmacascade(dev->id_drq);
|
if (error) {
|
||||||
|
device_printf(dev, "can't allocate resources in bt_isa_attach\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate our parent dmatag */
|
/* Allocate our parent dmatag */
|
||||||
filter = NULL;
|
filter = NULL;
|
||||||
@ -186,13 +232,13 @@ bt_isa_attach(dev)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bt_init(bt)) {
|
if (bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
||||||
@ -207,8 +253,8 @@ bt_isa_attach(dev)
|
|||||||
/*nsegments*/1,
|
/*nsegments*/1,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->sense_dmat) != 0) {
|
/*flags*/0, &bt->sense_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
@ -217,8 +263,8 @@ bt_isa_attach(dev)
|
|||||||
if (bus_dmamem_alloc(bt->sense_dmat,
|
if (bus_dmamem_alloc(bt->sense_dmat,
|
||||||
(void **)&bt->sense_buffers,
|
(void **)&bt->sense_buffers,
|
||||||
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
||||||
bt_free(bt);
|
bt_isa_release_resources(dev);
|
||||||
return (-1);
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
@ -232,19 +278,13 @@ bt_isa_attach(dev)
|
|||||||
bt->init_level++;
|
bt->init_level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (bt_attach(bt));
|
error = bt_attach(dev);
|
||||||
}
|
if (error) {
|
||||||
|
bt_isa_release_resources(dev);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
return (0);
|
||||||
* Handle an ISA interrupt.
|
|
||||||
* XXX should go away as soon as ISA interrupt handlers
|
|
||||||
* take a (void *) arg.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
bt_isa_intr(void *unit)
|
|
||||||
{
|
|
||||||
struct bt_softc* arg = bt_softcs[(int)unit];
|
|
||||||
bt_intr((void *)arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BIOS_MAP_SIZE (16 * 1024)
|
#define BIOS_MAP_SIZE (16 * 1024)
|
||||||
@ -273,3 +313,22 @@ btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
|||||||
bt = (struct bt_softc*)arg;
|
bt = (struct bt_softc*)arg;
|
||||||
bt->sense_buffers_physbase = segs->ds_addr;
|
bt->sense_buffers_physbase = segs->ds_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_isa_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_isa_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_isa_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_isa_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_isa_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, isa, bt_isa_driver, bt_devclass, 0, 0);
|
||||||
|
181
sys/pci/bt_pci.c
181
sys/pci/bt_pci.c
@ -26,7 +26,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: bt_pci.c,v 1.3 1998/11/10 06:45:14 gibbs Exp $
|
* $Id: bt_pci.c,v 1.4 1998/12/14 06:32:54 dillon Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
|
||||||
#include <pci/pcireg.h>
|
#include <pci/pcireg.h>
|
||||||
#include <pci/pcivar.h>
|
#include <pci/pcivar.h>
|
||||||
@ -41,6 +42,8 @@
|
|||||||
#include <machine/bus_memio.h>
|
#include <machine/bus_memio.h>
|
||||||
#include <machine/bus_pio.h>
|
#include <machine/bus_pio.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
#include <dev/buslogic/btreg.h>
|
#include <dev/buslogic/btreg.h>
|
||||||
|
|
||||||
@ -51,72 +54,74 @@
|
|||||||
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul
|
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul
|
||||||
#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul
|
#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul
|
||||||
|
|
||||||
static int btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
|
|
||||||
bus_space_handle_t* bshp);
|
|
||||||
static const char* bt_pci_probe(pcici_t tag, pcidi_t type);
|
|
||||||
static void bt_pci_attach(pcici_t config_id, int unit);
|
|
||||||
|
|
||||||
static struct pci_device bt_pci_driver = {
|
|
||||||
"bt",
|
|
||||||
bt_pci_probe,
|
|
||||||
bt_pci_attach,
|
|
||||||
&bt_unit,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
DATA_SET (pcidevice_set, bt_pci_driver);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
|
bt_pci_alloc_resources(device_t dev)
|
||||||
bus_space_handle_t* bshp)
|
|
||||||
{
|
{
|
||||||
vm_offset_t vaddr;
|
int command, type = 0, rid, zero;
|
||||||
vm_offset_t paddr;
|
struct resource *regs = 0;
|
||||||
u_int16_t io_port;
|
struct resource *irq = 0;
|
||||||
int command;
|
|
||||||
|
|
||||||
vaddr = 0;
|
command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
|
||||||
paddr = 0;
|
|
||||||
command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1);
|
|
||||||
/* XXX Memory Mapped I/O seems to cause problems */
|
|
||||||
#if 0
|
#if 0
|
||||||
if ((command & PCIM_CMD_MEMEN) == 0
|
/* XXX Memory Mapped I/O seems to cause problems */
|
||||||
|| (pci_map_mem(config_id, BT_PCI_MEMADDR, &vaddr, &paddr)) == 0)
|
if (command & PCIM_CMD_MEMEN) {
|
||||||
#endif
|
type = SYS_RES_MEMORY;
|
||||||
if ((command & PCIM_CMD_PORTEN) == 0
|
rid = BT_PCI_MEMADDR;
|
||||||
|| (pci_map_port(config_id, BT_PCI_IOADDR, &io_port)) == 0)
|
regs = bus_alloc_resource(dev, type, &rid,
|
||||||
return (-1);
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
|
||||||
if (vaddr != 0) {
|
|
||||||
*tagp = I386_BUS_SPACE_MEM;
|
|
||||||
*bshp = vaddr;
|
|
||||||
} else {
|
|
||||||
*tagp = I386_BUS_SPACE_IO;
|
|
||||||
*bshp = io_port;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (!regs && (command & PCIM_CMD_PORTEN)) {
|
||||||
|
type = SYS_RES_IOPORT;
|
||||||
|
rid = BT_PCI_IOADDR;
|
||||||
|
regs = bus_alloc_resource(dev, type, &rid,
|
||||||
|
0, ~0, 1, RF_ACTIVE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!regs)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
zero = 0;
|
||||||
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero,
|
||||||
|
0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
|
||||||
|
if (!irq) {
|
||||||
|
bus_release_resource(dev, type, rid, regs);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bt_init_softc(dev, regs, irq, 0);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char*
|
static void
|
||||||
bt_pci_probe (pcici_t config_id, pcidi_t type)
|
bt_pci_release_resources(device_t dev)
|
||||||
{
|
{
|
||||||
switch(type) {
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
|
|
||||||
|
if (bt->port)
|
||||||
|
/* XXX can't cope with memory registers anyway */
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||||
|
BT_PCI_IOADDR, bt->port);
|
||||||
|
if (bt->irq)
|
||||||
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->irq);
|
||||||
|
bt_free_softc(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bt_pci_probe(device_t dev)
|
||||||
|
{
|
||||||
|
switch (pci_get_devid(dev)) {
|
||||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
|
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
|
||||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
|
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_space_tag_t tag;
|
|
||||||
bus_space_handle_t bsh;
|
|
||||||
pci_info_data_t pci_info;
|
pci_info_data_t pci_info;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
error = bt_pci_alloc_resources(dev);
|
||||||
break;
|
if (error)
|
||||||
|
return (error);
|
||||||
bt = bt_alloc(BT_TEMP_UNIT, tag, bsh);
|
|
||||||
if (bt == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if an ISA compatible I/O port has been
|
* Determine if an ISA compatible I/O port has been
|
||||||
@ -131,7 +136,7 @@ bt_pci_probe (pcici_t config_id, pcidi_t type)
|
|||||||
if (error == 0
|
if (error == 0
|
||||||
&& pci_info.io_port < BIO_DISABLED) {
|
&& pci_info.io_port < BIO_DISABLED) {
|
||||||
bt_mark_probed_bio(pci_info.io_port);
|
bt_mark_probed_bio(pci_info.io_port);
|
||||||
if (bsh != bt_iop_from_bio(pci_info.io_port)) {
|
if (bt->bsh != bt_iop_from_bio(pci_info.io_port)) {
|
||||||
u_int8_t new_addr;
|
u_int8_t new_addr;
|
||||||
|
|
||||||
new_addr = BIO_DISABLED;
|
new_addr = BIO_DISABLED;
|
||||||
@ -142,30 +147,30 @@ bt_pci_probe (pcici_t config_id, pcidi_t type)
|
|||||||
DEFAULT_CMD_TIMEOUT);
|
DEFAULT_CMD_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bt_free(bt);
|
bt_pci_release_resources(dev);
|
||||||
return ("Buslogic Multi-Master SCSI Host Adapter");
|
device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter");
|
||||||
break;
|
return (0);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
bt_pci_attach(pcici_t config_id, int unit)
|
bt_pci_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct bt_softc *bt;
|
struct bt_softc *bt = device_get_softc(dev);
|
||||||
bus_space_tag_t tag;
|
|
||||||
bus_space_handle_t bsh;
|
|
||||||
int opri;
|
int opri;
|
||||||
|
int error;
|
||||||
|
|
||||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
/* Initialise softc */
|
||||||
return;
|
error = bt_pci_alloc_resources(dev);
|
||||||
|
if (error) {
|
||||||
if ((bt = bt_alloc(unit, tag, bsh)) == NULL)
|
device_printf(dev, "can't allocate resources in bt_pci_attach\n");
|
||||||
return; /* XXX PCI code should take return status */
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a dmatag for our CCB DMA maps */
|
/* Allocate a dmatag for our CCB DMA maps */
|
||||||
/* XXX Should be a child of the PCI bus dma tag */
|
/* XXX Should be a child of the PCI bus dma tag */
|
||||||
@ -177,14 +182,10 @@ bt_pci_attach(pcici_t config_id, int unit)
|
|||||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||||
bt_free(bt);
|
bt_pci_release_resources(dev);
|
||||||
return;
|
return (ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pci_map_int(config_id, bt_intr, (void *)bt, &cam_imask)) == 0) {
|
|
||||||
bt_free(bt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Protect ourself from spurrious interrupts during
|
* Protect ourself from spurrious interrupts during
|
||||||
* intialization and attach. We should really rely
|
* intialization and attach. We should really rely
|
||||||
@ -195,16 +196,40 @@ bt_pci_attach(pcici_t config_id, int unit)
|
|||||||
*/
|
*/
|
||||||
opri = splcam();
|
opri = splcam();
|
||||||
|
|
||||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) {
|
||||||
bt_free(bt);
|
bt_pci_release_resources(dev);
|
||||||
splx(opri);
|
splx(opri);
|
||||||
return; /* XXX PCI code should take return status */
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_attach(bt);
|
error = bt_attach(dev);
|
||||||
|
|
||||||
splx(opri);
|
splx(opri);
|
||||||
return;
|
|
||||||
|
if (error) {
|
||||||
|
bt_pci_release_resources(dev);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static device_method_t bt_pci_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, bt_pci_probe),
|
||||||
|
DEVMETHOD(device_attach, bt_pci_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t bt_pci_driver = {
|
||||||
|
"bt",
|
||||||
|
bt_pci_methods,
|
||||||
|
DRIVER_TYPE_CAM,
|
||||||
|
sizeof(struct bt_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t bt_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0);
|
||||||
|
|
||||||
#endif /* NPCI > 0 */
|
#endif /* NPCI > 0 */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**
|
**
|
||||||
** $Id: pcisupport.c,v 1.96 1999/04/16 21:22:52 peter Exp $
|
** $Id: pcisupport.c,v 1.97 1999/04/17 19:48:45 dfr Exp $
|
||||||
**
|
**
|
||||||
** Device driver for DEC/INTEL PCI chipsets.
|
** Device driver for DEC/INTEL PCI chipsets.
|
||||||
**
|
**
|
||||||
@ -890,6 +890,19 @@ static devclass_t pcib_devclass;
|
|||||||
|
|
||||||
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0);
|
DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0);
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
eisab_match(device_t dev)
|
||||||
|
{
|
||||||
|
switch (pci_get_devid(dev)) {
|
||||||
|
case 0x04828086:
|
||||||
|
/* Recognize this specifically, it has PCI-HOST class (!) */
|
||||||
|
return ("Intel 82375EB PCI-EISA bridge");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
isab_match(device_t dev)
|
isab_match(device_t dev)
|
||||||
{
|
{
|
||||||
@ -901,8 +914,6 @@ isab_match(device_t dev)
|
|||||||
if (rev == 3)
|
if (rev == 3)
|
||||||
return ("Intel 82378ZB PCI to ISA bridge");
|
return ("Intel 82378ZB PCI to ISA bridge");
|
||||||
return ("Intel 82378IB PCI to ISA bridge");
|
return ("Intel 82378IB PCI to ISA bridge");
|
||||||
case 0x04828086:
|
|
||||||
return ("Intel 82375EB PCI-EISA bridge");
|
|
||||||
case 0x122e8086:
|
case 0x122e8086:
|
||||||
return ("Intel 82371FB PCI to ISA bridge");
|
return ("Intel 82371FB PCI to ISA bridge");
|
||||||
case 0x70008086:
|
case 0x70008086:
|
||||||
@ -947,10 +958,26 @@ static int
|
|||||||
isab_probe(device_t dev)
|
isab_probe(device_t dev)
|
||||||
{
|
{
|
||||||
const char *desc;
|
const char *desc;
|
||||||
|
int is_eisa;
|
||||||
|
|
||||||
desc = isab_match(dev);
|
is_eisa = 0;
|
||||||
|
desc = eisab_match(dev);
|
||||||
|
if (desc)
|
||||||
|
is_eisa = 1;
|
||||||
|
else
|
||||||
|
desc = isab_match(dev);
|
||||||
if (desc) {
|
if (desc) {
|
||||||
device_set_desc_copy(dev, desc);
|
device_set_desc_copy(dev, desc);
|
||||||
|
|
||||||
|
/* In case of a generic EISA bridge */
|
||||||
|
if (pci_get_subclass(dev) == PCIS_BRIDGE_EISA)
|
||||||
|
is_eisa = 1;
|
||||||
|
|
||||||
|
/* For PCI-EISA bridge, add both eisa and isa */
|
||||||
|
/* Don't bother adding more than one EISA bus */
|
||||||
|
if (is_eisa && !devclass_get_device(devclass_find("isa"), 0))
|
||||||
|
device_add_child(dev, "eisa", -1, 0);
|
||||||
|
|
||||||
/* Don't bother adding more than one ISA bus */
|
/* Don't bother adding more than one ISA bus */
|
||||||
if (!devclass_get_device(devclass_find("isa"), 0))
|
if (!devclass_get_device(devclass_find("isa"), 0))
|
||||||
device_add_child(dev, "isa", -1, 0);
|
device_add_child(dev, "isa", -1, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user