Mylex/Buslogic MultiMaster SCSI-Host Adapter Driver for CAM.
This commit is contained in:
parent
4530878e33
commit
532abf3b7a
2154
sys/dev/buslogic/bt.c
Normal file
2154
sys/dev/buslogic/bt.c
Normal file
File diff suppressed because it is too large
Load Diff
392
sys/dev/buslogic/bt_eisa.c
Normal file
392
sys/dev/buslogic/bt_eisa.c
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT74x SCSI controllers
|
||||
*
|
||||
* Copyright (c) 1995, 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice immediately at the beginning of the file, without modification,
|
||||
* this list of conditions, and the following disclaimer.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "eisa.h"
|
||||
#if NEISA > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <i386/eisa/eisaconf.h>
|
||||
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#define EISA_DEVICE_ID_BUSLOGIC_74X_B 0x0ab34201
|
||||
#define EISA_DEVICE_ID_BUSLOGIC_74X_C 0x0ab34202
|
||||
#define EISA_DEVICE_ID_SDC3222F 0x0ab34781
|
||||
#define EISA_DEVICE_ID_AMI_4801 0x05a94801
|
||||
|
||||
#define BT_IOSIZE 0x04 /* Move to central header */
|
||||
#define BT_EISA_IOSIZE 0x100
|
||||
#define BT_EISA_SLOT_OFFSET 0xc00
|
||||
|
||||
#define EISA_IOCONF 0x08C
|
||||
#define PORTADDR 0x07
|
||||
#define PORT_330 0x00
|
||||
#define PORT_334 0x01
|
||||
#define PORT_230 0x02
|
||||
#define PORT_234 0x03
|
||||
#define PORT_130 0x04
|
||||
#define PORT_134 0x05
|
||||
#define IRQ_CHANNEL 0xe0
|
||||
#define INT_11 0x40
|
||||
#define INT_10 0x20
|
||||
#define INT_15 0xa0
|
||||
#define INT_12 0x60
|
||||
#define INT_14 0x80
|
||||
#define INT_9 0x00
|
||||
|
||||
#define EISA_IRQ_TYPE 0x08D
|
||||
#define LEVEL 0x40
|
||||
|
||||
/* Definitions for the AMI Series 48 controler */
|
||||
#define AMI_EISA_IOSIZE 0x500 /* Two separate ranges?? */
|
||||
#define AMI_EISA_SLOT_OFFSET 0x800
|
||||
#define AMI_EISA_IOCONF 0x000
|
||||
#define AMI_DMA_CHANNEL 0x03
|
||||
#define AMI_IRQ_CHANNEL 0x1c
|
||||
#define AMI_INT_15 0x14
|
||||
#define AMI_INT_14 0x10
|
||||
#define AMI_INT_12 0x0c
|
||||
#define AMI_INT_11 0x00
|
||||
#define AMI_INT_10 0x08
|
||||
#define AMI_INT_9 0x04
|
||||
#define AMI_BIOS_ADDR 0xe0
|
||||
|
||||
#define AMI_EISA_IOCONF1 0x001
|
||||
#define AMI_PORTADDR 0x0e
|
||||
#define AMI_PORT_334 0x08
|
||||
#define AMI_PORT_330 0x00
|
||||
#define AMI_PORT_234 0x0c
|
||||
#define AMI_PORT_230 0x04
|
||||
#define AMI_PORT_134 0x0a
|
||||
#define AMI_PORT_130 0x02
|
||||
#define AMI_IRQ_LEVEL 0x01
|
||||
|
||||
|
||||
#define AMI_MISC2_OPTIONS 0x49E
|
||||
#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)
|
||||
{
|
||||
switch(type) {
|
||||
case EISA_DEVICE_ID_BUSLOGIC_74X_B:
|
||||
return ("Buslogic 74xB SCSI host adapter");
|
||||
break;
|
||||
case EISA_DEVICE_ID_BUSLOGIC_74X_C:
|
||||
return ("Buslogic 74xC SCSI host adapter");
|
||||
break;
|
||||
case EISA_DEVICE_ID_SDC3222F:
|
||||
return ("Storage Dimensions SDC3222F SCSI host adapter");
|
||||
break;
|
||||
case EISA_DEVICE_ID_AMI_4801:
|
||||
return ("AMI Series 48 SCSI host adapter");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
bt_eisa_probe(void)
|
||||
{
|
||||
u_long iobase;
|
||||
struct eisa_device *e_dev = NULL;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
while ((e_dev = eisa_match_dev(e_dev, bt_match))) {
|
||||
u_char ioconf;
|
||||
u_long port;
|
||||
int irq;
|
||||
|
||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
|
||||
if (e_dev->id == EISA_DEVICE_ID_AMI_4801) {
|
||||
u_char ioconf1;
|
||||
iobase += AMI_EISA_SLOT_OFFSET;
|
||||
|
||||
eisa_add_iospace(e_dev, iobase, AMI_EISA_IOSIZE,
|
||||
RESVADDR_NONE);
|
||||
|
||||
ioconf = inb(iobase + AMI_EISA_IOCONF);
|
||||
ioconf1 = inb(iobase + AMI_EISA_IOCONF1);
|
||||
/* Determine "ISA" I/O port */
|
||||
switch (ioconf1 & AMI_PORTADDR) {
|
||||
case AMI_PORT_330:
|
||||
port = 0x330;
|
||||
break;
|
||||
case AMI_PORT_334:
|
||||
port = 0x334;
|
||||
break;
|
||||
case AMI_PORT_230:
|
||||
port = 0x230;
|
||||
break;
|
||||
case AMI_PORT_234:
|
||||
port = 0x234;
|
||||
break;
|
||||
case AMI_PORT_134:
|
||||
port = 0x134;
|
||||
break;
|
||||
case AMI_PORT_130:
|
||||
port = 0x130;
|
||||
break;
|
||||
default:
|
||||
/* Disabled */
|
||||
printf("bt: AMI EISA Adapter at "
|
||||
"slot %d has a disabled I/O "
|
||||
"port. Cannot attach.\n",
|
||||
e_dev->ioconf.slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine our IRQ */
|
||||
switch (ioconf & AMI_IRQ_CHANNEL) {
|
||||
case AMI_INT_11:
|
||||
irq = 11;
|
||||
break;
|
||||
case AMI_INT_10:
|
||||
irq = 10;
|
||||
break;
|
||||
case AMI_INT_15:
|
||||
irq = 15;
|
||||
break;
|
||||
case AMI_INT_12:
|
||||
irq = 12;
|
||||
break;
|
||||
case AMI_INT_14:
|
||||
irq = 14;
|
||||
break;
|
||||
case AMI_INT_9:
|
||||
irq = 9;
|
||||
break;
|
||||
default:
|
||||
/* Disabled */
|
||||
printf("bt: AMI EISA Adapter at "
|
||||
"slot %d has its IRQ disabled. "
|
||||
"Cannot attach.\n",
|
||||
e_dev->ioconf.slot);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
iobase += BT_EISA_SLOT_OFFSET;
|
||||
|
||||
eisa_add_iospace(e_dev, iobase, BT_EISA_IOSIZE,
|
||||
RESVADDR_NONE);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Determine our IRQ */
|
||||
switch (ioconf & IRQ_CHANNEL) {
|
||||
case INT_11:
|
||||
irq = 11;
|
||||
break;
|
||||
case INT_10:
|
||||
irq = 10;
|
||||
break;
|
||||
case INT_15:
|
||||
irq = 15;
|
||||
break;
|
||||
case INT_12:
|
||||
irq = 12;
|
||||
break;
|
||||
case INT_14:
|
||||
irq = 14;
|
||||
break;
|
||||
case INT_9:
|
||||
irq = 9;
|
||||
break;
|
||||
default:
|
||||
/* Disabled */
|
||||
printf("bt: Buslogic EISA Adapter at "
|
||||
"slot %d has its IRQ disabled. "
|
||||
"Cannot attach.\n",
|
||||
e_dev->ioconf.slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
bt_mark_probed_iop(port);
|
||||
eisa_add_iospace(e_dev, port, BT_IOSIZE, RESVADDR_NONE);
|
||||
eisa_add_intr(e_dev, irq);
|
||||
|
||||
eisa_registerdev(e_dev, &bt_eisa_driver);
|
||||
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
bt_eisa_attach(struct eisa_device *e_dev)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
int unit = e_dev->unit;
|
||||
int irq;
|
||||
resvaddr_t *ioport;
|
||||
resvaddr_t *eisa_ioport;
|
||||
u_char level_intr;
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
if (e_dev->id == EISA_DEVICE_ID_AMI_4801) {
|
||||
level_intr = inb(eisa_ioport->addr + AMI_EISA_IOCONF1)
|
||||
& AMI_IRQ_LEVEL;
|
||||
} else {
|
||||
level_intr = inb(eisa_ioport->addr + EISA_IRQ_TYPE)
|
||||
& LEVEL;
|
||||
}
|
||||
|
||||
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 */
|
||||
/* XXX Should be a child of the PCI bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/0, /*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (eisa_reg_intr(e_dev, irq, bt_intr, (void *)bt, &cam_imask,
|
||||
/*shared ==*/level_intr)) {
|
||||
bt_free(bt);
|
||||
return -1;
|
||||
}
|
||||
eisa_reg_end(e_dev);
|
||||
|
||||
/*
|
||||
* Now that we know we own the resources we need, do the full
|
||||
* card initialization.
|
||||
*/
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* Attach sub-devices - always succeeds */
|
||||
bt_attach(bt);
|
||||
|
||||
if (eisa_enable_intr(e_dev, irq)) {
|
||||
bt_free(bt);
|
||||
eisa_release_intr(e_dev, irq, bt_intr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NEISA > 0 */
|
322
sys/dev/buslogic/bt_isa.c
Normal file
322
sys/dev/buslogic/bt_isa.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT-54X and BT-445 cards
|
||||
*
|
||||
* Copyright (c) 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
#include "ioconf.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_dmamap_callback_t btmapsensebuffers;
|
||||
|
||||
struct isa_driver btdriver =
|
||||
{
|
||||
bt_isa_probe,
|
||||
bt_isa_attach,
|
||||
"bt"
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if the device can be found at the port given
|
||||
* and if so, set it up ready for further work
|
||||
* as an argument, takes the isa_device structure from
|
||||
* autoconf.c
|
||||
*/
|
||||
static int
|
||||
bt_isa_probe(dev)
|
||||
struct isa_device *dev;
|
||||
{
|
||||
/*
|
||||
* find unit and check we have that many defined
|
||||
*/
|
||||
struct bt_softc *bt;
|
||||
int 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;
|
||||
max_port_index = BT_NUM_ISAPORTS - 1;
|
||||
/*
|
||||
* Bound our board search if the user has
|
||||
* specified an exact port.
|
||||
*/
|
||||
if (dev->id_iobase > 0) {
|
||||
for (;port_index <= max_port_index; port_index++)
|
||||
if (dev->id_iobase >= bt_isa_ports[port_index].addr)
|
||||
break;
|
||||
if ((port_index > max_port_index)
|
||||
|| (dev->id_iobase != bt_isa_ports[port_index].addr)) {
|
||||
printf("
|
||||
bt_isa_probe: Invalid baseport of 0x%x specified.
|
||||
bt_isa_probe: Nearest valid baseport is 0x%x.
|
||||
bt_isa_probe: Failing probe.\n",
|
||||
dev->id_iobase,
|
||||
(port_index <= max_port_index)
|
||||
? bt_isa_ports[port_index].addr
|
||||
: bt_isa_ports[max_port_index].addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to find an adapter */
|
||||
for (;port_index <= max_port_index; port_index++) {
|
||||
config_data_t config_data;
|
||||
u_int ioport;
|
||||
int error;
|
||||
|
||||
ioport = bt_isa_ports[port_index].addr;
|
||||
|
||||
/*
|
||||
* Ensure this port has not already been claimed already
|
||||
* by a PCI or EISA adapter.
|
||||
*/
|
||||
if (bt_check_probed_iop(ioport) != 0)
|
||||
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 */
|
||||
bt_mark_probed_bio(port_index);
|
||||
|
||||
/* See if there is really a card present */
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
|
||||
bt_free(bt);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine our IRQ, and DMA settings and
|
||||
* export them to the configuration system.
|
||||
*/
|
||||
error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
|
||||
(u_int8_t*)&config_data, sizeof(config_data),
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
if (error != 0) {
|
||||
printf("bt_isa_probe: Could not determine IRQ or DMA "
|
||||
"settings for adapter at 0x%x. Failing probe\n",
|
||||
ioport);
|
||||
bt_free(bt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bt->model[0] == '5') {
|
||||
/* DMA settings only make sense for ISA cards */
|
||||
switch (config_data.dma_chan) {
|
||||
case DMA_CHAN_5:
|
||||
dev->id_drq = 5;
|
||||
break;
|
||||
case DMA_CHAN_6:
|
||||
dev->id_drq = 6;
|
||||
break;
|
||||
case DMA_CHAN_7:
|
||||
dev->id_drq = 7;
|
||||
break;
|
||||
default:
|
||||
printf("bt_isa_probe: Invalid DMA setting "
|
||||
"detected for adapter at 0x%x. "
|
||||
"Failing probe\n", ioport);
|
||||
}
|
||||
} else {
|
||||
/* VL DMA */
|
||||
dev->id_drq = -1;
|
||||
}
|
||||
dev->id_iobase = bt_isa_ports[port_index].addr;
|
||||
dev->id_irq = (config_data.irq << 9);
|
||||
dev->id_intr = bt_isa_intr;
|
||||
bt_unit++;
|
||||
return (BT_NREGS);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach all the sub-devices we can find
|
||||
*/
|
||||
static int
|
||||
bt_isa_attach(dev)
|
||||
struct isa_device *dev;
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_dma_filter_t *filter;
|
||||
void *filter_arg;
|
||||
bus_addr_t lowaddr;
|
||||
|
||||
bt = bt_softcs[dev->id_unit];
|
||||
if (dev->id_drq != -1)
|
||||
isa_dmacascade(dev->id_drq);
|
||||
|
||||
/* Allocate our parent dmatag */
|
||||
filter = NULL;
|
||||
filter_arg = NULL;
|
||||
lowaddr = BUS_SPACE_MAXADDR_24BIT;
|
||||
if (bt->model[0] == '4') {
|
||||
/*
|
||||
* This is a VL adapter. Typically, VL devices have access
|
||||
* to the full 32bit address space. On BT-445S adapters
|
||||
* prior to revision E, there is a hardware bug that causes
|
||||
* corruption of transfers to/from addresses in the range of
|
||||
* the BIOS modulo 16MB. The only properly functioning
|
||||
* BT-445S Host Adapters have firmware version 3.37.
|
||||
* If we encounter one of these adapters and the BIOS is
|
||||
* installed, install a filter function for our bus_dma_map
|
||||
* that will catch these accesses and bounce them to a safe
|
||||
* region of memory.
|
||||
*/
|
||||
if (bt->bios_addr != 0
|
||||
&& strcmp(bt->model, "445S") == 0
|
||||
&& strcmp(bt->firmware_ver, "3.37") < 0) {
|
||||
filter = btvlbouncefilter;
|
||||
filter_arg = bt;
|
||||
} else {
|
||||
lowaddr = BUS_SPACE_MAXADDR_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX Should be a child of the ISA or VL bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
|
||||
lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
|
||||
filter, filter_arg,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
||||
/* DMA tag for our sense buffers */
|
||||
if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
|
||||
/*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
bt->max_ccbs
|
||||
* sizeof(struct scsi_sense_data),
|
||||
/*nsegments*/1,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->sense_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bt->init_level++;
|
||||
|
||||
/* Allocation of sense buffers */
|
||||
if (bus_dmamem_alloc(bt->sense_dmat,
|
||||
(void **)&bt->sense_buffers,
|
||||
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bt->init_level++;
|
||||
|
||||
/* And permanently map them */
|
||||
bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
|
||||
bt->sense_buffers,
|
||||
bt->max_ccbs * sizeof(*bt->sense_buffers),
|
||||
btmapsensebuffers, bt, /*flags*/0);
|
||||
|
||||
bt->init_level++;
|
||||
}
|
||||
|
||||
return (bt_attach(bt));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
static int
|
||||
btvlbouncefilter(void *arg, bus_addr_t addr)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
|
||||
bt = (struct bt_softc *)arg;
|
||||
|
||||
addr &= BUS_SPACE_MAXADDR_24BIT;
|
||||
|
||||
if (addr == 0
|
||||
|| (addr >= bt->bios_addr
|
||||
&& addr < (bt->bios_addr + BIOS_MAP_SIZE)))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
{
|
||||
struct bt_softc* bt;
|
||||
|
||||
bt = (struct bt_softc*)arg;
|
||||
bt->sense_buffers_physbase = segs->ds_addr;
|
||||
}
|
205
sys/dev/buslogic/bt_pci.c
Normal file
205
sys/dev/buslogic/bt_pci.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT946, BT948, BT956, BT958 SCSI controllers
|
||||
*
|
||||
* Copyright (c) 1995, 1997, 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "pci.h"
|
||||
#if NPCI > 0
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#include <machine/bus_memio.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#define BT_PCI_IOADDR PCIR_MAPS
|
||||
#define BT_PCI_MEMADDR PCIR_MAPS + 4
|
||||
|
||||
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul
|
||||
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul
|
||||
#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 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
|
||||
btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
|
||||
bus_space_handle_t* bshp)
|
||||
{
|
||||
vm_offset_t vaddr;
|
||||
vm_offset_t paddr;
|
||||
u_int16_t io_port;
|
||||
int command;
|
||||
|
||||
vaddr = 0;
|
||||
paddr = 0;
|
||||
command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1);
|
||||
/* XXX Memory Mapped I/O seems to cause problems */
|
||||
#if 0
|
||||
if ((command & PCIM_CMD_MEMEN) == 0
|
||||
|| (pci_map_mem(config_id, BT_PCI_MEMADDR, &vaddr, &paddr)) == 0)
|
||||
#endif
|
||||
if ((command & PCIM_CMD_PORTEN) == 0
|
||||
|| (pci_map_port(config_id, BT_PCI_IOADDR, &io_port)) == 0)
|
||||
return (-1);
|
||||
|
||||
if (vaddr != 0) {
|
||||
*tagp = I386_BUS_SPACE_MEM;
|
||||
*bshp = vaddr;
|
||||
} else {
|
||||
*tagp = I386_BUS_SPACE_IO;
|
||||
*bshp = io_port;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char*
|
||||
bt_pci_probe (pcici_t config_id, pcidi_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
|
||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_space_tag_t tag;
|
||||
bus_space_handle_t bsh;
|
||||
pci_info_data_t pci_info;
|
||||
int error;
|
||||
u_int8_t new_addr;
|
||||
|
||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
||||
break;
|
||||
|
||||
bt = bt_alloc(BT_TEMP_UNIT, tag, bsh);
|
||||
if (bt == NULL)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Determine if an ISA compatible I/O port has been
|
||||
* enabled. If so, record the port so it will not
|
||||
* be probed by our ISA probe, and disable the port.
|
||||
*/
|
||||
error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO,
|
||||
/*param*/NULL, /*paramlen*/0,
|
||||
(u_int8_t*)&pci_info, sizeof(pci_info),
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
if (error == 0
|
||||
&& pci_info.io_port < BIO_DISABLED) {
|
||||
bt_mark_probed_bio(pci_info.io_port);
|
||||
}
|
||||
|
||||
new_addr = BIO_DISABLED;
|
||||
bt_cmd(bt, BOP_MODIFY_IO_ADDR, /*param*/&new_addr,
|
||||
/*paramlen*/1, /*reply_buf*/NULL, /*reply_len*/0,
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
bt_free(bt);
|
||||
return ("Buslogic Multimaster SCSI host adapter");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
bt_pci_attach(pcici_t config_id, int unit)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_space_tag_t tag;
|
||||
bus_space_handle_t bsh;
|
||||
int opri;
|
||||
|
||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
||||
return;
|
||||
|
||||
if ((bt = bt_alloc(unit, tag, bsh)) == NULL)
|
||||
return; /* XXX PCI code should take return status */
|
||||
|
||||
/* Allocate a dmatag for our CCB DMA maps */
|
||||
/* XXX Should be a child of the PCI bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pci_map_int(config_id, bt_intr, (void *)bt, &cam_imask)) == 0) {
|
||||
bt_free(bt);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Protect ourself from spurrious interrupts during
|
||||
* intialization and attach. We should really rely
|
||||
* on interrupts during attach, but we don't have
|
||||
* access to our interrupts during ISA probes, so until
|
||||
* that changes, we mask our interrupts during attach
|
||||
* too.
|
||||
*/
|
||||
opri = splcam();
|
||||
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
splx(opri);
|
||||
return; /* XXX PCI code should take return status */
|
||||
}
|
||||
|
||||
bt_attach(bt);
|
||||
|
||||
splx(opri);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* NPCI > 0 */
|
682
sys/dev/buslogic/btreg.h
Normal file
682
sys/dev/buslogic/btreg.h
Normal file
@ -0,0 +1,682 @@
|
||||
/*
|
||||
* Generic register and struct definitions for the BusLogic
|
||||
* MultiMaster SCSI host adapters. Product specific probe and
|
||||
* attach routines can be found in:
|
||||
* i386/isa/bt_isa.c BT-54X, BT-445 cards
|
||||
* i386/eisa/bt_eisa.c BT-74x, BT-75x cards
|
||||
* pci/bt_pci.c BT-946, BT-948, BT-956, BT-958 cards
|
||||
*
|
||||
* Copyright (c) 1998 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _BTREG_H_
|
||||
#define _BTREG_H_
|
||||
|
||||
#include "bt.h"
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define BT_MAXTRANSFER_SIZE 0xffffffff /* limited by 32bit counter */
|
||||
#define BT_NSEG 32 /* The number of dma segments supported.
|
||||
* BT_NSEG can be maxed out at 8192 entries,
|
||||
* but the kernel will never need to transfer
|
||||
* such a large request. To reduce the
|
||||
* driver's memory consumption, we reduce the
|
||||
* max to 32. 16 would work if all transfers
|
||||
* are paged alined since the kernel will only
|
||||
* generate at most a 64k transfer, but to
|
||||
* handle non-page aligned transfers, you need
|
||||
* 17, so we round to the next power of two
|
||||
* to make allocating SG space easy and
|
||||
* efficient.
|
||||
*/
|
||||
|
||||
#define ALL_TARGETS (~0)
|
||||
|
||||
/*
|
||||
* Control Register pp. 1-8, 1-9 (Write Only)
|
||||
*/
|
||||
#define CONTROL_REG 0x00
|
||||
#define HARD_RESET 0x80 /* Hard Reset - return to POST state */
|
||||
#define SOFT_RESET 0x40 /* Soft Reset - Clears Adapter state */
|
||||
#define RESET_INTR 0x20 /* Reset/Ack Interrupt */
|
||||
#define RESET_SBUS 0x10 /* Drive SCSI bus reset signal */
|
||||
|
||||
/*
|
||||
* Status Register pp. 1-9, 1-10 (Read Only)
|
||||
*/
|
||||
#define STATUS_REG 0x00
|
||||
#define DIAG_ACTIVE 0x80 /* Performing Internal Diags */
|
||||
#define DIAG_FAIL 0x40 /* Internal Diags failed */
|
||||
#define INIT_REQUIRED 0x20 /* MBOXes need initialization */
|
||||
#define HA_READY 0x10 /* HA ready for new commands */
|
||||
#define CMD_REG_BUSY 0x08 /* HA busy with last cmd byte */
|
||||
#define DATAIN_REG_READY 0x04 /* Data-in Byte available */
|
||||
#define STATUS_REG_RSVD 0x02
|
||||
#define CMD_INVALID 0x01 /* Invalid Command detected */
|
||||
|
||||
/*
|
||||
* Command/Parameter Register pp. 1-10, 1-11 (Write Only)
|
||||
*/
|
||||
#define COMMAND_REG 0x01
|
||||
|
||||
/*
|
||||
* Data in Register p. 1-11 (Read Only)
|
||||
*/
|
||||
#define DATAIN_REG 0x01
|
||||
|
||||
/*
|
||||
* Interrupt Status Register pp. 1-12 -> 1-14 (Read Only)
|
||||
*/
|
||||
#define INTSTAT_REG 0x02
|
||||
#define INTR_PENDING 0x80 /* There is a pending INTR */
|
||||
#define INTSTAT_REG_RSVD 0x70
|
||||
#define SCSI_BUS_RESET 0x08 /* Bus Reset detected */
|
||||
#define CMD_COMPLETE 0x04
|
||||
#define OMB_READY 0x02 /* Outgoin Mailbox Ready */
|
||||
#define IMB_LOADED 0x01 /* Incoming Mailbox loaded */
|
||||
|
||||
/*
|
||||
* Definitions for the "undocumented" geometry register
|
||||
*/
|
||||
typedef enum {
|
||||
GEOM_NODISK,
|
||||
GEOM_64x32,
|
||||
GEOM_128x32,
|
||||
GEOM_255x32
|
||||
} disk_geom_t;
|
||||
|
||||
#define GEOMETRY_REG 0x03
|
||||
#define DISK0_GEOMETRY 0x03
|
||||
#define DISK1_GEOMETRY 0x0c
|
||||
#define EXTENDED_TRANSLATION 0x10
|
||||
#define GEOMETRY_DISK0(g_reg) (greg & DISK0_GEOMETRY)
|
||||
#define GEOMETRY_DISK1(g_reg) ((greg & DISK1_GEOMETRY) >> 2)
|
||||
|
||||
#define BT_NREGS (4)
|
||||
/*
|
||||
* Opcodes for Adapter commands.
|
||||
* pp 1-18 -> 1-20
|
||||
*/
|
||||
typedef enum {
|
||||
BOP_TEST_CMDC_INTR = 0x00,
|
||||
BOP_INITIALIZE_24BMBOX = 0x01,
|
||||
BOP_START_MBOX = 0x02,
|
||||
BOP_EXECUTE_BIOS_CMD = 0x03,
|
||||
BOP_INQUIRE_BOARD_ID = 0x04,
|
||||
BOP_ENABLE_OMBR_INT = 0x05,
|
||||
BOP_SET_SEL_TIMOUT = 0x06,
|
||||
BOP_SET_TIME_ON_BUS = 0x07,
|
||||
BOP_SET_TIME_OFF_BUS = 0x08,
|
||||
BOP_SET_BUS_TRANS_RATE = 0x09,
|
||||
BOP_INQUIRE_INST_LDEVS = 0x0A,
|
||||
BOP_INQUIRE_CONFIG = 0x0B,
|
||||
BOP_ENABLE_TARGET_MODE = 0x0C,
|
||||
BOP_INQUIRE_SETUP_INFO = 0x0D,
|
||||
BOP_WRITE_LRAM = 0x1A,
|
||||
BOP_READ_LRAM = 0x1B,
|
||||
BOP_WRITE_CHIP_FIFO = 0x1C,
|
||||
BOP_READ_CHIP_FIFO = 0x1C,
|
||||
BOP_ECHO_DATA_BYTE = 0x1F,
|
||||
BOP_ADAPTER_DIAGNOSTICS = 0x20,
|
||||
BOP_SET_ADAPTER_OPTIONS = 0x21,
|
||||
BOP_INQUIRE_INST_HDEVS = 0x23,
|
||||
BOP_INQUIRE_TARG_DEVS = 0x24,
|
||||
BOP_DISABLE_HAC_INTR = 0x25,
|
||||
BOP_INITIALIZE_32BMBOX = 0x81,
|
||||
BOP_EXECUTE_SCSI_CMD = 0x83,
|
||||
BOP_INQUIRE_FW_VER_3DIG = 0x84,
|
||||
BOP_INQUIRE_FW_VER_4DIG = 0x85,
|
||||
BOP_INQUIRE_PCI_INFO = 0x86,
|
||||
BOP_INQUIRE_MODEL = 0x8B,
|
||||
BOP_TARG_SYNC_INFO = 0x8C,
|
||||
BOP_INQUIRE_ESETUP_INFO = 0x8D,
|
||||
BOP_ENABLE_STRICT_RR = 0x8F,
|
||||
BOP_STORE_LRAM = 0x90,
|
||||
BOP_FETCH_LRAM = 0x91,
|
||||
BOP_SAVE_TO_EEPROM = 0x92,
|
||||
BOP_UPLOAD_AUTO_SCSI = 0x94,
|
||||
BOP_MODIFY_IO_ADDR = 0x95,
|
||||
BOP_SET_CCB_FORMAT = 0x96,
|
||||
BOP_FLASH_ROM_DOWNLOAD = 0x97,
|
||||
BOP_FLASH_WRITE_ENABLE = 0x98,
|
||||
BOP_WRITE_INQ_BUFFER = 0x9A,
|
||||
BOP_READ_INQ_BUFFER = 0x9B,
|
||||
BOP_FLASH_UP_DOWNLOAD = 0xA7,
|
||||
BOP_READ_SCAM_DATA = 0xA8,
|
||||
BOP_WRITE_SCAM_DATA = 0xA9
|
||||
} bt_op_t;
|
||||
|
||||
/************** Definitions of Multi-byte commands and responses ************/
|
||||
|
||||
typedef struct {
|
||||
u_int8_t num_mboxes;
|
||||
u_int8_t base_addr[3];
|
||||
} init_24b_mbox_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t board_type;
|
||||
#define BOARD_TYPE_NON_MCA 0x41
|
||||
#define BOARD_TYPE_MCA 0x42
|
||||
u_int8_t cust_features;
|
||||
#define FEATURES_STANDARD 0x41
|
||||
u_int8_t firmware_rev_major;
|
||||
u_int8_t firmware_rev_minor;
|
||||
} board_id_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t enable;
|
||||
} enable_ombr_intr_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t enable;
|
||||
u_int8_t reserved;
|
||||
u_int8_t timeout[2]; /* timeout in milliseconds */
|
||||
} set_selto_parmas_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t time; /* time in milliseconds (2-15) */
|
||||
} set_timeon_bus_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t time; /* time in milliseconds (2-15) */
|
||||
} set_timeoff_bus_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t rate;
|
||||
} set_bus_trasfer_rate_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t targets[8];
|
||||
} installed_ldevs_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t dma_chan;
|
||||
#define DMA_CHAN_5 0x20
|
||||
#define DMA_CHAN_6 0x40
|
||||
#define DMA_CHAN_7 0x80
|
||||
u_int8_t irq;
|
||||
#define IRQ_9 0x01
|
||||
#define IRQ_10 0x02
|
||||
#define IRQ_11 0x04
|
||||
#define IRQ_12 0x08
|
||||
#define IRQ_14 0x20
|
||||
#define IRQ_15 0x40
|
||||
u_int8_t scsi_id;
|
||||
} config_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t enable;
|
||||
} target_mode_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t offset : 4,
|
||||
period : 3,
|
||||
sync : 1;
|
||||
} targ_syncinfo_t;
|
||||
|
||||
typedef enum {
|
||||
HAB_ISA = 'A',
|
||||
HAB_MCA = 'B',
|
||||
HAB_EISA = 'C',
|
||||
HAB_NUBUS = 'D',
|
||||
HAB_VESA = 'E',
|
||||
HAB_PCI = 'F'
|
||||
} ha_type_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t initiate_sync : 1,
|
||||
parity_enable : 1,
|
||||
: 6;
|
||||
|
||||
u_int8_t bus_transfer_rate;
|
||||
u_int8_t time_on_bus;
|
||||
u_int8_t time_off_bus;
|
||||
u_int8_t num_mboxes;
|
||||
u_int8_t mbox_base_addr[3];
|
||||
targ_syncinfo_t low_syncinfo[8]; /* For fast and ultra, use 8C */
|
||||
u_int8_t low_discinfo;
|
||||
u_int8_t customer_sig;
|
||||
u_int8_t letter_d;
|
||||
u_int8_t ha_type;
|
||||
u_int8_t low_wide_allowed;
|
||||
u_int8_t low_wide_active;
|
||||
targ_syncinfo_t high_syncinfo[8];
|
||||
u_int8_t high_discinfo;
|
||||
u_int8_t high_wide_allowed;
|
||||
u_int8_t high_wide_active;
|
||||
} setup_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t phys_addr[3];
|
||||
} write_adapter_lram_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t phys_addr[3];
|
||||
} read_adapter_lram_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t phys_addr[3];
|
||||
} write_chip_fifo_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t phys_addr[3];
|
||||
} read_chip_fifo_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t length; /* Excludes this member */
|
||||
u_int8_t low_disc_disable;
|
||||
u_int8_t low_busy_retry_disable;
|
||||
u_int8_t high_disc_disable;
|
||||
u_int8_t high_busy_retry_disable;
|
||||
} set_adapter_options_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t targets[8];
|
||||
} installed_hdevs_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t low_devs;
|
||||
u_int8_t high_devs;
|
||||
} target_devs_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t enable;
|
||||
} enable_hac_interrupt_params_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t num_boxes;
|
||||
u_int8_t base_addr[4];
|
||||
} init_32b_mbox_params_t;
|
||||
|
||||
typedef u_int8_t fw_ver_3dig_data_t;
|
||||
|
||||
typedef u_int8_t fw_ver_4dig_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t offset;
|
||||
u_int8_t response_len;
|
||||
} fetch_lram_params_t;
|
||||
|
||||
#define AUTO_SCSI_BYTE_OFFSET 64
|
||||
typedef struct {
|
||||
u_int8_t factory_sig[2];
|
||||
u_int8_t auto_scsi_data_size; /* 2 -> 64 bytes */
|
||||
u_int8_t model_num[6];
|
||||
u_int8_t adapter_ioport;
|
||||
u_int8_t floppy_enabled :1,
|
||||
floppy_secondary :1,
|
||||
level_trigger :1,
|
||||
:2,
|
||||
system_ram_area :3;
|
||||
u_int8_t dma_channel :7,
|
||||
dma_autoconf :1;
|
||||
u_int8_t irq_channel :7,
|
||||
irq_autoconf :1;
|
||||
u_int8_t dma_trans_rate;
|
||||
u_int8_t scsi_id;
|
||||
u_int8_t low_termination :1,
|
||||
scsi_parity :1,
|
||||
high_termination :1,
|
||||
req_ack_filter :1,
|
||||
fast_sync :1,
|
||||
bus_reset :1,
|
||||
:1,
|
||||
active_negation :1;
|
||||
u_int8_t bus_on_delay;
|
||||
u_int8_t bus_off_delay;
|
||||
u_int8_t bios_enabled :1,
|
||||
int19h_redirect :1,
|
||||
extended_trans :1,
|
||||
removable_drives :1,
|
||||
:1,
|
||||
morethan2disks :1,
|
||||
interrupt_mode :1,
|
||||
floptical_support:1;
|
||||
u_int8_t low_device_enabled;
|
||||
u_int8_t high_device_enabled;
|
||||
u_int8_t low_wide_permitted;
|
||||
u_int8_t high_wide_permitted;
|
||||
u_int8_t low_fast_permitted;
|
||||
u_int8_t high_fast_permitted;
|
||||
u_int8_t low_sync_permitted;
|
||||
u_int8_t high_sync_permitted;
|
||||
u_int8_t low_disc_permitted;
|
||||
u_int8_t high_disc_permitted;
|
||||
u_int8_t low_send_start_unit;
|
||||
u_int8_t high_send_start_unit;
|
||||
u_int8_t low_ignore_in_bios_scan;
|
||||
u_int8_t high_ignore_in_bios_scan;
|
||||
u_int8_t pci_int_pin :2,
|
||||
host_ioport :2,
|
||||
round_robin :1,
|
||||
vesa_bus_over_33 :1,
|
||||
vesa_burst_write :1,
|
||||
vesa_burst_read :1;
|
||||
u_int8_t low_ultra_permitted;
|
||||
u_int8_t high_ultra_permitted;
|
||||
u_int8_t reserved[5];
|
||||
u_int8_t auto_scsi_max_lun;
|
||||
u_int8_t :1,
|
||||
scam_dominant :1,
|
||||
scam_enabled :1,
|
||||
scam_level2 :1,
|
||||
:4;
|
||||
u_int8_t int13_extensions :1,
|
||||
:1,
|
||||
cdrom_boot :1,
|
||||
:2,
|
||||
multi_boot :1,
|
||||
:2;
|
||||
u_int8_t boot_target_id :4,
|
||||
boot_channel :4;
|
||||
u_int8_t force_dev_scan :1,
|
||||
:7;
|
||||
u_int8_t low_tagged_lun_independance;
|
||||
u_int8_t high_tagged_lun_independance;
|
||||
u_int8_t low_renegotiate_after_cc;
|
||||
u_int8_t high_renegotiate_after_cc;
|
||||
u_int8_t reserverd2[10];
|
||||
u_int8_t manufacturing_diagnotic[2];
|
||||
u_int8_t checksum[2];
|
||||
} auto_scsi_data_t;
|
||||
|
||||
struct bt_isa_port {
|
||||
u_int16_t addr;
|
||||
u_int8_t probed;
|
||||
};
|
||||
|
||||
extern struct bt_isa_port bt_isa_ports[];
|
||||
|
||||
#define BT_NUM_ISAPORTS 6
|
||||
|
||||
typedef enum {
|
||||
BIO_330 = 0,
|
||||
BIO_334 = 1,
|
||||
BIO_230 = 2,
|
||||
BIO_234 = 3,
|
||||
BIO_130 = 4,
|
||||
BIO_134 = 5,
|
||||
BIO_DISABLED = 6,
|
||||
BIO_DISABLED2 = 7
|
||||
} isa_compat_io_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t io_port;
|
||||
u_int8_t irq_num;
|
||||
u_int8_t low_byte_term :1,
|
||||
high_byte_term :1,
|
||||
:2,
|
||||
jp1_status :1,
|
||||
jp2_status :1,
|
||||
jp3_status :1,
|
||||
:1;
|
||||
u_int8_t reserved;
|
||||
} pci_info_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t ascii_model[5]; /* Fifth byte is always 0 */
|
||||
} ha_model_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t sync_rate[16]; /* Sync in 10ns units */
|
||||
} target_sync_info_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t bus_type;
|
||||
u_int8_t bios_addr;
|
||||
u_int16_t max_sg;
|
||||
u_int8_t num_mboxes;
|
||||
u_int8_t mbox_base[4];
|
||||
u_int8_t :2,
|
||||
sync_neg10MB :1,
|
||||
floppy_disable :1,
|
||||
floppy_secondary_port :1,
|
||||
burst_mode_enabled :1,
|
||||
level_trigger_ints :1,
|
||||
:1;
|
||||
u_int8_t fw_ver_bytes_2_to_4[3];
|
||||
u_int8_t wide_bus :1,
|
||||
diff_bus :1,
|
||||
scam_capable :1,
|
||||
ultra_scsi :1,
|
||||
auto_term :1,
|
||||
:3;
|
||||
} esetup_info_data_t;
|
||||
|
||||
typedef struct {
|
||||
u_int32_t len;
|
||||
u_int32_t addr;
|
||||
} bt_sg_t;
|
||||
|
||||
/********************** Mail Box definitions *******************************/
|
||||
|
||||
typedef enum {
|
||||
BMBO_FREE = 0x0, /* MBO intry is free */
|
||||
BMBO_START = 0x1, /* MBO activate entry */
|
||||
BMBO_ABORT = 0x2 /* MBO abort entry */
|
||||
} bt_mbo_action_code_t;
|
||||
|
||||
typedef struct bt_mbox_out {
|
||||
u_int32_t ccb_addr;
|
||||
u_int8_t reserved[3];
|
||||
u_int8_t action_code;
|
||||
} bt_mbox_out_t;
|
||||
|
||||
typedef enum {
|
||||
BMBI_FREE = 0x0, /* MBI entry is free */
|
||||
BMBI_OK = 0x1, /* completed without error */
|
||||
BMBI_ABORT = 0x2, /* aborted ccb */
|
||||
BMBI_NOT_FOUND = 0x3, /* Tried to abort invalid CCB */
|
||||
BMBI_ERROR = 0x4 /* Completed with error */
|
||||
} bt_mbi_comp_code_t;
|
||||
|
||||
typedef struct bt_mbox_in {
|
||||
u_int32_t ccb_addr;
|
||||
u_int8_t btstat;
|
||||
u_int8_t sdstat;
|
||||
u_int8_t reserved;
|
||||
u_int8_t comp_code;
|
||||
} bt_mbox_in_t;
|
||||
|
||||
/****************** Hardware CCB definition *********************************/
|
||||
typedef enum {
|
||||
INITIATOR_CCB = 0x00,
|
||||
INITIATOR_SG_CCB = 0x02,
|
||||
INITIATOR_CCB_WRESID = 0x03,
|
||||
INITIATOR_SG_CCB_WRESID = 0x04,
|
||||
INITIATOR_BUS_DEV_RESET = 0x81
|
||||
} bt_ccb_opcode_t;
|
||||
|
||||
typedef enum {
|
||||
BTSTAT_NOERROR = 0x00,
|
||||
BTSTAT_LINKED_CMD_COMPLETE = 0x0A,
|
||||
BTSTAT_LINKED_CMD_FLAG_COMPLETE = 0x0B,
|
||||
BTSTAT_DATAUNDERUN_ERROR = 0x0C,
|
||||
BTSTAT_SELTIMEOUT = 0x11,
|
||||
BTSTAT_DATARUN_ERROR = 0x12,
|
||||
BTSTAT_UNEXPECTED_BUSFREE = 0x13,
|
||||
BTSTAT_INVALID_PHASE = 0x14,
|
||||
BTSTAT_INVALID_ACTION_CODE = 0x15,
|
||||
BTSTAT_INVALID_OPCODE = 0x16,
|
||||
BTSTAT_LINKED_CCB_LUN_MISMATCH = 0x17,
|
||||
BTSTAT_INVALID_CCB_OR_SG_PARAM = 0x1A,
|
||||
BTSTAT_AUTOSENSE_FAILED = 0x1B,
|
||||
BTSTAT_TAGGED_MSG_REJECTED = 0x1C,
|
||||
BTSTAT_UNSUPPORTED_MSG_RECEIVED = 0x1D,
|
||||
BTSTAT_HARDWARE_FAILURE = 0x20,
|
||||
BTSTAT_TARGET_IGNORED_ATN = 0x21,
|
||||
BTSTAT_HA_SCSI_BUS_RESET = 0x22,
|
||||
BTSTAT_OTHER_SCSI_BUS_RESET = 0x23,
|
||||
BTSTAT_INVALID_RECONNECT = 0x24,
|
||||
BTSTAT_HA_BDR = 0x25,
|
||||
BTSTAT_ABORT_QUEUE_GENERATED = 0x26,
|
||||
BTSTAT_HA_SOFTWARE_ERROR = 0x27,
|
||||
BTSTAT_HA_WATCHDOG_ERROR = 0x28,
|
||||
BTSTAT_SCSI_PERROR_DETECTED = 0x30
|
||||
} btstat_t;
|
||||
|
||||
struct bt_hccb {
|
||||
u_int8_t opcode;
|
||||
u_int8_t :3,
|
||||
datain :1,
|
||||
dataout :1,
|
||||
wide_tag_enable :1, /* Wide Lun CCB format */
|
||||
wide_tag_type :2; /* Wide Lun CCB format */
|
||||
u_int8_t cmd_len;
|
||||
u_int8_t sense_len;
|
||||
u_int32_t data_len;
|
||||
u_int32_t data_addr;
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t btstat;
|
||||
u_int8_t sdstat;
|
||||
u_int8_t target_id;
|
||||
u_int8_t target_lun :5,
|
||||
tag_enable :1,
|
||||
tag_type :2;
|
||||
u_int8_t scsi_cdb[12];
|
||||
u_int8_t reserved2[6];
|
||||
u_int32_t sense_addr;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
BCCB_FREE = 0x0,
|
||||
BCCB_ACTIVE = 0x1,
|
||||
BCCB_DEVICE_RESET = 0x2,
|
||||
BCCB_RELEASE_SIMQ = 0x4
|
||||
} bccb_flags_t;
|
||||
|
||||
struct bt_ccb {
|
||||
struct bt_hccb hccb;
|
||||
SLIST_ENTRY(bt_ccb) links;
|
||||
u_int32_t flags;
|
||||
union ccb *ccb;
|
||||
bus_dmamap_t dmamap;
|
||||
bt_sg_t *sg_list;
|
||||
u_int32_t sg_list_phys;
|
||||
};
|
||||
|
||||
struct sg_map_node {
|
||||
bus_dmamap_t sg_dmamap;
|
||||
bus_addr_t sg_physaddr;
|
||||
bt_sg_t* sg_vaddr;
|
||||
SLIST_ENTRY(sg_map_node) links;
|
||||
};
|
||||
|
||||
struct bt_softc {
|
||||
bus_space_tag_t tag;
|
||||
bus_space_handle_t bsh;
|
||||
struct cam_sim *sim;
|
||||
struct cam_path *path;
|
||||
bt_mbox_out_t *cur_outbox;
|
||||
bt_mbox_in_t *cur_inbox;
|
||||
bt_mbox_out_t *last_outbox;
|
||||
bt_mbox_in_t *last_inbox;
|
||||
struct bt_ccb *bt_ccb_array;
|
||||
SLIST_HEAD(,bt_ccb) free_bt_ccbs;
|
||||
LIST_HEAD(,ccb_hdr) pending_ccbs;
|
||||
u_int32_t bt_ccb_physbase;
|
||||
bt_mbox_in_t *in_boxes;
|
||||
bt_mbox_out_t *out_boxes;
|
||||
struct scsi_sense_data *sense_buffers;
|
||||
u_int32_t sense_buffers_physbase;
|
||||
struct bt_ccb *recovery_bccb;
|
||||
u_int num_boxes;
|
||||
bus_dma_tag_t parent_dmat; /*
|
||||
* All dmat's derive from
|
||||
* the dmat defined by our
|
||||
* bus.
|
||||
*/
|
||||
bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */
|
||||
bus_dma_tag_t mailbox_dmat; /* dmat for our mailboxes */
|
||||
bus_dmamap_t mailbox_dmamap;
|
||||
bus_dma_tag_t ccb_dmat; /* dmat for our ccb array */
|
||||
bus_dmamap_t ccb_dmamap;
|
||||
bus_dma_tag_t sg_dmat; /* dmat for our sg maps */
|
||||
bus_dma_tag_t sense_dmat; /* dmat for our sg maps */
|
||||
bus_dmamap_t sense_dmamap;
|
||||
SLIST_HEAD(, sg_map_node) sg_maps;
|
||||
bus_addr_t mailbox_physbase;
|
||||
u_int num_ccbs; /* Number of CCBs malloc'd */
|
||||
u_int max_ccbs; /* Maximum allocatable CCBs */
|
||||
u_int max_sg;
|
||||
u_int unit;
|
||||
u_int scsi_id;
|
||||
u_int32_t extended_trans :1,
|
||||
wide_bus :1,
|
||||
diff_bus :1,
|
||||
ultra_scsi :1,
|
||||
extended_lun :1,
|
||||
strict_rr :1,
|
||||
tag_capable :1,
|
||||
wide_lun_ccb :1,
|
||||
resource_shortage:1,
|
||||
:23;
|
||||
u_int16_t tags_permitted;
|
||||
u_int16_t disc_permitted;
|
||||
u_int16_t sync_permitted;
|
||||
u_int16_t fast_permitted;
|
||||
u_int16_t ultra_permitted;
|
||||
u_int16_t wide_permitted;
|
||||
u_int8_t init_level;
|
||||
volatile u_int8_t command_cmp;
|
||||
volatile u_int8_t latched_status;
|
||||
u_int32_t bios_addr;
|
||||
char firmware_ver[6];
|
||||
char model[5];
|
||||
};
|
||||
|
||||
extern struct bt_softc *bt_softcs[]; /* XXX Config should handle this */
|
||||
extern u_long bt_unit;
|
||||
|
||||
#define BT_TEMP_UNIT 0xFF /* Unit for probes */
|
||||
struct bt_softc* bt_alloc(int unit, bus_space_tag_t tag,
|
||||
bus_space_handle_t bsh);
|
||||
void bt_free(struct bt_softc *bt);
|
||||
int bt_probe(struct bt_softc *bt);
|
||||
int bt_fetch_adapter_info(struct bt_softc *bt);
|
||||
int bt_init(struct bt_softc *bt);
|
||||
int bt_attach(struct bt_softc *bt);
|
||||
void bt_intr(void *arg);
|
||||
char * bt_name(struct bt_softc *bt);
|
||||
int bt_check_probed_iop(u_int ioport);
|
||||
void bt_mark_probed_bio(isa_compat_io_t port);
|
||||
void bt_mark_probed_iop(u_int ioport);
|
||||
|
||||
#define DEFAULT_CMD_TIMEOUT 10000 /* 1 sec */
|
||||
int bt_cmd(struct bt_softc *bt, bt_op_t opcode,
|
||||
u_int8_t *params, u_int param_len,
|
||||
u_int8_t *reply_data, u_int reply_len,
|
||||
u_int cmd_timeout);
|
||||
|
||||
#define bt_inb(bt, port) \
|
||||
bus_space_read_1((bt)->tag, (bt)->bsh, port)
|
||||
|
||||
#define bt_outb(bt, port, value) \
|
||||
bus_space_write_1((bt)->tag, (bt)->bsh, port, value)
|
||||
|
||||
#endif /* _BT_H_ */
|
392
sys/i386/eisa/bt_eisa.c
Normal file
392
sys/i386/eisa/bt_eisa.c
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT74x SCSI controllers
|
||||
*
|
||||
* Copyright (c) 1995, 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice immediately at the beginning of the file, without modification,
|
||||
* this list of conditions, and the following disclaimer.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "eisa.h"
|
||||
#if NEISA > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <i386/eisa/eisaconf.h>
|
||||
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#define EISA_DEVICE_ID_BUSLOGIC_74X_B 0x0ab34201
|
||||
#define EISA_DEVICE_ID_BUSLOGIC_74X_C 0x0ab34202
|
||||
#define EISA_DEVICE_ID_SDC3222F 0x0ab34781
|
||||
#define EISA_DEVICE_ID_AMI_4801 0x05a94801
|
||||
|
||||
#define BT_IOSIZE 0x04 /* Move to central header */
|
||||
#define BT_EISA_IOSIZE 0x100
|
||||
#define BT_EISA_SLOT_OFFSET 0xc00
|
||||
|
||||
#define EISA_IOCONF 0x08C
|
||||
#define PORTADDR 0x07
|
||||
#define PORT_330 0x00
|
||||
#define PORT_334 0x01
|
||||
#define PORT_230 0x02
|
||||
#define PORT_234 0x03
|
||||
#define PORT_130 0x04
|
||||
#define PORT_134 0x05
|
||||
#define IRQ_CHANNEL 0xe0
|
||||
#define INT_11 0x40
|
||||
#define INT_10 0x20
|
||||
#define INT_15 0xa0
|
||||
#define INT_12 0x60
|
||||
#define INT_14 0x80
|
||||
#define INT_9 0x00
|
||||
|
||||
#define EISA_IRQ_TYPE 0x08D
|
||||
#define LEVEL 0x40
|
||||
|
||||
/* Definitions for the AMI Series 48 controler */
|
||||
#define AMI_EISA_IOSIZE 0x500 /* Two separate ranges?? */
|
||||
#define AMI_EISA_SLOT_OFFSET 0x800
|
||||
#define AMI_EISA_IOCONF 0x000
|
||||
#define AMI_DMA_CHANNEL 0x03
|
||||
#define AMI_IRQ_CHANNEL 0x1c
|
||||
#define AMI_INT_15 0x14
|
||||
#define AMI_INT_14 0x10
|
||||
#define AMI_INT_12 0x0c
|
||||
#define AMI_INT_11 0x00
|
||||
#define AMI_INT_10 0x08
|
||||
#define AMI_INT_9 0x04
|
||||
#define AMI_BIOS_ADDR 0xe0
|
||||
|
||||
#define AMI_EISA_IOCONF1 0x001
|
||||
#define AMI_PORTADDR 0x0e
|
||||
#define AMI_PORT_334 0x08
|
||||
#define AMI_PORT_330 0x00
|
||||
#define AMI_PORT_234 0x0c
|
||||
#define AMI_PORT_230 0x04
|
||||
#define AMI_PORT_134 0x0a
|
||||
#define AMI_PORT_130 0x02
|
||||
#define AMI_IRQ_LEVEL 0x01
|
||||
|
||||
|
||||
#define AMI_MISC2_OPTIONS 0x49E
|
||||
#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)
|
||||
{
|
||||
switch(type) {
|
||||
case EISA_DEVICE_ID_BUSLOGIC_74X_B:
|
||||
return ("Buslogic 74xB SCSI host adapter");
|
||||
break;
|
||||
case EISA_DEVICE_ID_BUSLOGIC_74X_C:
|
||||
return ("Buslogic 74xC SCSI host adapter");
|
||||
break;
|
||||
case EISA_DEVICE_ID_SDC3222F:
|
||||
return ("Storage Dimensions SDC3222F SCSI host adapter");
|
||||
break;
|
||||
case EISA_DEVICE_ID_AMI_4801:
|
||||
return ("AMI Series 48 SCSI host adapter");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
bt_eisa_probe(void)
|
||||
{
|
||||
u_long iobase;
|
||||
struct eisa_device *e_dev = NULL;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
while ((e_dev = eisa_match_dev(e_dev, bt_match))) {
|
||||
u_char ioconf;
|
||||
u_long port;
|
||||
int irq;
|
||||
|
||||
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
|
||||
if (e_dev->id == EISA_DEVICE_ID_AMI_4801) {
|
||||
u_char ioconf1;
|
||||
iobase += AMI_EISA_SLOT_OFFSET;
|
||||
|
||||
eisa_add_iospace(e_dev, iobase, AMI_EISA_IOSIZE,
|
||||
RESVADDR_NONE);
|
||||
|
||||
ioconf = inb(iobase + AMI_EISA_IOCONF);
|
||||
ioconf1 = inb(iobase + AMI_EISA_IOCONF1);
|
||||
/* Determine "ISA" I/O port */
|
||||
switch (ioconf1 & AMI_PORTADDR) {
|
||||
case AMI_PORT_330:
|
||||
port = 0x330;
|
||||
break;
|
||||
case AMI_PORT_334:
|
||||
port = 0x334;
|
||||
break;
|
||||
case AMI_PORT_230:
|
||||
port = 0x230;
|
||||
break;
|
||||
case AMI_PORT_234:
|
||||
port = 0x234;
|
||||
break;
|
||||
case AMI_PORT_134:
|
||||
port = 0x134;
|
||||
break;
|
||||
case AMI_PORT_130:
|
||||
port = 0x130;
|
||||
break;
|
||||
default:
|
||||
/* Disabled */
|
||||
printf("bt: AMI EISA Adapter at "
|
||||
"slot %d has a disabled I/O "
|
||||
"port. Cannot attach.\n",
|
||||
e_dev->ioconf.slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine our IRQ */
|
||||
switch (ioconf & AMI_IRQ_CHANNEL) {
|
||||
case AMI_INT_11:
|
||||
irq = 11;
|
||||
break;
|
||||
case AMI_INT_10:
|
||||
irq = 10;
|
||||
break;
|
||||
case AMI_INT_15:
|
||||
irq = 15;
|
||||
break;
|
||||
case AMI_INT_12:
|
||||
irq = 12;
|
||||
break;
|
||||
case AMI_INT_14:
|
||||
irq = 14;
|
||||
break;
|
||||
case AMI_INT_9:
|
||||
irq = 9;
|
||||
break;
|
||||
default:
|
||||
/* Disabled */
|
||||
printf("bt: AMI EISA Adapter at "
|
||||
"slot %d has its IRQ disabled. "
|
||||
"Cannot attach.\n",
|
||||
e_dev->ioconf.slot);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
iobase += BT_EISA_SLOT_OFFSET;
|
||||
|
||||
eisa_add_iospace(e_dev, iobase, BT_EISA_IOSIZE,
|
||||
RESVADDR_NONE);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Determine our IRQ */
|
||||
switch (ioconf & IRQ_CHANNEL) {
|
||||
case INT_11:
|
||||
irq = 11;
|
||||
break;
|
||||
case INT_10:
|
||||
irq = 10;
|
||||
break;
|
||||
case INT_15:
|
||||
irq = 15;
|
||||
break;
|
||||
case INT_12:
|
||||
irq = 12;
|
||||
break;
|
||||
case INT_14:
|
||||
irq = 14;
|
||||
break;
|
||||
case INT_9:
|
||||
irq = 9;
|
||||
break;
|
||||
default:
|
||||
/* Disabled */
|
||||
printf("bt: Buslogic EISA Adapter at "
|
||||
"slot %d has its IRQ disabled. "
|
||||
"Cannot attach.\n",
|
||||
e_dev->ioconf.slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
bt_mark_probed_iop(port);
|
||||
eisa_add_iospace(e_dev, port, BT_IOSIZE, RESVADDR_NONE);
|
||||
eisa_add_intr(e_dev, irq);
|
||||
|
||||
eisa_registerdev(e_dev, &bt_eisa_driver);
|
||||
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
bt_eisa_attach(struct eisa_device *e_dev)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
int unit = e_dev->unit;
|
||||
int irq;
|
||||
resvaddr_t *ioport;
|
||||
resvaddr_t *eisa_ioport;
|
||||
u_char level_intr;
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
if (e_dev->id == EISA_DEVICE_ID_AMI_4801) {
|
||||
level_intr = inb(eisa_ioport->addr + AMI_EISA_IOCONF1)
|
||||
& AMI_IRQ_LEVEL;
|
||||
} else {
|
||||
level_intr = inb(eisa_ioport->addr + EISA_IRQ_TYPE)
|
||||
& LEVEL;
|
||||
}
|
||||
|
||||
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 */
|
||||
/* XXX Should be a child of the PCI bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/0, /*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (eisa_reg_intr(e_dev, irq, bt_intr, (void *)bt, &cam_imask,
|
||||
/*shared ==*/level_intr)) {
|
||||
bt_free(bt);
|
||||
return -1;
|
||||
}
|
||||
eisa_reg_end(e_dev);
|
||||
|
||||
/*
|
||||
* Now that we know we own the resources we need, do the full
|
||||
* card initialization.
|
||||
*/
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* Attach sub-devices - always succeeds */
|
||||
bt_attach(bt);
|
||||
|
||||
if (eisa_enable_intr(e_dev, irq)) {
|
||||
bt_free(bt);
|
||||
eisa_release_intr(e_dev, irq, bt_intr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* NEISA > 0 */
|
322
sys/i386/isa/bt_isa.c
Normal file
322
sys/i386/isa/bt_isa.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT-54X and BT-445 cards
|
||||
*
|
||||
* Copyright (c) 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
#include "ioconf.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_dmamap_callback_t btmapsensebuffers;
|
||||
|
||||
struct isa_driver btdriver =
|
||||
{
|
||||
bt_isa_probe,
|
||||
bt_isa_attach,
|
||||
"bt"
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if the device can be found at the port given
|
||||
* and if so, set it up ready for further work
|
||||
* as an argument, takes the isa_device structure from
|
||||
* autoconf.c
|
||||
*/
|
||||
static int
|
||||
bt_isa_probe(dev)
|
||||
struct isa_device *dev;
|
||||
{
|
||||
/*
|
||||
* find unit and check we have that many defined
|
||||
*/
|
||||
struct bt_softc *bt;
|
||||
int 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;
|
||||
max_port_index = BT_NUM_ISAPORTS - 1;
|
||||
/*
|
||||
* Bound our board search if the user has
|
||||
* specified an exact port.
|
||||
*/
|
||||
if (dev->id_iobase > 0) {
|
||||
for (;port_index <= max_port_index; port_index++)
|
||||
if (dev->id_iobase >= bt_isa_ports[port_index].addr)
|
||||
break;
|
||||
if ((port_index > max_port_index)
|
||||
|| (dev->id_iobase != bt_isa_ports[port_index].addr)) {
|
||||
printf("
|
||||
bt_isa_probe: Invalid baseport of 0x%x specified.
|
||||
bt_isa_probe: Nearest valid baseport is 0x%x.
|
||||
bt_isa_probe: Failing probe.\n",
|
||||
dev->id_iobase,
|
||||
(port_index <= max_port_index)
|
||||
? bt_isa_ports[port_index].addr
|
||||
: bt_isa_ports[max_port_index].addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to find an adapter */
|
||||
for (;port_index <= max_port_index; port_index++) {
|
||||
config_data_t config_data;
|
||||
u_int ioport;
|
||||
int error;
|
||||
|
||||
ioport = bt_isa_ports[port_index].addr;
|
||||
|
||||
/*
|
||||
* Ensure this port has not already been claimed already
|
||||
* by a PCI or EISA adapter.
|
||||
*/
|
||||
if (bt_check_probed_iop(ioport) != 0)
|
||||
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 */
|
||||
bt_mark_probed_bio(port_index);
|
||||
|
||||
/* See if there is really a card present */
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
|
||||
bt_free(bt);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine our IRQ, and DMA settings and
|
||||
* export them to the configuration system.
|
||||
*/
|
||||
error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
|
||||
(u_int8_t*)&config_data, sizeof(config_data),
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
if (error != 0) {
|
||||
printf("bt_isa_probe: Could not determine IRQ or DMA "
|
||||
"settings for adapter at 0x%x. Failing probe\n",
|
||||
ioport);
|
||||
bt_free(bt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bt->model[0] == '5') {
|
||||
/* DMA settings only make sense for ISA cards */
|
||||
switch (config_data.dma_chan) {
|
||||
case DMA_CHAN_5:
|
||||
dev->id_drq = 5;
|
||||
break;
|
||||
case DMA_CHAN_6:
|
||||
dev->id_drq = 6;
|
||||
break;
|
||||
case DMA_CHAN_7:
|
||||
dev->id_drq = 7;
|
||||
break;
|
||||
default:
|
||||
printf("bt_isa_probe: Invalid DMA setting "
|
||||
"detected for adapter at 0x%x. "
|
||||
"Failing probe\n", ioport);
|
||||
}
|
||||
} else {
|
||||
/* VL DMA */
|
||||
dev->id_drq = -1;
|
||||
}
|
||||
dev->id_iobase = bt_isa_ports[port_index].addr;
|
||||
dev->id_irq = (config_data.irq << 9);
|
||||
dev->id_intr = bt_isa_intr;
|
||||
bt_unit++;
|
||||
return (BT_NREGS);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach all the sub-devices we can find
|
||||
*/
|
||||
static int
|
||||
bt_isa_attach(dev)
|
||||
struct isa_device *dev;
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_dma_filter_t *filter;
|
||||
void *filter_arg;
|
||||
bus_addr_t lowaddr;
|
||||
|
||||
bt = bt_softcs[dev->id_unit];
|
||||
if (dev->id_drq != -1)
|
||||
isa_dmacascade(dev->id_drq);
|
||||
|
||||
/* Allocate our parent dmatag */
|
||||
filter = NULL;
|
||||
filter_arg = NULL;
|
||||
lowaddr = BUS_SPACE_MAXADDR_24BIT;
|
||||
if (bt->model[0] == '4') {
|
||||
/*
|
||||
* This is a VL adapter. Typically, VL devices have access
|
||||
* to the full 32bit address space. On BT-445S adapters
|
||||
* prior to revision E, there is a hardware bug that causes
|
||||
* corruption of transfers to/from addresses in the range of
|
||||
* the BIOS modulo 16MB. The only properly functioning
|
||||
* BT-445S Host Adapters have firmware version 3.37.
|
||||
* If we encounter one of these adapters and the BIOS is
|
||||
* installed, install a filter function for our bus_dma_map
|
||||
* that will catch these accesses and bounce them to a safe
|
||||
* region of memory.
|
||||
*/
|
||||
if (bt->bios_addr != 0
|
||||
&& strcmp(bt->model, "445S") == 0
|
||||
&& strcmp(bt->firmware_ver, "3.37") < 0) {
|
||||
filter = btvlbouncefilter;
|
||||
filter_arg = bt;
|
||||
} else {
|
||||
lowaddr = BUS_SPACE_MAXADDR_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX Should be a child of the ISA or VL bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
|
||||
lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
|
||||
filter, filter_arg,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
||||
/* DMA tag for our sense buffers */
|
||||
if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
|
||||
/*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
bt->max_ccbs
|
||||
* sizeof(struct scsi_sense_data),
|
||||
/*nsegments*/1,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->sense_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bt->init_level++;
|
||||
|
||||
/* Allocation of sense buffers */
|
||||
if (bus_dmamem_alloc(bt->sense_dmat,
|
||||
(void **)&bt->sense_buffers,
|
||||
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bt->init_level++;
|
||||
|
||||
/* And permanently map them */
|
||||
bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
|
||||
bt->sense_buffers,
|
||||
bt->max_ccbs * sizeof(*bt->sense_buffers),
|
||||
btmapsensebuffers, bt, /*flags*/0);
|
||||
|
||||
bt->init_level++;
|
||||
}
|
||||
|
||||
return (bt_attach(bt));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
static int
|
||||
btvlbouncefilter(void *arg, bus_addr_t addr)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
|
||||
bt = (struct bt_softc *)arg;
|
||||
|
||||
addr &= BUS_SPACE_MAXADDR_24BIT;
|
||||
|
||||
if (addr == 0
|
||||
|| (addr >= bt->bios_addr
|
||||
&& addr < (bt->bios_addr + BIOS_MAP_SIZE)))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
{
|
||||
struct bt_softc* bt;
|
||||
|
||||
bt = (struct bt_softc*)arg;
|
||||
bt->sense_buffers_physbase = segs->ds_addr;
|
||||
}
|
322
sys/isa/bt_isa.c
Normal file
322
sys/isa/bt_isa.c
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT-54X and BT-445 cards
|
||||
*
|
||||
* Copyright (c) 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
#include "ioconf.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_dmamap_callback_t btmapsensebuffers;
|
||||
|
||||
struct isa_driver btdriver =
|
||||
{
|
||||
bt_isa_probe,
|
||||
bt_isa_attach,
|
||||
"bt"
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if the device can be found at the port given
|
||||
* and if so, set it up ready for further work
|
||||
* as an argument, takes the isa_device structure from
|
||||
* autoconf.c
|
||||
*/
|
||||
static int
|
||||
bt_isa_probe(dev)
|
||||
struct isa_device *dev;
|
||||
{
|
||||
/*
|
||||
* find unit and check we have that many defined
|
||||
*/
|
||||
struct bt_softc *bt;
|
||||
int 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;
|
||||
max_port_index = BT_NUM_ISAPORTS - 1;
|
||||
/*
|
||||
* Bound our board search if the user has
|
||||
* specified an exact port.
|
||||
*/
|
||||
if (dev->id_iobase > 0) {
|
||||
for (;port_index <= max_port_index; port_index++)
|
||||
if (dev->id_iobase >= bt_isa_ports[port_index].addr)
|
||||
break;
|
||||
if ((port_index > max_port_index)
|
||||
|| (dev->id_iobase != bt_isa_ports[port_index].addr)) {
|
||||
printf("
|
||||
bt_isa_probe: Invalid baseport of 0x%x specified.
|
||||
bt_isa_probe: Nearest valid baseport is 0x%x.
|
||||
bt_isa_probe: Failing probe.\n",
|
||||
dev->id_iobase,
|
||||
(port_index <= max_port_index)
|
||||
? bt_isa_ports[port_index].addr
|
||||
: bt_isa_ports[max_port_index].addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to find an adapter */
|
||||
for (;port_index <= max_port_index; port_index++) {
|
||||
config_data_t config_data;
|
||||
u_int ioport;
|
||||
int error;
|
||||
|
||||
ioport = bt_isa_ports[port_index].addr;
|
||||
|
||||
/*
|
||||
* Ensure this port has not already been claimed already
|
||||
* by a PCI or EISA adapter.
|
||||
*/
|
||||
if (bt_check_probed_iop(ioport) != 0)
|
||||
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 */
|
||||
bt_mark_probed_bio(port_index);
|
||||
|
||||
/* See if there is really a card present */
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
|
||||
bt_free(bt);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine our IRQ, and DMA settings and
|
||||
* export them to the configuration system.
|
||||
*/
|
||||
error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
|
||||
(u_int8_t*)&config_data, sizeof(config_data),
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
if (error != 0) {
|
||||
printf("bt_isa_probe: Could not determine IRQ or DMA "
|
||||
"settings for adapter at 0x%x. Failing probe\n",
|
||||
ioport);
|
||||
bt_free(bt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bt->model[0] == '5') {
|
||||
/* DMA settings only make sense for ISA cards */
|
||||
switch (config_data.dma_chan) {
|
||||
case DMA_CHAN_5:
|
||||
dev->id_drq = 5;
|
||||
break;
|
||||
case DMA_CHAN_6:
|
||||
dev->id_drq = 6;
|
||||
break;
|
||||
case DMA_CHAN_7:
|
||||
dev->id_drq = 7;
|
||||
break;
|
||||
default:
|
||||
printf("bt_isa_probe: Invalid DMA setting "
|
||||
"detected for adapter at 0x%x. "
|
||||
"Failing probe\n", ioport);
|
||||
}
|
||||
} else {
|
||||
/* VL DMA */
|
||||
dev->id_drq = -1;
|
||||
}
|
||||
dev->id_iobase = bt_isa_ports[port_index].addr;
|
||||
dev->id_irq = (config_data.irq << 9);
|
||||
dev->id_intr = bt_isa_intr;
|
||||
bt_unit++;
|
||||
return (BT_NREGS);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach all the sub-devices we can find
|
||||
*/
|
||||
static int
|
||||
bt_isa_attach(dev)
|
||||
struct isa_device *dev;
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_dma_filter_t *filter;
|
||||
void *filter_arg;
|
||||
bus_addr_t lowaddr;
|
||||
|
||||
bt = bt_softcs[dev->id_unit];
|
||||
if (dev->id_drq != -1)
|
||||
isa_dmacascade(dev->id_drq);
|
||||
|
||||
/* Allocate our parent dmatag */
|
||||
filter = NULL;
|
||||
filter_arg = NULL;
|
||||
lowaddr = BUS_SPACE_MAXADDR_24BIT;
|
||||
if (bt->model[0] == '4') {
|
||||
/*
|
||||
* This is a VL adapter. Typically, VL devices have access
|
||||
* to the full 32bit address space. On BT-445S adapters
|
||||
* prior to revision E, there is a hardware bug that causes
|
||||
* corruption of transfers to/from addresses in the range of
|
||||
* the BIOS modulo 16MB. The only properly functioning
|
||||
* BT-445S Host Adapters have firmware version 3.37.
|
||||
* If we encounter one of these adapters and the BIOS is
|
||||
* installed, install a filter function for our bus_dma_map
|
||||
* that will catch these accesses and bounce them to a safe
|
||||
* region of memory.
|
||||
*/
|
||||
if (bt->bios_addr != 0
|
||||
&& strcmp(bt->model, "445S") == 0
|
||||
&& strcmp(bt->firmware_ver, "3.37") < 0) {
|
||||
filter = btvlbouncefilter;
|
||||
filter_arg = bt;
|
||||
} else {
|
||||
lowaddr = BUS_SPACE_MAXADDR_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX Should be a child of the ISA or VL bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
|
||||
lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
|
||||
filter, filter_arg,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
|
||||
/* DMA tag for our sense buffers */
|
||||
if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
|
||||
/*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
bt->max_ccbs
|
||||
* sizeof(struct scsi_sense_data),
|
||||
/*nsegments*/1,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->sense_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bt->init_level++;
|
||||
|
||||
/* Allocation of sense buffers */
|
||||
if (bus_dmamem_alloc(bt->sense_dmat,
|
||||
(void **)&bt->sense_buffers,
|
||||
BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
|
||||
bt_free(bt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bt->init_level++;
|
||||
|
||||
/* And permanently map them */
|
||||
bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
|
||||
bt->sense_buffers,
|
||||
bt->max_ccbs * sizeof(*bt->sense_buffers),
|
||||
btmapsensebuffers, bt, /*flags*/0);
|
||||
|
||||
bt->init_level++;
|
||||
}
|
||||
|
||||
return (bt_attach(bt));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
static int
|
||||
btvlbouncefilter(void *arg, bus_addr_t addr)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
|
||||
bt = (struct bt_softc *)arg;
|
||||
|
||||
addr &= BUS_SPACE_MAXADDR_24BIT;
|
||||
|
||||
if (addr == 0
|
||||
|| (addr >= bt->bios_addr
|
||||
&& addr < (bt->bios_addr + BIOS_MAP_SIZE)))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
{
|
||||
struct bt_softc* bt;
|
||||
|
||||
bt = (struct bt_softc*)arg;
|
||||
bt->sense_buffers_physbase = segs->ds_addr;
|
||||
}
|
205
sys/pci/bt_pci.c
Normal file
205
sys/pci/bt_pci.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Product specific probe and attach routines for:
|
||||
* Buslogic BT946, BT948, BT956, BT958 SCSI controllers
|
||||
*
|
||||
* Copyright (c) 1995, 1997, 1998 Justin T. Gibbs
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "pci.h"
|
||||
#if NPCI > 0
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#include <machine/bus_memio.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/buslogic/btreg.h>
|
||||
|
||||
#define BT_PCI_IOADDR PCIR_MAPS
|
||||
#define BT_PCI_MEMADDR PCIR_MAPS + 4
|
||||
|
||||
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul
|
||||
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul
|
||||
#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 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
|
||||
btpcideterminebusspace(pcici_t config_id, bus_space_tag_t* tagp,
|
||||
bus_space_handle_t* bshp)
|
||||
{
|
||||
vm_offset_t vaddr;
|
||||
vm_offset_t paddr;
|
||||
u_int16_t io_port;
|
||||
int command;
|
||||
|
||||
vaddr = 0;
|
||||
paddr = 0;
|
||||
command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1);
|
||||
/* XXX Memory Mapped I/O seems to cause problems */
|
||||
#if 0
|
||||
if ((command & PCIM_CMD_MEMEN) == 0
|
||||
|| (pci_map_mem(config_id, BT_PCI_MEMADDR, &vaddr, &paddr)) == 0)
|
||||
#endif
|
||||
if ((command & PCIM_CMD_PORTEN) == 0
|
||||
|| (pci_map_port(config_id, BT_PCI_IOADDR, &io_port)) == 0)
|
||||
return (-1);
|
||||
|
||||
if (vaddr != 0) {
|
||||
*tagp = I386_BUS_SPACE_MEM;
|
||||
*bshp = vaddr;
|
||||
} else {
|
||||
*tagp = I386_BUS_SPACE_IO;
|
||||
*bshp = io_port;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char*
|
||||
bt_pci_probe (pcici_t config_id, pcidi_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER:
|
||||
case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC:
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_space_tag_t tag;
|
||||
bus_space_handle_t bsh;
|
||||
pci_info_data_t pci_info;
|
||||
int error;
|
||||
u_int8_t new_addr;
|
||||
|
||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
||||
break;
|
||||
|
||||
bt = bt_alloc(BT_TEMP_UNIT, tag, bsh);
|
||||
if (bt == NULL)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Determine if an ISA compatible I/O port has been
|
||||
* enabled. If so, record the port so it will not
|
||||
* be probed by our ISA probe, and disable the port.
|
||||
*/
|
||||
error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO,
|
||||
/*param*/NULL, /*paramlen*/0,
|
||||
(u_int8_t*)&pci_info, sizeof(pci_info),
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
if (error == 0
|
||||
&& pci_info.io_port < BIO_DISABLED) {
|
||||
bt_mark_probed_bio(pci_info.io_port);
|
||||
}
|
||||
|
||||
new_addr = BIO_DISABLED;
|
||||
bt_cmd(bt, BOP_MODIFY_IO_ADDR, /*param*/&new_addr,
|
||||
/*paramlen*/1, /*reply_buf*/NULL, /*reply_len*/0,
|
||||
DEFAULT_CMD_TIMEOUT);
|
||||
bt_free(bt);
|
||||
return ("Buslogic Multimaster SCSI host adapter");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
bt_pci_attach(pcici_t config_id, int unit)
|
||||
{
|
||||
struct bt_softc *bt;
|
||||
bus_space_tag_t tag;
|
||||
bus_space_handle_t bsh;
|
||||
int opri;
|
||||
|
||||
if (btpcideterminebusspace(config_id, &tag, &bsh) != 0)
|
||||
return;
|
||||
|
||||
if ((bt = bt_alloc(unit, tag, bsh)) == NULL)
|
||||
return; /* XXX PCI code should take return status */
|
||||
|
||||
/* Allocate a dmatag for our CCB DMA maps */
|
||||
/* XXX Should be a child of the PCI bus dma tag */
|
||||
if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
|
||||
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
|
||||
/*highaddr*/BUS_SPACE_MAXADDR,
|
||||
/*filter*/NULL, /*filterarg*/NULL,
|
||||
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*nsegments*/BUS_SPACE_UNRESTRICTED,
|
||||
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
|
||||
/*flags*/0, &bt->parent_dmat) != 0) {
|
||||
bt_free(bt);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pci_map_int(config_id, bt_intr, (void *)bt, &cam_imask)) == 0) {
|
||||
bt_free(bt);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Protect ourself from spurrious interrupts during
|
||||
* intialization and attach. We should really rely
|
||||
* on interrupts during attach, but we don't have
|
||||
* access to our interrupts during ISA probes, so until
|
||||
* that changes, we mask our interrupts during attach
|
||||
* too.
|
||||
*/
|
||||
opri = splcam();
|
||||
|
||||
if (bt_probe(bt) || bt_fetch_adapter_info(bt) || bt_init(bt)) {
|
||||
bt_free(bt);
|
||||
splx(opri);
|
||||
return; /* XXX PCI code should take return status */
|
||||
}
|
||||
|
||||
bt_attach(bt);
|
||||
|
||||
splx(opri);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* NPCI > 0 */
|
Loading…
Reference in New Issue
Block a user