Add basic support for the 398X cards as multi-channel SCSI host adapters.
This involves expanding the support of the SEEPROM routines to deal with the larger SEEPROMs on these cards and providing a mechanism to share SCB arrays between multiple controllers. Most of the 398X support came from Dan Eischer. ahc_data -> ahc_softc Clean up some more type bogons I missed from the last pass. Be more clear when handing the NO_MATCH condition. NO_MATCH can also happen when the sequencer encounters an SCB we've asked to be aborted.
This commit is contained in:
parent
a30df8e223
commit
82270a2c1b
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Interface for the 93C46/26/06 serial eeprom parts.
|
||||
* Interface for the 93C66/56/46/26/06 serial eeprom parts.
|
||||
*
|
||||
* Copyright (c) 1995 Daniel M. Eischen
|
||||
* Copyright (c) 1995, 1996 Daniel M. Eischen
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -18,14 +18,14 @@
|
||||
* 4. Modifications may be freely made to this file if the above conditions
|
||||
* are met.
|
||||
*
|
||||
* $Id: 93cx6.c,v 1.5 1996/05/30 07:19:54 gibbs Exp $
|
||||
* $Id: 93cx6.c,v 1.6 1996/10/25 06:42:49 gibbs Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* The instruction set of the 93C46/26/06 chips are as follows:
|
||||
* The instruction set of the 93C66/56/46/26/06 chips are as follows:
|
||||
*
|
||||
* Start OP
|
||||
* Function Bit Code Address Data Description
|
||||
* Start OP *
|
||||
* Function Bit Code Address** Data Description
|
||||
* -------------------------------------------------------------------
|
||||
* READ 1 10 A5 - A0 Reads data stored in memory,
|
||||
* starting at specified address
|
||||
@ -38,12 +38,14 @@
|
||||
* EWDS 1 00 00XXXX Disables all programming
|
||||
* instructions
|
||||
* *Note: A value of X for address is a don't care condition.
|
||||
* **Note: There are 8 address bits for the 93C56/66 chips unlike
|
||||
* the 93C46/26/06 chips which have 6 address bits.
|
||||
*
|
||||
* The 93C46 has a four wire interface: clock, chip select, data in, and
|
||||
* data out. In order to perform one of the above functions, you need
|
||||
* to enable the chip select for a clock period (typically a minimum of
|
||||
* 1 usec, with the clock high and low a minimum of 750 and 250 nsec
|
||||
* respectively. While the chip select remains high, you can clock in
|
||||
* respectively). While the chip select remains high, you can clock in
|
||||
* the instructions (above) starting with the start bit, followed by the
|
||||
* OP code, Address, and Data (if needed). For the READ instruction, the
|
||||
* requested 16-bit register contents is read from the data out line but
|
||||
@ -125,8 +127,8 @@ read_seeprom(sd, buf, start_addr, count)
|
||||
if (seeprom_read.bits[i] != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
}
|
||||
/* Send the 6 bit address (MSB first, LSB last). */
|
||||
for (i = 5; i >= 0; i--) {
|
||||
/* Send the 6 or 8 bit address (MSB first, LSB last). */
|
||||
for (i = (sd->sd_chip - 1); i >= 0; i--) {
|
||||
if ((k & (1 << i)) != 0)
|
||||
temp ^= sd->sd_DO;
|
||||
SEEPROM_OUTB(sd, temp);
|
||||
|
@ -20,7 +20,7 @@
|
||||
* 4. Modifications may be freely made to this file if the above conditions
|
||||
* are met.
|
||||
*
|
||||
* $Id: 93cx6.h,v 1.1.2.3 1996/06/08 07:10:44 gibbs Exp $
|
||||
* $Id: 93cx6.h,v 1.4 1996/10/25 06:42:50 gibbs Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -28,6 +28,11 @@
|
||||
#include <sys/systm.h>
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
C46 = 6,
|
||||
C56_66 = 8
|
||||
} seeprom_chip_t;
|
||||
|
||||
struct seeprom_descriptor {
|
||||
#if defined(__FreeBSD__)
|
||||
u_int32_t sd_iobase;
|
||||
@ -37,6 +42,7 @@ struct seeprom_descriptor {
|
||||
bus_io_handle_t sd_ioh;
|
||||
bus_io_size_t sd_offset;
|
||||
#endif
|
||||
seeprom_chip_t sd_chip;
|
||||
u_int16_t sd_MS;
|
||||
u_int16_t sd_RDY;
|
||||
u_int16_t sd_CS;
|
||||
|
@ -32,7 +32,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.75.2.5 1996/10/06 22:48:12 gibbs Exp $
|
||||
* $Id: aic7xxx.c,v 1.80 1996/10/25 06:42:51 gibbs Exp $
|
||||
*/
|
||||
/*
|
||||
* TODO:
|
||||
@ -163,16 +163,16 @@ int ahc_broken_cache = 1;
|
||||
|
||||
static void ahcminphys __P((struct buf *bp));
|
||||
static int32_t ahc_scsi_cmd __P((struct scsi_xfer *xs));
|
||||
static void ahc_run_waiting_queue __P((struct ahc_data *ahc));
|
||||
static void ahc_run_waiting_queue __P((struct ahc_softc *ahc));
|
||||
static struct scb *
|
||||
ahc_get_scb __P((struct ahc_data *ahc, u_int32_t flags));
|
||||
static void ahc_free_scb __P((struct ahc_data *ahc, struct scb *scb));
|
||||
ahc_get_scb __P((struct ahc_softc *ahc, u_int32_t flags));
|
||||
static void ahc_free_scb __P((struct ahc_softc *ahc, struct scb *scb));
|
||||
static struct scb *
|
||||
ahc_alloc_scb __P((struct ahc_data *ahc));
|
||||
static inline void pause_sequencer __P((struct ahc_data *ahc));
|
||||
static inline void unpause_sequencer __P((struct ahc_data *ahc,
|
||||
ahc_alloc_scb __P((struct ahc_softc *ahc));
|
||||
static inline void pause_sequencer __P((struct ahc_softc *ahc));
|
||||
static inline void unpause_sequencer __P((struct ahc_softc *ahc,
|
||||
int unpause_always));
|
||||
static inline void restart_sequencer __P((struct ahc_data *ahc));
|
||||
static inline void restart_sequencer __P((struct ahc_softc *ahc));
|
||||
|
||||
static struct scsi_adapter ahc_switch =
|
||||
{
|
||||
@ -202,7 +202,7 @@ static struct scsi_device ahc_dev =
|
||||
|
||||
static inline void
|
||||
pause_sequencer(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
AHC_OUTB(ahc, HCNTRL, ahc->pause);
|
||||
|
||||
@ -216,7 +216,7 @@ pause_sequencer(ahc)
|
||||
|
||||
static inline void
|
||||
unpause_sequencer(ahc, unpause_always)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int unpause_always;
|
||||
{
|
||||
if (unpause_always
|
||||
@ -229,7 +229,7 @@ unpause_sequencer(ahc, unpause_always)
|
||||
*/
|
||||
static inline void
|
||||
restart_sequencer(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
do {
|
||||
AHC_OUTB(ahc, SEQCTL, SEQRESET|FASTMODE);
|
||||
@ -247,31 +247,31 @@ restart_sequencer(ahc)
|
||||
((sc_link)->scsibus == (ahc)->sc_link_b.scsibus)
|
||||
#endif
|
||||
|
||||
static u_int8_t ahc_abort_wscb __P((struct ahc_data *ahc, struct scb *scbp,
|
||||
static u_int8_t ahc_abort_wscb __P((struct ahc_softc *ahc, struct scb *scbp,
|
||||
u_int8_t scbpos, u_int8_t prev,
|
||||
struct scb *timedout_scb,
|
||||
u_int32_t xs_error));
|
||||
static void ahc_done __P((struct ahc_data *ahc, struct scb *scbp));
|
||||
static void ahc_handle_seqint __P((struct ahc_data *ahc, u_int8_t intstat));
|
||||
static void ahc_handle_scsiint __P((struct ahc_data *ahc,
|
||||
static void ahc_done __P((struct ahc_softc *ahc, struct scb *scbp));
|
||||
static void ahc_handle_seqint __P((struct ahc_softc *ahc, u_int8_t intstat));
|
||||
static void ahc_handle_scsiint __P((struct ahc_softc *ahc,
|
||||
u_int8_t intstat));
|
||||
static void ahc_loadseq __P((struct ahc_data *ahc));
|
||||
static void ahc_loadseq __P((struct ahc_softc *ahc));
|
||||
static int ahc_match_scb __P((struct scb *scb, int target, char channel));
|
||||
static int ahc_poll __P((struct ahc_data *ahc, int wait));
|
||||
static int ahc_poll __P((struct ahc_softc *ahc, int wait));
|
||||
#ifdef AHC_DEBUG
|
||||
static void ahc_print_scb __P((struct scb *scb));
|
||||
#endif
|
||||
static u_int8_t find_scb __P((struct ahc_data *ahc, struct scb *scb));
|
||||
static int ahc_reset_channel __P((struct ahc_data *ahc, char channel,
|
||||
static u_int8_t find_scb __P((struct ahc_softc *ahc, struct scb *scb));
|
||||
static int ahc_reset_channel __P((struct ahc_softc *ahc, char channel,
|
||||
struct scb *timedout_scb,
|
||||
u_int32_t xs_error,
|
||||
int initiate_reset));
|
||||
static int ahc_reset_device __P((struct ahc_data *ahc, int target,
|
||||
static int ahc_reset_device __P((struct ahc_softc *ahc, int target,
|
||||
char channel, struct scb *timedout_scb,
|
||||
u_int32_t xs_error));
|
||||
static void ahc_reset_current_bus __P((struct ahc_data *ahc));
|
||||
static void ahc_run_done_queue __P((struct ahc_data *ahc));
|
||||
static void ahc_scsirate __P((struct ahc_data* ahc, u_int8_t *scsirate,
|
||||
static void ahc_reset_current_bus __P((struct ahc_softc *ahc));
|
||||
static void ahc_run_done_queue __P((struct ahc_softc *ahc));
|
||||
static void ahc_scsirate __P((struct ahc_softc* ahc, u_int8_t *scsirate,
|
||||
u_int8_t *period, u_int8_t *offset,
|
||||
char channel, int target));
|
||||
#if defined(__FreeBSD__)
|
||||
@ -281,13 +281,13 @@ static timeout_t
|
||||
static void ahc_timeout __P((void *));
|
||||
#endif
|
||||
|
||||
static void ahc_unbusy_target __P((struct ahc_data *ahc,
|
||||
static u_int8_t ahc_unbusy_target __P((struct ahc_softc *ahc,
|
||||
int target, char channel));
|
||||
|
||||
static void ahc_construct_sdtr __P((struct ahc_data *ahc, int start_byte,
|
||||
static void ahc_construct_sdtr __P((struct ahc_softc *ahc, int start_byte,
|
||||
u_int8_t period, u_int8_t offset));
|
||||
|
||||
static void ahc_construct_wdtr __P((struct ahc_data *ahc, int start_byte,
|
||||
static void ahc_construct_wdtr __P((struct ahc_softc *ahc, int start_byte,
|
||||
u_int8_t bus_width));
|
||||
|
||||
static void ahc_calc_residual __P((struct scb *scb));
|
||||
@ -295,7 +295,7 @@ static void ahc_calc_residual __P((struct scb *scb));
|
||||
#if defined(__FreeBSD__)
|
||||
|
||||
char *ahc_name(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
static char name[10];
|
||||
|
||||
@ -377,41 +377,53 @@ static int ahc_num_syncrates =
|
||||
* is paused.
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
struct ahc_data *
|
||||
ahc_alloc(unit, iobase, maddr, type, flags)
|
||||
struct ahc_softc *
|
||||
ahc_alloc(unit, iobase, maddr, type, flags, scb_data)
|
||||
int unit;
|
||||
u_int32_t iobase;
|
||||
#elif defined(__NetBSD__)
|
||||
void
|
||||
ahc_construct(ahc, bc, ioh, maddr, type, flags)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
bus_chipset_tag_t bc;
|
||||
bus_io_handle_t ioh;
|
||||
#endif
|
||||
vm_offset_t maddr;
|
||||
ahc_type type;
|
||||
ahc_flag flags;
|
||||
struct scb_data *scb_data;
|
||||
{
|
||||
|
||||
/*
|
||||
* find unit and check we have that many defined
|
||||
*/
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
size_t alloc_size;
|
||||
|
||||
/*
|
||||
* Allocate a storage area for us
|
||||
*/
|
||||
|
||||
ahc = malloc(sizeof(struct ahc_data), M_TEMP, M_NOWAIT);
|
||||
if (scb_data == NULL)
|
||||
/*
|
||||
* We are not sharing SCB space with another controller
|
||||
* so allocate our own SCB data space.
|
||||
*/
|
||||
alloc_size = sizeof(struct full_ahc_softc);
|
||||
else
|
||||
alloc_size = sizeof(struct ahc_softc);
|
||||
ahc = malloc(alloc_size, M_DEVBUF, M_NOWAIT);
|
||||
if (!ahc) {
|
||||
printf("ahc%d: cannot malloc!\n", unit);
|
||||
return NULL;
|
||||
}
|
||||
bzero(ahc, sizeof(struct ahc_data));
|
||||
bzero(ahc, alloc_size);
|
||||
#endif
|
||||
STAILQ_INIT(&ahc->free_scbs);
|
||||
if (scb_data == NULL) {
|
||||
struct full_ahc_softc* full_softc = (struct full_ahc_softc*)ahc;
|
||||
ahc->scb_data = &full_softc->scb_data_storage;
|
||||
STAILQ_INIT(&ahc->scb_data->free_scbs);
|
||||
} else
|
||||
ahc->scb_data = scb_data;
|
||||
STAILQ_INIT(&ahc->waiting_scbs);
|
||||
#if defined(__FreeBSD__)
|
||||
ahc->unit = unit;
|
||||
@ -435,7 +447,7 @@ ahc_construct(ahc, bc, ioh, maddr, type, flags)
|
||||
|
||||
void
|
||||
ahc_free(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
#if defined(__FreeBSD__)
|
||||
free(ahc, M_DEVBUF);
|
||||
@ -498,7 +510,7 @@ ahc_reset(devname, bc, ioh)
|
||||
*/
|
||||
static void
|
||||
ahc_scsirate(ahc, scsirate, period, offset, channel, target )
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
u_int8_t *scsirate;
|
||||
u_int8_t *period;
|
||||
u_int8_t *offset;
|
||||
@ -592,7 +604,7 @@ ahcprint(aux, name)
|
||||
*/
|
||||
int
|
||||
ahc_attach(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
struct scsibus_data *scbus;
|
||||
|
||||
@ -715,10 +727,10 @@ int
|
||||
ahc_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
u_int8_t intstat;
|
||||
|
||||
ahc = (struct ahc_data *)arg;
|
||||
ahc = (struct ahc_softc *)arg;
|
||||
intstat = AHC_INB(ahc, INTSTAT);
|
||||
/*
|
||||
* Is this interrupt for me? or for
|
||||
@ -764,7 +776,7 @@ ahc_intr(arg)
|
||||
|
||||
for (; qoutcnt > 0; qoutcnt--) {
|
||||
scb_index = AHC_INB(ahc, QOUTFIFO);
|
||||
scb = ahc->scbarray[scb_index];
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
if (!scb || !(scb->flags & SCB_ACTIVE)) {
|
||||
printf("%s: WARNING "
|
||||
"no command for scb %d "
|
||||
@ -798,7 +810,7 @@ ahc_intr(arg)
|
||||
|
||||
static void
|
||||
ahc_handle_seqint(ahc, intstat)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
u_int8_t intstat;
|
||||
{
|
||||
struct scb *scb;
|
||||
@ -813,16 +825,75 @@ ahc_handle_seqint(ahc, intstat)
|
||||
|
||||
switch (intstat & SEQINT_MASK) {
|
||||
case NO_MATCH:
|
||||
{
|
||||
/*
|
||||
* This could be for a normal abort request.
|
||||
* Figure out the SCB that we were trying to find
|
||||
* and only give an error if we didn't ask for this
|
||||
* to happen.
|
||||
*/
|
||||
u_int8_t scb_index;
|
||||
u_int8_t busy_scbid;
|
||||
|
||||
busy_scbid = ahc_unbusy_target(ahc, target, channel);
|
||||
scb_index = AHC_INB(ahc, ARG_1);
|
||||
|
||||
if (scb_index == SCB_LIST_NULL)
|
||||
/* Untagged Request */
|
||||
scb_index = busy_scbid;
|
||||
|
||||
if (scb_index < ahc->scb_data->numscbs) {
|
||||
scb = ahc->scb_data->scbarray[busy_scbid];
|
||||
|
||||
if (scb->hscb->control & ABORT_SCB) {
|
||||
sc_print_addr(scb->xs->sc_link);
|
||||
printf(" - SCB abort successfull\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%s:%c:%d: no active SCB for reconnecting "
|
||||
"target - issuing ABORT\n",
|
||||
ahc_name(ahc), channel, target);
|
||||
printf("SAVED_TCL == 0x%x\n",
|
||||
AHC_INB(ahc, SAVED_TCL));
|
||||
ahc_unbusy_target(ahc, target, channel);
|
||||
AHC_OUTB(ahc, SCB_CONTROL, 0);
|
||||
AHC_OUTB(ahc, CLRSINT1, CLRSELTIMEO);
|
||||
AHC_OUTB(ahc, RETURN_1, 0);
|
||||
break;
|
||||
}
|
||||
case NO_MATCH_BUSY:
|
||||
{
|
||||
/* The SCB that wanted to link in is in CUR_SCBID */
|
||||
u_int8_t scb_index;
|
||||
u_int8_t busy_scbindex;
|
||||
struct scb *busy_scb = NULL;
|
||||
|
||||
scb_index = AHC_INB(ahc, CUR_SCBID);
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
|
||||
/* Find the busy SCB and unbusy this target */
|
||||
busy_scbindex = ahc_unbusy_target(ahc, scb->xs->sc_link->target,
|
||||
channel);
|
||||
if (busy_scbindex == SCB_LIST_NULL)
|
||||
panic("%s:%c:%d: Target busy link failure, but "
|
||||
"the target is not busy!\n",
|
||||
ahc_name(ahc), channel, target);
|
||||
|
||||
busy_scb = ahc->scb_data->scbarray[busy_scbindex];
|
||||
/* Busy SCB should be aborted */
|
||||
if ((busy_scb != NULL)
|
||||
&& (busy_scb->hscb->control & ABORT_SCB) == 0
|
||||
&& (busy_scb->hscb->control & SCB_ACTIVE) != 0) {
|
||||
panic("%s:%c:%d: Target busy link failure, but "
|
||||
"busy SCB exists!\n",
|
||||
ahc_name(ahc), channel, target);
|
||||
}
|
||||
|
||||
if ((scb->hscb->control & ABORT_SCB) == 0) {
|
||||
/* We didn't want to abort this one too */
|
||||
AHC_OUTB(ahc, QINFIFO, scb_index);
|
||||
} else
|
||||
/* It's been aborted */
|
||||
ahc_done(ahc, scb);
|
||||
restart_sequencer(ahc);
|
||||
}
|
||||
case SEND_REJECT:
|
||||
{
|
||||
u_int8_t rejbyte = AHC_INB(ahc, REJBYTE);
|
||||
@ -1070,7 +1141,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
*/
|
||||
|
||||
scb_index = AHC_INB(ahc, SCB_TAG);
|
||||
scb = ahc->scbarray[scb_index];
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
hscb = scb->hscb;
|
||||
|
||||
/*
|
||||
@ -1168,6 +1239,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
* The upper level SCSI code will someday
|
||||
* handle this properly.
|
||||
*/
|
||||
printf("Queue Full\n");
|
||||
xs->error = XS_BUSY;
|
||||
break;
|
||||
default:
|
||||
@ -1184,7 +1256,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
struct scsi_xfer *xs;
|
||||
|
||||
scb_index = AHC_INB(ahc, SCB_TAG);
|
||||
scb = ahc->scbarray[scb_index];
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
xs = scb->xs;
|
||||
/*
|
||||
* We didn't recieve a valid tag back from
|
||||
@ -1202,7 +1274,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
int scb_index;
|
||||
|
||||
scb_index = AHC_INB(ahc, SCB_TAG);
|
||||
scb = ahc->scbarray[scb_index];
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
/*
|
||||
* This SCB had MK_MESSAGE set in its control byte,
|
||||
* informing the sequencer that we wanted to send a
|
||||
@ -1256,7 +1328,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
*/
|
||||
u_int8_t scbindex = AHC_INB(ahc, SCB_TAG);
|
||||
|
||||
scb = ahc->scbarray[scbindex];
|
||||
scb = ahc->scb_data->scbarray[scbindex];
|
||||
if (scb->flags & SCB_DEVICE_RESET) {
|
||||
u_int8_t targ_scratch;
|
||||
int found;
|
||||
@ -1297,7 +1369,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
*/
|
||||
u_int8_t scbindex = AHC_INB(ahc, SCB_TAG);
|
||||
u_int32_t overrun;
|
||||
scb = ahc->scbarray[scbindex];
|
||||
scb = ahc->scb_data->scbarray[scbindex];
|
||||
overrun = AHC_INB(ahc, STCNT0)
|
||||
| (AHC_INB(ahc, STCNT1) << 8)
|
||||
| (AHC_INB(ahc, STCNT2) << 16);
|
||||
@ -1343,7 +1415,7 @@ ahc_handle_seqint(ahc, intstat)
|
||||
|
||||
static void
|
||||
ahc_handle_scsiint(ahc, intstat)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
u_int8_t intstat;
|
||||
{
|
||||
u_int8_t scb_index;
|
||||
@ -1352,7 +1424,7 @@ ahc_handle_scsiint(ahc, intstat)
|
||||
|
||||
scb_index = AHC_INB(ahc, SCB_TAG);
|
||||
status = AHC_INB(ahc, SSTAT1);
|
||||
scb = ahc->scbarray[scb_index];
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
|
||||
if (status & SCSIRSTI) {
|
||||
char channel;
|
||||
@ -1489,7 +1561,7 @@ ahc_handle_scsiint(ahc, intstat)
|
||||
*/
|
||||
static void
|
||||
ahc_done(ahc, scb)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
struct scb *scb;
|
||||
{
|
||||
struct scsi_xfer *xs = scb->xs;
|
||||
@ -1542,7 +1614,8 @@ ahc_done(ahc, scb)
|
||||
printf("%s: target %d Tagged Queuing Device\n",
|
||||
ahc_name(ahc), xs->sc_link->target);
|
||||
ahc->tagenable |= mask;
|
||||
if (ahc->maxhscbs >= 16 || (ahc->flags&AHC_PAGESCBS)) {
|
||||
if (ahc->scb_data->maxhscbs >= 16
|
||||
|| (ahc->flags & AHC_PAGESCBS)) {
|
||||
/* Default to 8 tags */
|
||||
xs->sc_link->opennings += 6;
|
||||
} else {
|
||||
@ -1568,7 +1641,7 @@ ahc_done(ahc, scb)
|
||||
*/
|
||||
int
|
||||
ahc_init(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
u_int8_t scsi_conf, sblkctl, i;
|
||||
u_int16_t ultraenable = 0;
|
||||
@ -1587,22 +1660,28 @@ ahc_init(ahc)
|
||||
case 0:
|
||||
ahc->our_id = (AHC_INB(ahc, SCSICONF) & HSCSIID);
|
||||
ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
|
||||
if (ahc->type == AHC_394)
|
||||
printf("Channel %c, SCSI Id=%d, ",
|
||||
ahc->flags & AHC_CHNLB ? 'B' : 'A',
|
||||
if ((ahc->type & AHC_39X) != 0) {
|
||||
char channel = 'A';
|
||||
|
||||
if ((ahc->flags & (AHC_CHNLB|AHC_CHNLC)) != 0)
|
||||
channel = ahc->flags & AHC_CHNLB ? 'B' : 'C';
|
||||
printf("Channel %c, SCSI Id=%d, ", channel,
|
||||
ahc->our_id);
|
||||
else
|
||||
} else
|
||||
printf("Single Channel, SCSI Id=%d, ", ahc->our_id);
|
||||
AHC_OUTB(ahc, FLAGS, SINGLE_BUS | (ahc->flags & AHC_PAGESCBS));
|
||||
break;
|
||||
case 2:
|
||||
ahc->our_id = (AHC_INB(ahc, SCSICONF + 1) & HWSCSIID);
|
||||
ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
|
||||
if (ahc->type == AHC_394)
|
||||
printf("Wide Channel %c, SCSI Id=%d, ",
|
||||
ahc->flags & AHC_CHNLB ? 'B' : 'A',
|
||||
if ((ahc->type & AHC_39X) != 0) {
|
||||
char channel = 'A';
|
||||
|
||||
if ((ahc->flags & (AHC_CHNLB|AHC_CHNLC)) != 0)
|
||||
channel = ahc->flags & AHC_CHNLB ? 'B' : 'C';
|
||||
printf("Wide Channel %c, SCSI Id=%d, ", channel,
|
||||
ahc->our_id);
|
||||
else
|
||||
} else
|
||||
printf("Wide Channel, SCSI Id=%d, ", ahc->our_id);
|
||||
ahc->type |= AHC_WIDE;
|
||||
AHC_OUTB(ahc, FLAGS, WIDE_BUS | (ahc->flags & AHC_PAGESCBS));
|
||||
@ -1622,7 +1701,7 @@ ahc_init(ahc)
|
||||
|
||||
/* Determine the number of SCBs and initialize them */
|
||||
|
||||
{
|
||||
if (ahc->scb_data->maxhscbs == 0) {
|
||||
/* SCB 0 heads the free list */
|
||||
AHC_OUTB(ahc, FREE_SCBH, 0);
|
||||
for (i = 0; i < AHC_SCB_MAX; i++) {
|
||||
@ -1656,16 +1735,18 @@ ahc_init(ahc)
|
||||
AHC_OUTB(ahc, SCBPTR, 0);
|
||||
AHC_OUTB(ahc, SCB_CONTROL, 0);
|
||||
|
||||
ahc->maxhscbs = i;
|
||||
ahc->scb_data->maxhscbs = i;
|
||||
}
|
||||
|
||||
if ((ahc->maxhscbs < AHC_SCB_MAX) && (ahc->flags & AHC_PAGESCBS)) {
|
||||
ahc->maxscbs = AHC_SCB_MAX;
|
||||
printf("%d/%d SCBs\n", ahc->maxhscbs, ahc->maxscbs);
|
||||
if ((ahc->scb_data->maxhscbs < AHC_SCB_MAX)
|
||||
&& (ahc->flags & AHC_PAGESCBS)) {
|
||||
ahc->scb_data->maxscbs = AHC_SCB_MAX;
|
||||
printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs,
|
||||
ahc->scb_data->maxscbs);
|
||||
} else {
|
||||
ahc->maxscbs = ahc->maxhscbs;
|
||||
ahc->scb_data->maxscbs = ahc->scb_data->maxhscbs;
|
||||
ahc->flags &= ~AHC_PAGESCBS;
|
||||
printf("%d SCBs\n", ahc->maxhscbs);
|
||||
printf("%d SCBs\n", ahc->scb_data->maxhscbs);
|
||||
}
|
||||
|
||||
|
||||
@ -1832,12 +1913,12 @@ ahc_init(ahc)
|
||||
/*
|
||||
* Set the number of availible hardware SCBs
|
||||
*/
|
||||
AHC_OUTB(ahc, SCBCOUNT, ahc->maxhscbs);
|
||||
AHC_OUTB(ahc, SCBCOUNT, ahc->scb_data->maxhscbs);
|
||||
|
||||
/*
|
||||
* 2's compliment of maximum tag value
|
||||
*/
|
||||
i = ahc->maxscbs;
|
||||
i = ahc->scb_data->maxscbs;
|
||||
AHC_OUTB(ahc, COMP_SCBCOUNT, -i & 0xff);
|
||||
|
||||
/*
|
||||
@ -1848,29 +1929,29 @@ ahc_init(ahc)
|
||||
* sequencer depends on this array being physically
|
||||
* contiguous.
|
||||
*/
|
||||
{
|
||||
if (ahc->scb_data->hscbs == NULL) {
|
||||
size_t array_size;
|
||||
u_int32_t hscb_physaddr;
|
||||
|
||||
array_size = ahc->maxscbs * sizeof(struct hardware_scb);
|
||||
array_size = ahc->scb_data->maxscbs*sizeof(struct hardware_scb);
|
||||
if (array_size > PAGE_SIZE) {
|
||||
ahc->hscbs = (struct hardware_scb *)
|
||||
ahc->scb_data->hscbs = (struct hardware_scb *)
|
||||
contigmalloc(array_size, M_DEVBUF,
|
||||
M_NOWAIT, 0ul, 0xffffffff, PAGE_SIZE,
|
||||
0x10000);
|
||||
} else {
|
||||
ahc->hscbs = (struct hardware_scb *)
|
||||
ahc->scb_data->hscbs = (struct hardware_scb *)
|
||||
malloc(array_size, M_DEVBUF, M_NOWAIT);
|
||||
}
|
||||
|
||||
if (ahc->hscbs == NULL) {
|
||||
if (ahc->scb_data->hscbs == NULL) {
|
||||
printf("%s: unable to allocate hardware SCB array. "
|
||||
"Failing attach\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Tell the sequencer where it can find the hscb array. */
|
||||
hscb_physaddr = vtophys(ahc->hscbs);
|
||||
hscb_physaddr = vtophys(ahc->scb_data->hscbs);
|
||||
AHC_OUTB(ahc, HSCB_ADDR0, hscb_physaddr & 0xFF);
|
||||
AHC_OUTB(ahc, HSCB_ADDR1, (hscb_physaddr >> 8)& 0xFF);
|
||||
AHC_OUTB(ahc, HSCB_ADDR2, (hscb_physaddr >> 16)& 0xFF);
|
||||
@ -1887,7 +1968,7 @@ ahc_init(ahc)
|
||||
} else if (ahc->type & AHC_AIC7850) {
|
||||
ahc->qfullcount = 8;
|
||||
ahc->qcntmask = 0x0f;
|
||||
} else if (ahc->maxhscbs == 255) {
|
||||
} else if (ahc->scb_data->maxhscbs == 255) {
|
||||
/* 7870/7880 with external SRAM */
|
||||
ahc->qfullcount = 255;
|
||||
ahc->qcntmask = 0xff;
|
||||
@ -1972,12 +2053,12 @@ ahc_scsi_cmd(xs)
|
||||
{
|
||||
struct scb *scb;
|
||||
struct hardware_scb *hscb;
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
u_int16_t mask;
|
||||
int flags;
|
||||
int s;
|
||||
|
||||
ahc = (struct ahc_data *)xs->sc_link->adapter_softc;
|
||||
ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
|
||||
mask = (0x01 << (xs->sc_link->target
|
||||
| (IS_SCSIBUS_B(ahc, xs->sc_link) ? SELBUSB : 0)));
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
|
||||
@ -2148,7 +2229,7 @@ ahc_scsi_cmd(xs)
|
||||
*/
|
||||
static void
|
||||
ahc_run_waiting_queue(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
struct scb *scb;
|
||||
|
||||
@ -2188,7 +2269,7 @@ ahc_run_waiting_queue(ahc)
|
||||
*/
|
||||
static void
|
||||
ahc_free_scb(ahc, scb)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
struct scb *scb;
|
||||
{
|
||||
struct hardware_scb *hscb;
|
||||
@ -2203,13 +2284,13 @@ ahc_free_scb(ahc, scb)
|
||||
hscb->control = 0;
|
||||
hscb->status = 0;
|
||||
|
||||
STAILQ_INSERT_HEAD(&ahc->free_scbs, scb, links);
|
||||
STAILQ_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links);
|
||||
if (scb->links.stqe_next == NULL) {
|
||||
/*
|
||||
* If there were no SCBs availible, wake anybody waiting
|
||||
* for one to come free.
|
||||
*/
|
||||
wakeup((caddr_t)&ahc->free_scbs);
|
||||
wakeup((caddr_t)&ahc->scb_data->free_scbs);
|
||||
}
|
||||
#ifdef AHC_DEBUG
|
||||
ahc->activescbs--;
|
||||
@ -2225,7 +2306,7 @@ ahc_free_scb(ahc, scb)
|
||||
*/
|
||||
static struct scb *
|
||||
ahc_get_scb(ahc, flags)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
u_int32_t flags;
|
||||
{
|
||||
struct scb *scbp;
|
||||
@ -2237,15 +2318,14 @@ ahc_get_scb(ahc, flags)
|
||||
* but only if we can't allocate a new one.
|
||||
*/
|
||||
while (1) {
|
||||
if ((scbp = ahc->free_scbs.stqh_first)) {
|
||||
STAILQ_REMOVE_HEAD(&ahc->free_scbs, links);
|
||||
} else if(ahc->numscbs < ahc->maxscbs) {
|
||||
if ((scbp = ahc->scb_data->free_scbs.stqh_first)) {
|
||||
STAILQ_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
|
||||
} else if(ahc->scb_data->numscbs < ahc->scb_data->maxscbs) {
|
||||
scbp = ahc_alloc_scb(ahc);
|
||||
if (scbp == NULL)
|
||||
printf("%s: Can't malloc SCB\n", ahc_name(ahc));
|
||||
}
|
||||
else if ((flags & SCSI_NOSLEEP) == 0) {
|
||||
tsleep((caddr_t)&ahc->free_scbs, PRIBIO,
|
||||
} else if ((flags & SCSI_NOSLEEP) == 0) {
|
||||
tsleep((caddr_t)&ahc->scb_data->free_scbs, PRIBIO,
|
||||
"ahcscb", 0);
|
||||
continue;
|
||||
}
|
||||
@ -2256,7 +2336,7 @@ ahc_get_scb(ahc, flags)
|
||||
if (scbp) {
|
||||
ahc->activescbs++;
|
||||
if((ahc_debug & AHC_SHOWSCBCNT)
|
||||
&& (ahc->activescbs == ahc->maxhscbs))
|
||||
&& (ahc->activescbs == ahc->scb_data->maxhscbs))
|
||||
printf("%s: Max SCBs active\n", ahc_name(ahc));
|
||||
}
|
||||
#endif
|
||||
@ -2269,10 +2349,10 @@ ahc_get_scb(ahc, flags)
|
||||
|
||||
static struct scb *
|
||||
ahc_alloc_scb(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
static struct ahc_dma_seg *next_sg_array = NULL;
|
||||
static int sg_arrays_free;
|
||||
static int sg_arrays_free = 0;
|
||||
struct scb *newscb;
|
||||
|
||||
newscb = (struct scb *) malloc(sizeof(struct scb), M_DEVBUF, M_NOWAIT);
|
||||
@ -2282,9 +2362,6 @@ ahc_alloc_scb(ahc)
|
||||
size_t alloc_size = sizeof(struct ahc_dma_seg)
|
||||
* AHC_NSEG;
|
||||
sg_arrays_free = PAGE_SIZE / alloc_size;
|
||||
/* Don't ever allocate more than we may need */
|
||||
sg_arrays_free = MIN(ahc->maxscbs - ahc->numscbs,
|
||||
sg_arrays_free);
|
||||
alloc_size *= sg_arrays_free;
|
||||
if (alloc_size == 0)
|
||||
panic("%s: SG list doesn't fit in a page",
|
||||
@ -2301,21 +2378,21 @@ ahc_alloc_scb(ahc)
|
||||
next_sg_array = NULL;
|
||||
else
|
||||
next_sg_array = &next_sg_array[AHC_NSEG];
|
||||
hscb = &ahc->hscbs[ahc->numscbs];
|
||||
hscb = &ahc->scb_data->hscbs[ahc->scb_data->numscbs];
|
||||
newscb->hscb = hscb;
|
||||
hscb->control = 0;
|
||||
hscb->status = 0;
|
||||
hscb->tag = ahc->numscbs;
|
||||
hscb->tag = ahc->scb_data->numscbs;
|
||||
hscb->residual_data_count[2] = 0;
|
||||
hscb->residual_data_count[1] = 0;
|
||||
hscb->residual_data_count[0] = 0;
|
||||
hscb->residual_SG_segment_count = 0;
|
||||
ahc->numscbs++;
|
||||
ahc->scb_data->numscbs++;
|
||||
/*
|
||||
* Place in the scbarray
|
||||
* Never is removed.
|
||||
*/
|
||||
ahc->scbarray[hscb->tag] = newscb;
|
||||
ahc->scb_data->scbarray[hscb->tag] = newscb;
|
||||
} else {
|
||||
free(newscb, M_DEVBUF);
|
||||
newscb = NULL;
|
||||
@ -2325,7 +2402,7 @@ ahc_alloc_scb(ahc)
|
||||
}
|
||||
|
||||
static void ahc_loadseq(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
static u_char seqprog[] = {
|
||||
# include "aic7xxx_seq.h"
|
||||
@ -2347,7 +2424,7 @@ static void ahc_loadseq(ahc)
|
||||
*/
|
||||
static int
|
||||
ahc_poll(ahc, wait)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int wait; /* in msec */
|
||||
{
|
||||
while (--wait) {
|
||||
@ -2367,7 +2444,7 @@ ahc_timeout(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct scb *scb = (struct scb *)arg;
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int s, found;
|
||||
u_char bus_state;
|
||||
|
||||
@ -2379,7 +2456,7 @@ ahc_timeout(arg)
|
||||
return;
|
||||
}
|
||||
|
||||
ahc = (struct ahc_data *)scb->xs->sc_link->adapter_softc;
|
||||
ahc = (struct ahc_softc *)scb->xs->sc_link->adapter_softc;
|
||||
|
||||
if (ahc->in_timeout) {
|
||||
/*
|
||||
@ -2505,7 +2582,7 @@ ahc_timeout(arg)
|
||||
|
||||
saved_scbptr = AHC_INB(ahc, SCBPTR);
|
||||
active_scb_index = AHC_INB(ahc, SCB_TAG);
|
||||
active_scb = ahc->scbarray[active_scb_index];
|
||||
active_scb = ahc->scb_data->scbarray[active_scb_index];
|
||||
|
||||
if (bus_state != 0) {
|
||||
/* Send the abort to the active SCB */
|
||||
@ -2566,7 +2643,7 @@ ahc_timeout(arg)
|
||||
*/
|
||||
static u_int8_t
|
||||
find_scb(ahc, scb)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
struct scb *scb;
|
||||
{
|
||||
u_int8_t saved_scbptr;
|
||||
@ -2574,13 +2651,13 @@ find_scb(ahc, scb)
|
||||
|
||||
saved_scbptr = AHC_INB(ahc, SCBPTR);
|
||||
curindex = 0;
|
||||
for (curindex = 0; curindex < ahc->maxhscbs; curindex++) {
|
||||
for (curindex = 0; curindex < ahc->scb_data->maxhscbs; curindex++) {
|
||||
AHC_OUTB(ahc, SCBPTR, curindex);
|
||||
if (AHC_INB(ahc, SCB_TAG) == scb->hscb->tag)
|
||||
break;
|
||||
}
|
||||
AHC_OUTB(ahc, SCBPTR, saved_scbptr);
|
||||
if (curindex > ahc->maxhscbs)
|
||||
if (curindex > ahc->scb_data->maxhscbs)
|
||||
curindex = SCB_LIST_NULL;
|
||||
|
||||
return curindex;
|
||||
@ -2592,7 +2669,7 @@ find_scb(ahc, scb)
|
||||
*/
|
||||
static int
|
||||
ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int target;
|
||||
char channel;
|
||||
struct scb *timedout_scb;
|
||||
@ -2615,7 +2692,7 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
|
||||
|
||||
for (i = 0; i < (queued - found); i++) {
|
||||
saved_queue[i] = AHC_INB(ahc, QINFIFO);
|
||||
scbp = ahc->scbarray[saved_queue[i]];
|
||||
scbp = ahc->scb_data->scbarray[saved_queue[i]];
|
||||
if (ahc_match_scb (scbp, target, channel)) {
|
||||
/*
|
||||
* We found an scb that needs to be aborted.
|
||||
@ -2645,7 +2722,7 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
|
||||
|
||||
while (next != SCB_LIST_NULL) {
|
||||
AHC_OUTB(ahc, SCBPTR, next);
|
||||
scbp = ahc->scbarray[AHC_INB(ahc, SCB_TAG)];
|
||||
scbp = ahc->scb_data->scbarray[AHC_INB(ahc, SCB_TAG)];
|
||||
if (ahc_match_scb(scbp, target, channel)) {
|
||||
next = ahc_abort_wscb(ahc, scbp, next, prev,
|
||||
timedout_scb, xs_error);
|
||||
@ -2662,8 +2739,8 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
|
||||
* are other (most likely tagged) commands that
|
||||
* were disconnected when the reset occured.
|
||||
*/
|
||||
for (i = 0; i < ahc->numscbs; i++) {
|
||||
scbp = ahc->scbarray[i];
|
||||
for (i = 0; i < ahc->scb_data->numscbs; i++) {
|
||||
scbp = ahc->scb_data->scbarray[i];
|
||||
if ((scbp->flags & SCB_ACTIVE)
|
||||
&& ahc_match_scb(scbp, target, channel)) {
|
||||
/* Ensure the target is "free" */
|
||||
@ -2685,8 +2762,8 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
|
||||
*/
|
||||
static u_char
|
||||
ahc_abort_wscb (ahc, scbp, scbpos, prev, timedout_scb, xs_error)
|
||||
struct ahc_data *ahc;
|
||||
struct scb *scbp;
|
||||
struct ahc_softc *ahc;
|
||||
struct scb *scbp;
|
||||
u_int8_t scbpos;
|
||||
u_int8_t prev;
|
||||
struct scb *timedout_scb;
|
||||
@ -2733,14 +2810,15 @@ ahc_abort_wscb (ahc, scbp, scbpos, prev, timedout_scb, xs_error)
|
||||
return next;
|
||||
}
|
||||
|
||||
static void
|
||||
static u_int8_t
|
||||
ahc_unbusy_target(ahc, target, channel)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int target;
|
||||
char channel;
|
||||
{
|
||||
u_int8_t active_scb;
|
||||
u_int8_t info_scb;
|
||||
u_int8_t busy_scbid;
|
||||
u_int32_t scb_offset;
|
||||
|
||||
info_scb = target / 4;
|
||||
@ -2749,13 +2827,15 @@ ahc_unbusy_target(ahc, target, channel)
|
||||
active_scb = AHC_INB(ahc, SCBPTR);
|
||||
AHC_OUTB(ahc, SCBPTR, info_scb);
|
||||
scb_offset = SCB_ACTIVE0 + (target & 0x03);
|
||||
busy_scbid = AHC_INB(ahc, scb_offset);
|
||||
AHC_OUTB(ahc, scb_offset, SCB_LIST_NULL);
|
||||
AHC_OUTB(ahc, SCBPTR, active_scb);
|
||||
return busy_scbid;
|
||||
}
|
||||
|
||||
static void
|
||||
ahc_reset_current_bus(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
AHC_OUTB(ahc, SCSISEQ, SCSIRSTO);
|
||||
DELAY(1000);
|
||||
@ -2764,7 +2844,7 @@ ahc_reset_current_bus(ahc)
|
||||
|
||||
static int
|
||||
ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
char channel;
|
||||
struct scb *timedout_scb;
|
||||
u_int32_t xs_error;
|
||||
@ -2851,13 +2931,13 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
|
||||
|
||||
void
|
||||
ahc_run_done_queue(ahc)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
{
|
||||
int i;
|
||||
struct scb *scbp;
|
||||
|
||||
for (i = 0; i < ahc->numscbs; i++) {
|
||||
scbp = ahc->scbarray[i];
|
||||
for (i = 0; i < ahc->scb_data->numscbs; i++) {
|
||||
scbp = ahc->scb_data->scbarray[i];
|
||||
if (scbp->flags & SCB_QUEUED_FOR_DONE)
|
||||
ahc_done(ahc, scbp);
|
||||
}
|
||||
@ -2880,7 +2960,7 @@ ahc_match_scb (scb, target, channel)
|
||||
|
||||
static void
|
||||
ahc_construct_sdtr(ahc, start_byte, period, offset)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int start_byte;
|
||||
u_int8_t period;
|
||||
u_int8_t offset;
|
||||
@ -2895,7 +2975,7 @@ ahc_construct_sdtr(ahc, start_byte, period, offset)
|
||||
|
||||
static void
|
||||
ahc_construct_wdtr(ahc, start_byte, bus_width)
|
||||
struct ahc_data *ahc;
|
||||
struct ahc_softc *ahc;
|
||||
int start_byte;
|
||||
u_int8_t bus_width;
|
||||
{
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.h,v 1.28.2.2 1996/10/06 01:31:25 gibbs Exp $
|
||||
* $Id: aic7xxx.h,v 1.30 1996/10/25 06:42:53 gibbs Exp $
|
||||
*/
|
||||
|
||||
#ifndef _AIC7XXX_H_
|
||||
@ -97,23 +97,28 @@ struct ahc_dma_seg {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
AHC_NONE = 0x000,
|
||||
AHC_ULTRA = 0x001, /* Supports 20MHz Transfers */
|
||||
AHC_WIDE = 0x002, /* Wide Channel */
|
||||
AHC_TWIN = 0x008, /* Twin Channel */
|
||||
AHC_AIC7770 = 0x010,
|
||||
AHC_AIC7850 = 0x020,
|
||||
AHC_AIC7860 = 0x021, /* ULTRA version of the aic7850 */
|
||||
AHC_AIC7870 = 0x040,
|
||||
AHC_AIC7880 = 0x041,
|
||||
AHC_AIC78X0 = 0x060, /* PCI Based Controller */
|
||||
AHC_274 = 0x110, /* EISA Based Controller */
|
||||
AHC_284 = 0x210, /* VL/ISA Based Controller */
|
||||
AHC_294AU = 0x421, /* aic7860 based '2940' */
|
||||
AHC_294 = 0x440, /* PCI Based Controller */
|
||||
AHC_294U = 0x441, /* ULTRA PCI Based Controller */
|
||||
AHC_394 = 0x840, /* Twin Channel PCI Controller */
|
||||
AHC_394U = 0x841, /* Twin, ULTRA Channel PCI Controller */
|
||||
AHC_NONE = 0x0000,
|
||||
AHC_ULTRA = 0x0001, /* Supports 20MHz Transfers */
|
||||
AHC_WIDE = 0x0002, /* Wide Channel */
|
||||
AHC_TWIN = 0x0008, /* Twin Channel */
|
||||
AHC_AIC7770 = 0x0010,
|
||||
AHC_AIC7850 = 0x0020,
|
||||
AHC_AIC7860 = 0x0021, /* ULTRA version of the aic7850 */
|
||||
AHC_AIC7870 = 0x0040,
|
||||
AHC_AIC7880 = 0x0041,
|
||||
AHC_AIC78X0 = 0x0060, /* PCI Based Controller */
|
||||
AHC_274 = 0x0110, /* EISA Based Controller */
|
||||
AHC_284 = 0x0210, /* VL/ISA Based Controller */
|
||||
AHC_294AU = 0x0421, /* aic7860 based '2940' */
|
||||
AHC_294 = 0x0440, /* PCI Based Controller */
|
||||
AHC_294U = 0x0441, /* ULTRA PCI Based Controller */
|
||||
AHC_394 = 0x0840, /* Twin Channel PCI Controller */
|
||||
AHC_394U = 0x0841, /* ULTRA, Twin Channel PCI Controller */
|
||||
AHC_398 = 0x1040, /* Multi Channel PCI RAID Controller */
|
||||
AHC_398U = 0x1041, /* ULTRA, Multi Channel PCI
|
||||
* RAID Controller
|
||||
*/
|
||||
AHC_39X = 0x1800 /* Multi Channel PCI Adapter */
|
||||
}ahc_type;
|
||||
|
||||
typedef enum {
|
||||
@ -133,11 +138,16 @@ typedef enum {
|
||||
* settings.
|
||||
*/
|
||||
AHC_CHNLB = 0x20, /*
|
||||
* Second controller on 3940
|
||||
* Second controller on 3940/398X
|
||||
* Also encodes the offset in the
|
||||
* SEEPROM for CHNLB info (32)
|
||||
*/
|
||||
}ahc_flag;
|
||||
AHC_CHNLC = 0x40 /*
|
||||
* Third controller on 3985
|
||||
* Also encodes the offset in the
|
||||
* SEEPROM for CHNLC info (64)
|
||||
*/
|
||||
} ahc_flag;
|
||||
|
||||
typedef enum {
|
||||
SCB_FREE = 0x0000,
|
||||
@ -154,7 +164,7 @@ typedef enum {
|
||||
SCB_SENTORDEREDTAG = 0x0400,
|
||||
SCB_MSGOUT_SDTR = 0x0800,
|
||||
SCB_MSGOUT_WDTR = 0x1000
|
||||
}scb_flag;
|
||||
} scb_flag;
|
||||
|
||||
/*
|
||||
* The driver keeps up to MAX_SCB scb structures per card in memory. The SCB
|
||||
@ -198,8 +208,7 @@ struct hardware_scb {
|
||||
*/
|
||||
};
|
||||
|
||||
struct scb
|
||||
{
|
||||
struct scb {
|
||||
struct hardware_scb *hscb;
|
||||
STAILQ_ENTRY(scb) links; /* for chaining */
|
||||
struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
|
||||
@ -209,7 +218,22 @@ struct scb
|
||||
u_int8_t position;/* Position in card's scbarray */
|
||||
};
|
||||
|
||||
struct ahc_data {
|
||||
struct scb_data {
|
||||
struct hardware_scb *hscbs; /* Array of hardware SCBs */
|
||||
struct scb *scbarray[AHC_SCB_MAX]; /* Array of kernel SCBs */
|
||||
STAILQ_HEAD(, scb) free_scbs; /*
|
||||
* Pool of SCBs ready to be assigned
|
||||
* commands to execute.
|
||||
*/
|
||||
u_int8_t numscbs;
|
||||
u_int8_t maxhscbs; /* Number of SCBs on the card */
|
||||
u_int8_t maxscbs; /*
|
||||
* Max SCBs we allocate total including
|
||||
* any that will force us to page SCBs
|
||||
*/
|
||||
};
|
||||
|
||||
struct ahc_softc {
|
||||
#if defined(__FreeBSD__)
|
||||
int unit;
|
||||
#elif defined(__NetBSD__)
|
||||
@ -224,18 +248,14 @@ struct ahc_data {
|
||||
u_int32_t baseport;
|
||||
#endif
|
||||
volatile u_int8_t *maddr;
|
||||
struct hardware_scb *hscbs; /* Array of hardware SCBs */
|
||||
struct scb *scbarray[AHC_SCB_MAX]; /* Array of kernel SCBs */
|
||||
STAILQ_HEAD(, scb) free_scbs; /*
|
||||
* Pool of SCBs ready to be assigned
|
||||
* commands to execute.
|
||||
*/
|
||||
struct scb_data *scb_data;
|
||||
struct scsi_link sc_link;
|
||||
struct scsi_link sc_link_b; /* Second bus for Twin channel cards */
|
||||
STAILQ_HEAD(, scb) waiting_scbs;/*
|
||||
* SCBs waiting ready to go but
|
||||
* waiting for space in the QINFIFO.
|
||||
*/
|
||||
struct scsi_link sc_link;
|
||||
struct scsi_link sc_link_b; /* Second bus for Twin channel cards */
|
||||
u_int8_t activescbs;
|
||||
u_int16_t needsdtr_orig; /* Targets we initiate sync neg with */
|
||||
u_int16_t needwdtr_orig; /* Targets we initiate wide neg with */
|
||||
u_int16_t needsdtr; /* Current list of negotiated targets */
|
||||
@ -247,13 +267,6 @@ struct ahc_data {
|
||||
u_int16_t discenable; /* Targets allowed to disconnect */
|
||||
u_int8_t our_id; /* our scsi id */
|
||||
u_int8_t our_id_b; /* B channel scsi id */
|
||||
u_int8_t numscbs;
|
||||
u_int8_t activescbs;
|
||||
u_int8_t maxhscbs; /* Number of SCBs on the card */
|
||||
u_int8_t maxscbs; /*
|
||||
* Max SCBs we allocate total including
|
||||
* any that will force us to page SCBs
|
||||
*/
|
||||
u_int8_t qcntmask; /*
|
||||
* Mask of valid registers in the
|
||||
* Q*CNT registers.
|
||||
@ -276,6 +289,11 @@ struct ahc_data {
|
||||
u_int8_t in_timeout;
|
||||
};
|
||||
|
||||
struct full_ahc_softc {
|
||||
struct ahc_softc softc;
|
||||
struct scb_data scb_data_storage;
|
||||
};
|
||||
|
||||
/* #define AHC_DEBUG */
|
||||
#ifdef AHC_DEBUG
|
||||
/* Different debugging levels used when AHC_DEBUG is defined */
|
||||
@ -291,20 +309,22 @@ extern int ahc_debug; /* Initialized in i386/scsi/aic7xxx.c */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
|
||||
char *ahc_name __P((struct ahc_data *ahc));
|
||||
char *ahc_name __P((struct ahc_softc *ahc));
|
||||
|
||||
void ahc_reset __P((u_int32_t iobase));
|
||||
struct ahc_data *ahc_alloc __P((int unit, u_int32_t io_base, vm_offset_t maddr, ahc_type type, ahc_flag flags));
|
||||
struct ahc_softc *ahc_alloc __P((int unit, u_int32_t io_base,
|
||||
vm_offset_t maddr, ahc_type type,
|
||||
ahc_flag flags, struct scb_data *scb_data));
|
||||
#elif defined(__NetBSD__)
|
||||
|
||||
#define ahc_name(ahc) (ahc)->sc_dev.dv_xname
|
||||
|
||||
void ahc_reset __P((char *devname, bus_chipset_tag_t bc, bus_io_handle_t ioh));
|
||||
void ahc_construct __P((struct ahc_data *ahc, bus_chipset_tag_t bc, bus_io_handle_t ioh, ahc_type type, ahc_flag flags));
|
||||
void ahc_construct __P((struct ahc_softc *ahc, bus_chipset_tag_t bc, bus_io_handle_t ioh, ahc_type type, ahc_flag flags));
|
||||
#endif
|
||||
void ahc_free __P((struct ahc_data *));
|
||||
int ahc_init __P((struct ahc_data *));
|
||||
int ahc_attach __P((struct ahc_data *));
|
||||
void ahc_free __P((struct ahc_softc *));
|
||||
int ahc_init __P((struct ahc_softc *));
|
||||
int ahc_attach __P((struct ahc_softc *));
|
||||
#if defined(__FreeBSD__)
|
||||
void ahc_intr __P((void *arg));
|
||||
#elif defined(__NetBSD__)
|
||||
|
Loading…
Reference in New Issue
Block a user