summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/aic7xxx')
-rw-r--r--sys/dev/aic7xxx/ahc_eisa.c2
-rw-r--r--sys/dev/aic7xxx/ahc_pci.c35
-rw-r--r--sys/dev/aic7xxx/aic7770.c29
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c182
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h86
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg7
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq169
-rw-r--r--sys/dev/aic7xxx/aic7xxx_93cx6.c2
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.c25
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.h17
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h41
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c25
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.h17
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c289
14 files changed, 529 insertions, 397 deletions
diff --git a/sys/dev/aic7xxx/ahc_eisa.c b/sys/dev/aic7xxx/ahc_eisa.c
index e1262c7..79db102 100644
--- a/sys/dev/aic7xxx/ahc_eisa.c
+++ b/sys/dev/aic7xxx/ahc_eisa.c
@@ -180,7 +180,7 @@ aic7770_map_registers(struct ahc_softc *ahc)
}
int
-aic7770_map_int(struct ahc_softc *ahc)
+aic7770_map_int(struct ahc_softc *ahc, int irq)
{
int zero;
diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c
index 0703145..3519dce 100644
--- a/sys/dev/aic7xxx/ahc_pci.c
+++ b/sys/dev/aic7xxx/ahc_pci.c
@@ -213,3 +213,38 @@ ahc_pci_map_int(struct ahc_softc *ahc)
ahc->platform_data->irq_res_type = SYS_RES_IRQ;
return (0);
}
+
+void
+ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
+{
+ uint32_t cap;
+ u_int cap_offset;
+
+ /*
+ * Traverse the capability list looking for
+ * the power management capability.
+ */
+ cap = 0;
+ cap_offset = ahc_pci_read_config(ahc->dev_softc,
+ PCIR_CAP_PTR, /*bytes*/1);
+ while (cap_offset != 0) {
+
+ cap = ahc_pci_read_config(ahc->dev_softc,
+ cap_offset, /*bytes*/4);
+ if ((cap & 0xFF) == 1
+ && ((cap >> 16) & 0x3) > 0) {
+ uint32_t pm_control;
+
+ pm_control = ahc_pci_read_config(ahc->dev_softc,
+ cap_offset + 4,
+ /*bytes*/4);
+ pm_control &= ~0x3;
+ pm_control |= new_state;
+ ahc_pci_write_config(ahc->dev_softc,
+ cap_offset + 4,
+ pm_control, /*bytes*/2);
+ break;
+ }
+ cap_offset = (cap >> 8) & 0xFF;
+ }
+}
diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c
index 9c53eb4..c493da2 100644
--- a/sys/dev/aic7xxx/aic7770.c
+++ b/sys/dev/aic7xxx/aic7770.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7770.c#4 $
+ * $Id: //depot/src/aic7xxx/aic7770.c#8 $
*
* $FreeBSD$
*/
@@ -101,6 +101,8 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
struct ahc_probe_config probe_config;
int error;
u_int hostconf;
+ u_int irq;
+ u_int intdef;
ahc_init_probe_config(&probe_config);
error = entry->setup(ahc->dev_softc, &probe_config);
@@ -114,11 +116,30 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
probe_config.description = entry->name;
error = ahc_softc_init(ahc, &probe_config);
- error = aic7770_map_int(ahc);
+ error = ahc_reset(ahc);
if (error != 0)
return (error);
- error = ahc_reset(ahc);
+ /* Make sure we have a valid interrupt vector */
+ intdef = ahc_inb(ahc, INTDEF);
+ irq = intdef & VECTOR;
+ switch (irq) {
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 14:
+ case 15:
+ break;
+ default:
+ printf("aic7770_config: illegal irq setting %d\n", intdef);
+ return (ENXIO);
+ }
+
+ if ((intdef & EDGE_TRIG) != 0)
+ ahc->flags |= AHC_EDGE_INTERRUPT;
+
+ error = aic7770_map_int(ahc, irq);
if (error != 0)
return (error);
@@ -135,7 +156,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
/* Get the primary channel information */
if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
- ahc->flags |= AHC_CHANNEL_B_PRIMARY;
+ ahc->flags |= 1;
if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
ahc->flags |= AHC_USEDEFAULTS;
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index d0d0bcd..f6dc8c7 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.c#30 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#34 $
*
* $FreeBSD$
*/
@@ -66,9 +66,17 @@ char *ahc_chip_names[] =
"aic7892",
"aic7899"
};
-const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
+static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
-struct hard_error_entry hard_error[] = {
+/*
+ * Hardware error codes.
+ */
+struct ahc_hard_error_entry {
+ uint8_t errno;
+ char *errmesg;
+};
+
+static struct ahc_hard_error_entry ahc_hard_errors[] = {
{ ILLHADDR, "Illegal Host Access" },
{ ILLSADDR, "Illegal Sequencer Address referrenced" },
{ ILLOPCODE, "Illegal Opcode in sequencer program" },
@@ -78,9 +86,9 @@ struct hard_error_entry hard_error[] = {
{ PCIERRSTAT, "PCI Error detected" },
{ CIOPARERR, "CIOBUS Parity Error" },
};
-const u_int num_errors = NUM_ELEMENTS(hard_error);
+static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors);
-struct phase_table_entry phase_table[] =
+static struct ahc_phase_table_entry ahc_phase_table[] =
{
{ P_DATAOUT, MSG_NOOP, "in Data-out phase" },
{ P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
@@ -98,14 +106,14 @@ struct phase_table_entry phase_table[] =
* In most cases we only wish to itterate over real phases, so
* exclude the last element from the count.
*/
-const u_int num_phases = NUM_ELEMENTS(phase_table) - 1;
+static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1;
/*
* Valid SCSIRATE values. (p. 3-17)
* Provides a mapping of tranfer periods in ns to the proper value to
* stick in the scsixfer reg.
*/
-struct ahc_syncrate ahc_syncrates[] =
+static struct ahc_syncrate ahc_syncrates[] =
{
/* ultra2 fast/ultra period rate */
{ 0x42, 0x000, 9, "80.0" },
@@ -226,10 +234,11 @@ static int ahc_handle_target_cmd(struct ahc_softc *ahc,
* Restart the sequencer program from address zero
*/
void
-restart_sequencer(struct ahc_softc *ahc)
+ahc_restart(struct ahc_softc *ahc)
{
- pause_sequencer(ahc);
+ ahc_pause(ahc);
+
ahc_outb(ahc, SCSISIGO, 0); /* De-assert BSY */
ahc_outb(ahc, MSG_OUT, MSG_NOOP); /* No message to send */
ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);
@@ -252,11 +261,21 @@ restart_sequencer(struct ahc_softc *ahc)
ahc_outb(ahc, CCSGCTL, 0);
ahc_outb(ahc, CCSCBCTL, 0);
}
+ /*
+ * If we were in the process of DMA'ing SCB data into
+ * an SCB, replace that SCB on the free list. This prevents
+ * an SCB leak.
+ */
+ if ((ahc_inb(ahc, SEQ_FLAGS2) & SCB_DMA) != 0) {
+ ahc_add_curscb_to_free_list(ahc);
+ ahc_outb(ahc, SEQ_FLAGS2,
+ ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
+ }
ahc_outb(ahc, MWI_RESIDUAL, 0);
ahc_outb(ahc, SEQCTL, FASTMODE);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
/************************* Input/Output Queues ********************************/
@@ -337,14 +356,14 @@ ahc_handle_brkadrint(struct ahc_softc *ahc)
* We upset the sequencer :-(
* Lookup the error message
*/
- int i, error, num_errors;
+ int i;
+ int error;
error = ahc_inb(ahc, ERROR);
- num_errors = sizeof(hard_error)/sizeof(hard_error[0]);
for (i = 0; error != 1 && i < num_errors; i++)
error >>= 1;
printf("%s: brkadrint, %s at seqaddr = 0x%x\n",
- ahc_name(ahc), hard_error[i].errmesg,
+ ahc_name(ahc), ahc_hard_errors[i].errmesg,
ahc_inb(ahc, SEQADDR0) |
(ahc_inb(ahc, SEQADDR1) << 8));
@@ -630,7 +649,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
"Lastphase = 0x%x, Curphase = 0x%x\n",
ahc_name(ahc), devinfo.channel, devinfo.target,
lastphase, ahc_inb(ahc, SCSISIGI));
- restart_sequencer(ahc);
+ ahc_restart(ahc);
return;
}
case HOST_MSG_LOOP:
@@ -660,7 +679,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* we got here. Just punt the message.
*/
ahc_clear_intstat(ahc);
- restart_sequencer(ahc);
+ ahc_restart(ahc);
return;
}
@@ -746,13 +765,13 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
scb = ahc_lookup_scb(ahc, scbindex);
for (i = 0; i < num_phases; i++) {
- if (lastphase == phase_table[i].phase)
+ if (lastphase == ahc_phase_table[i].phase)
break;
}
ahc_print_path(ahc, scb);
printf("data overrun detected %s."
" Tag == 0x%x.\n",
- phase_table[i].phasemsg,
+ ahc_phase_table[i].phasemsg,
scb->hscb->tag);
ahc_print_path(ahc, scb);
printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n",
@@ -855,7 +874,7 @@ unpause:
* a SEQINT, so we should restart it when
* we're done.
*/
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
void
@@ -894,7 +913,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
if (status == 0) {
printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc));
ahc_outb(ahc, CLRINT, CLRSCSIINT);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
return;
}
}
@@ -972,10 +991,10 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
errorphase = lastphase;
for (i = 0; i < num_phases; i++) {
- if (errorphase == phase_table[i].phase)
+ if (errorphase == ahc_phase_table[i].phase)
break;
}
- mesg_out = phase_table[i].mesg_out;
+ mesg_out = ahc_phase_table[i].mesg_out;
if (scb != NULL)
ahc_print_path(ahc, scb);
else
@@ -984,7 +1003,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scsirate = ahc_inb(ahc, SCSIRATE);
printf("parity error detected %s. "
"SEQADDR(0x%x) SCSIRATE(0x%x)\n",
- phase_table[i].phasemsg,
+ ahc_phase_table[i].phasemsg,
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8),
scsirate);
@@ -1015,7 +1034,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_outb(ahc, MSG_OUT, mesg_out);
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else if ((status & BUSFREE) != 0
&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
u_int lastphase;
@@ -1171,17 +1190,18 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
printf("%s: ", ahc_name(ahc));
}
for (i = 0; i < num_phases; i++) {
- if (lastphase == phase_table[i].phase)
+ if (lastphase == ahc_phase_table[i].phase)
break;
}
printf("Unexpected busfree %s\n"
"SEQADDR == 0x%x\n",
- phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0)
+ ahc_phase_table[i].phasemsg,
+ ahc_inb(ahc, SEQADDR0)
| (ahc_inb(ahc, SEQADDR1) << 8));
}
ahc_clear_msg_state(ahc);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
- restart_sequencer(ahc);
+ ahc_restart(ahc);
} else if ((status & SELTO) != 0) {
u_int scbptr;
@@ -1218,7 +1238,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_freeze_devq(ahc, scb);
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
- restart_sequencer(ahc);
+ ahc_restart(ahc);
} else {
printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",
ahc_name(ahc), status);
@@ -1287,7 +1307,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
ahc_outb(ahc, HCNTRL, ahc->unpause);
do {
ahc_delay(200);
- } while (!sequencer_paused(ahc));
+ } while (!ahc_is_paused(ahc));
}
if (stepping) {
ahc_outb(ahc, SIMODE0, simode0);
@@ -1450,7 +1470,8 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc,
/* Can't do DT on an SE bus */
*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
}
- } else if ((ahc->features & AHC_ULTRA) != 0) {
+ } else if ((ahc->features & AHC_ULTRA) != 0
+ && (ahc->flags & AHC_ULTRA_DISABLED) == 0) {
maxsync = AHC_SYNCRATE_ULTRA;
} else {
maxsync = AHC_SYNCRATE_FAST;
@@ -1667,7 +1688,7 @@ ahc_update_target_msg_request(struct ahc_softc *ahc,
if (ahc->targ_msg_req != targ_msg_req_orig) {
/* Update the message request bit for this target */
if (!paused)
- pause_sequencer(ahc);
+ ahc_pause(ahc);
ahc_outb(ahc, TARGET_MSG_REQUEST,
ahc->targ_msg_req & 0xFF);
@@ -1675,7 +1696,7 @@ ahc_update_target_msg_request(struct ahc_softc *ahc,
(ahc->targ_msg_req >> 8) & 0xFF);
if (!paused)
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
}
@@ -1981,6 +2002,23 @@ ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
role);
}
+struct ahc_phase_table_entry*
+ahc_lookup_phase_entry(int phase)
+{
+ struct ahc_phase_table_entry *entry;
+ int i;
+
+ /*
+ * num_phases doesn't include the default entry which
+ * will be returned if the phase doesn't match.
+ */
+ for (i = 0, entry = ahc_phase_table; i < num_phases; i++) {
+ if (phase == entry->phase)
+ break;
+ }
+ return (entry);
+}
+
void
ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target,
u_int lun, char channel, role_t role)
@@ -2254,7 +2292,7 @@ ahc_clear_msg_state(struct ahc_softc *ahc)
ahc->msgout_len = 0;
ahc->msgin_index = 0;
ahc->msg_type = MSG_TYPE_NONE;
- if ((ahc_inb(ahc, SCSISIGI) & ATNI) == 0) {
+ if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) {
/*
* The target didn't care to respond to our
* message request, so clear ATN.
@@ -2875,7 +2913,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
"offset %x, options %x\n",
ahc_name(ahc), devinfo->channel,
devinfo->target, devinfo->lun,
- ahc->msgin_buf[3], saved_width,
+ saved_width, ahc->msgin_buf[3],
saved_offset, saved_ppr_options,
bus_width, period, offset, ppr_options);
}
@@ -2902,7 +2940,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
CAM_BDR_SENT,
"Bus Device Reset Received",
/*verbose_level*/0);
- restart_sequencer(ahc);
+ ahc_restart(ahc);
done = MSGLOOP_TERMINATED;
break;
case MSG_ABORT_TAG:
@@ -3356,29 +3394,37 @@ ahc_softc_insert(struct ahc_softc *ahc)
{
struct ahc_softc *list_ahc;
-#ifdef AHC_SUPPORT_PCI
+#if AHC_PCI_CONFIG > 0
/*
* Second Function PCI devices need to inherit some
- * settings from function 0. We assume that function 0
- * will always be found prior to function 1.
+ * settings from function 0.
*/
if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI
- && ahc_get_pci_function(ahc->dev_softc) == 1) {
+ && (ahc->features & AHC_MULTI_FUNC) != 0) {
TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
ahc_dev_softc_t list_pci;
ahc_dev_softc_t pci;
list_pci = list_ahc->dev_softc;
pci = ahc->dev_softc;
- if (ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)
- && ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
- && ahc_get_pci_function(list_pci) == 0) {
- ahc->flags &= ~AHC_BIOS_ENABLED;
- ahc->flags |=
- list_ahc->flags & AHC_BIOS_ENABLED;
- ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
- ahc->flags |=
- list_ahc->flags & AHC_CHANNEL_B_PRIMARY;
+ if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
+ && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) {
+ struct ahc_softc *master;
+ struct ahc_softc *slave;
+
+ if (ahc_get_pci_function(list_pci) == 0) {
+ master = list_ahc;
+ slave = ahc;
+ } else {
+ master = ahc;
+ slave = list_ahc;
+ }
+ slave->flags &= ~AHC_BIOS_ENABLED;
+ slave->flags |=
+ master->flags & AHC_BIOS_ENABLED;
+ slave->flags &= ~AHC_PRIMARY_CHANNEL;
+ slave->flags |=
+ master->flags & AHC_PRIMARY_CHANNEL;
break;
}
}
@@ -3519,7 +3565,7 @@ ahc_reset(struct ahc_softc *ahc)
* It contains settings that affect termination and we don't want
* to disturb the integrity of the bus.
*/
- pause_sequencer(ahc);
+ ahc_pause(ahc);
sxfrctl1_b = 0;
if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
u_int sblkctl;
@@ -3957,7 +4003,7 @@ ahc_controller_info(struct ahc_softc *ahc, char *buf)
len = sprintf(buf, "Twin Channel, A SCSI Id=%d, "
"B SCSI Id=%d, primary %c, ",
ahc->our_id, ahc->our_id_b,
- ahc->flags & AHC_CHANNEL_B_PRIMARY ? 'B': 'A');
+ (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A');
else {
const char *type;
@@ -4134,6 +4180,7 @@ ahc_init(struct ahc_softc *ahc)
}
ahc_outb(ahc, SEQ_FLAGS, 0);
+ ahc_outb(ahc, SEQ_FLAGS2, 0);
if (ahc->scb_data->maxhscbs < AHC_SCB_MAX) {
ahc->flags |= AHC_PAGESCBS;
@@ -4218,6 +4265,8 @@ ahc_init(struct ahc_softc *ahc)
ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8)
| ahc_inb(ahc, ULTRA_ENB);
}
+ if ((ahc->flags & AHC_ULTRA_DISABLED) != 0)
+ ultraenb = 0;
if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
max_targ = 7;
@@ -4274,6 +4323,9 @@ ahc_init(struct ahc_softc *ahc)
offset = MAX_OFFSET_ULTRA2;
} else
offset = ahc_inb(ahc, TARG_OFFSET + i);
+ if ((scsirate & ~WIDEXFER) == 0 && offset != 0)
+ /* Set to the lowest sync rate, 5MHz */
+ scsirate |= 0x1c;
maxsync = AHC_SYNCRATE_ULTRA2;
if ((ahc->features & AHC_DT) != 0)
maxsync = AHC_SYNCRATE_DT;
@@ -4302,6 +4354,8 @@ ahc_init(struct ahc_softc *ahc)
if (tinfo->user.period != 0)
tinfo->user.offset = ~0;
}
+ if (tinfo->user.period == 0)
+ tinfo->user.offset = 0;
if ((scsirate & WIDEXFER) != 0
&& (ahc->features & AHC_WIDE) != 0)
tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
@@ -4438,12 +4492,12 @@ ahc_init(struct ahc_softc *ahc)
* never settle, so don't complain if we
* fail here.
*/
- pause_sequencer(ahc);
+ ahc_pause(ahc);
for (wait = 5000;
(ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
wait--)
ahc_delay(100);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
return (0);
}
@@ -4466,7 +4520,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
intstat = 0;
do {
ahc_intr(ahc);
- pause_sequencer(ahc);
+ ahc_pause(ahc);
ahc_clear_critical_section(ahc);
if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
break;
@@ -5397,7 +5451,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD,
channel, ROLE_UNKNOWN);
- pause_sequencer(ahc);
+ ahc_pause(ahc);
/* Make sure the sequencer is in a safe location. */
ahc_clear_critical_section(ahc);
@@ -5512,9 +5566,9 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
}
if (restart_needed)
- restart_sequencer(ahc);
+ ahc_restart(ahc);
else
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
return found;
}
@@ -5813,7 +5867,7 @@ ahc_loadseq(struct ahc_softc *ahc)
memcpy(ahc->critical_sections, cs_table, cs_count);
}
ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
- restart_sequencer(ahc);
+ ahc_restart(ahc);
if (bootverbose)
printf(" %d instructions downloaded\n", downloaded);
@@ -6215,7 +6269,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
ahc->flags |= AHC_TARGETROLE;
if ((ahc->features & AHC_MULTIROLE) == 0)
ahc->flags &= ~AHC_INITIATORROLE;
- pause_sequencer(ahc);
+ ahc_pause(ahc);
ahc_loadseq(ahc);
ahc_unlock(ahc, &s);
}
@@ -6284,7 +6338,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
SLIST_INIT(&lstate->accept_tios);
SLIST_INIT(&lstate->immed_notifies);
ahc_lock(ahc, &s);
- pause_sequencer(ahc);
+ ahc_pause(ahc);
if (target != CAM_TARGET_WILDCARD) {
tstate->enabled_luns[lun] = lstate;
ahc->enabled_luns++;
@@ -6348,7 +6402,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
scsiseq |= ENSELI;
ahc_outb(ahc, SCSISEQ, scsiseq);
}
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
ahc_unlock(ahc, &s);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_print_path(ccb->ccb_h.path);
@@ -6398,7 +6452,7 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
xpt_free_path(lstate->path);
free(lstate, M_DEVBUF);
- pause_sequencer(ahc);
+ ahc_pause(ahc);
/* Can we clean up the target too? */
if (target != CAM_TARGET_WILDCARD) {
tstate->enabled_luns[lun] = NULL;
@@ -6451,11 +6505,11 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
printf("Configuring Initiator Mode\n");
ahc->flags &= ~AHC_TARGETROLE;
ahc->flags |= AHC_INITIATORROLE;
- pause_sequencer(ahc);
+ ahc_pause(ahc);
ahc_loadseq(ahc);
}
}
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
ahc_unlock(ahc, &s);
}
}
@@ -6537,11 +6591,11 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
ahc_outb(ahc, HS_MAILBOX, hs_mailbox);
} else {
if (!paused)
- pause_sequencer(ahc);
+ ahc_pause(ahc);
ahc_outb(ahc, KERNEL_TQINPOS,
ahc->tqinfifonext & HOST_TQINPOS);
if (!paused)
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
}
}
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index f8e81ec..329a58d 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.h#18 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.h#22 $
*
* $FreeBSD$
*/
@@ -286,50 +286,56 @@ typedef enum {
* chip/controller's configuration.
*/
typedef enum {
- AHC_FNONE = 0x000,
- AHC_PAGESCBS = 0x001,/* Enable SCB paging */
- AHC_CHANNEL_B_PRIMARY = 0x002,/*
- * On twin channel adapters, probe
- * channel B first since it is the
- * primary bus.
+ AHC_FNONE = 0x000,
+ AHC_PRIMARY_CHANNEL = 0x003,/*
+ * The channel that should
+ * be probed first.
*/
- AHC_USEDEFAULTS = 0x004,/*
+ AHC_USEDEFAULTS = 0x004,/*
* For cards without an seeprom
* or a BIOS to initialize the chip's
* SRAM, we use the default target
* settings.
*/
- AHC_SEQUENCER_DEBUG = 0x008,
- AHC_SHARED_SRAM = 0x010,
- AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */
- AHC_RESET_BUS_A = 0x040,
- AHC_RESET_BUS_B = 0x080,
- AHC_EXTENDED_TRANS_A = 0x100,
- AHC_EXTENDED_TRANS_B = 0x200,
- AHC_TERM_ENB_A = 0x400,
- AHC_TERM_ENB_B = 0x800,
- AHC_INITIATORROLE = 0x1000,/*
+ AHC_SEQUENCER_DEBUG = 0x008,
+ AHC_SHARED_SRAM = 0x010,
+ AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */
+ AHC_RESET_BUS_A = 0x040,
+ AHC_RESET_BUS_B = 0x080,
+ AHC_EXTENDED_TRANS_A = 0x100,
+ AHC_EXTENDED_TRANS_B = 0x200,
+ AHC_TERM_ENB_A = 0x400,
+ AHC_TERM_ENB_B = 0x800,
+ AHC_INITIATORROLE = 0x1000,/*
* Allow initiator operations on
* this controller.
*/
- AHC_TARGETROLE = 0x2000,/*
+ AHC_TARGETROLE = 0x2000,/*
* Allow target operations on this
* controller.
*/
- AHC_NEWEEPROM_FMT = 0x4000,
- AHC_RESOURCE_SHORTAGE = 0x8000,
- AHC_TQINFIFO_BLOCKED = 0x10000,/* Blocked waiting for ATIOs */
- AHC_INT50_SPEEDFLEX = 0x20000,/*
+ AHC_NEWEEPROM_FMT = 0x4000,
+ AHC_RESOURCE_SHORTAGE = 0x8000,
+ AHC_TQINFIFO_BLOCKED = 0x10000,/* Blocked waiting for ATIOs */
+ AHC_INT50_SPEEDFLEX = 0x20000,/*
* Internal 50pin connector
* sits behind an aic3860
*/
- AHC_SCB_BTT = 0x40000,/*
+ AHC_SCB_BTT = 0x40000,/*
* The busy targets table is
* stored in SCB space rather
* than SRAM.
*/
- AHC_BIOS_ENABLED = 0x80000,
- AHC_ALL_INTERRUPTS = 0x100000
+ AHC_BIOS_ENABLED = 0x80000,
+ AHC_ALL_INTERRUPTS = 0x100000,
+ AHC_ULTRA_DISABLED = 0x200000, /*
+ * The precision resistor for
+ * ultra transmission speeds is
+ * missing, so we must limit
+ * ourselves to fast SCSI.
+ */
+ AHC_PAGESCBS = 0x400000, /* Enable SCB paging */
+ AHC_EDGE_INTERRUPT = 0x800000 /* Device uses edge triggered ints */
} ahc_flag;
/*
@@ -705,32 +711,14 @@ extern struct ahc_syncrate ahc_syncrates[];
/***************************** Lookup Tables **********************************/
/*
- * Textual descriptions of the different chips indexed by chip type.
- */
-extern char *ahc_chip_names[];
-extern const u_int num_chip_names;
-
-/*
- * Hardware error codes.
- */
-struct hard_error_entry {
- uint8_t errno;
- char *errmesg;
-};
-extern struct hard_error_entry hard_error[];
-extern const u_int num_errors;
-
-/*
* Phase -> name and message out response
* to parity errors in each phase table.
*/
-struct phase_table_entry {
+struct ahc_phase_table_entry {
uint8_t phase;
uint8_t mesg_out; /* Message response to parity errors */
char *phasemsg;
};
-extern struct phase_table_entry phase_table[];
-extern const u_int num_phases;
/************************** Serial EEPROM Format ******************************/
@@ -782,7 +770,8 @@ struct seeprom_config {
#define CFMULTILUN 0x0020 /* SCSI low byte term (284x cards) */
#define CFRESETB 0x0040 /* reset SCSI bus at boot */
#define CFCLUSTERENB 0x0080 /* Cluster Enable */
-#define CFCHNLBPRIMARY 0x0100 /* aic7895 probe B channel first */
+#define CFBOOTCHAN 0x0300 /* probe this channel first */
+#define CFBOOTCHANSHIFT 8
#define CFSEAUTOTERM 0x0400 /* Ultra2 Perform secondary Auto Term*/
#define CFSELOWTERM 0x0800 /* Ultra2 secondary low term */
#define CFSEHIGHTERM 0x1000 /* Ultra2 secondary high term */
@@ -806,6 +795,7 @@ struct seeprom_config {
uint16_t res_1[10]; /* words 20-29 */
uint16_t signature; /* Signature == 0x250 */
#define CFSIGNATURE 0x250
+#define CFSIGNATURE2 0x300
uint16_t checksum; /* word 31 */
};
@@ -1137,8 +1127,10 @@ int ahc_search_disc_list(struct ahc_softc *ahc, int target,
void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
int ahc_reset_channel(struct ahc_softc *ahc, char channel,
int initiate_reset);
-void restart_sequencer(struct ahc_softc *ahc);
+void ahc_restart(struct ahc_softc *ahc);
/*************************** Utility Functions ********************************/
+struct ahc_phase_table_entry*
+ ahc_lookup_phase_entry(int phase);
void ahc_compile_devinfo(struct ahc_devinfo *devinfo,
u_int our_id, u_int target,
u_int lun, char channel,
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index 9dabe15..93e7d8e 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.reg#12 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.reg#14 $
*
* $FreeBSD$
*/
@@ -877,6 +877,7 @@ register DFSTATUS {
address 0x094
access_mode RO
bit PRELOAD_AVAIL 0x80
+ bit DFCACHETH 0x40
bit DWORDEMP 0x20
bit MREQPEND 0x10
bit HDONE 0x08
@@ -1456,6 +1457,10 @@ scratch_ram {
size 1
}
+ SEQ_FLAGS2 {
+ size 1
+ bit SCB_DMA 0x01
+ }
/*
* These are reserved registers in the card's scratch ram. Some of
* the values are specified in the AHA2742 technical reference manual
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index b490f62..6152c77 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.seq#20 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.seq#23 $
*
* $FreeBSD$
*/
@@ -88,7 +88,6 @@ BEGIN_CRITICAL
cmp KERNEL_QINPOS, A je poll_for_work_loop;
}
mov ARG_1, NEXT_QUEUED_SCB;
-END_CRITICAL
/*
* We have at least one queued SCB now and we don't have any
@@ -101,6 +100,8 @@ END_CRITICAL
/* In the non-paging case, the SCBID == hardware SCB index */
mov SCBPTR, ARG_1;
}
+ or SEQ_FLAGS2, SCB_DMA;
+END_CRITICAL
dma_queued_scb:
/*
* DMA the SCB from host ram into the current SCB location.
@@ -128,6 +129,7 @@ BEGIN_CRITICAL
} else {
inc QINPOS;
}
+ and SEQ_FLAGS2, ~SCB_DMA;
END_CRITICAL
start_waiting:
/*
@@ -692,69 +694,75 @@ sg_advance:
adc SCB_RESIDUAL_SGPTR[2],A;
adc SCB_RESIDUAL_SGPTR[3],A ret;
+if ((ahc->features & AHC_CMD_CHAN) != 0) {
+disable_ccsgen:
+ test CCSGCTL, CCSGEN jz return;
+ test CCSGCTL, CCSGDONE jz .;
+disable_ccsgen_fetch_done:
+ clr CCSGCTL;
+ test CCSGCTL, CCSGEN jnz .;
+ ret;
idle_loop:
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- /* Did we just finish fetching segs? */
- cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
+ /* Did we just finish fetching segs? */
+ cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
- /* Are we actively fetching segments? */
- test CCSGCTL, CCSGEN jnz return;
+ /* Are we actively fetching segments? */
+ test CCSGCTL, CCSGEN jnz return;
- /*
- * Do we need any more segments?
- */
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
+ /*
+ * Do we need any more segments?
+ */
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
- /*
- * Do we have any prefetch left???
- */
- cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
+ /*
+ * Do we have any prefetch left???
+ */
+ cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
- /*
- * Need to fetch segments, but we can only do that
- * if the command channel is completely idle. Make
- * sure we don't have an SCB prefetch going on.
- */
- test CCSCBCTL, CCSCBEN jnz return;
+ /*
+ * Need to fetch segments, but we can only do that
+ * if the command channel is completely idle. Make
+ * sure we don't have an SCB prefetch going on.
+ */
+ test CCSCBCTL, CCSCBEN jnz return;
- /*
- * We fetch a "cacheline aligned" and sized amount of data
- * so we don't end up referencing a non-existant page.
- * Cacheline aligned is in quotes because the kernel will
- * set the prefetch amount to a reasonable level if the
- * cacheline size is unknown.
- */
- mvi CCHCNT, SG_PREFETCH_CNT;
- and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
- bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
- mvi CCSGCTL, CCSGEN|CCSGRESET ret;
+ /*
+ * We fetch a "cacheline aligned" and sized amount of data
+ * so we don't end up referencing a non-existant page.
+ * Cacheline aligned is in quotes because the kernel will
+ * set the prefetch amount to a reasonable level if the
+ * cacheline size is unknown.
+ */
+ mvi CCHCNT, SG_PREFETCH_CNT;
+ and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
+ bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
+ mvi CCSGCTL, CCSGEN|CCSGRESET ret;
idle_sgfetch_complete:
- clr CCSGCTL;
- test CCSGCTL, CCSGEN jnz .;
- and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
+ call disable_ccsgen_fetch_done;
+ and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
idle_sg_avail:
- if ((ahc->features & AHC_ULTRA2) != 0) {
- /* Does the hardware have space for another SG entry? */
- test DFSTATUS, PRELOAD_AVAIL jz return;
- bmov HADDR, CCSGRAM, 4;
- bmov SINDEX, CCSGRAM, 1;
- test SINDEX, 0x1 jz . + 2;
- xor DATA_COUNT_ODD, 0x1;
- bmov HCNT[0], SINDEX, 1;
- bmov HCNT[1], CCSGRAM, 2;
- bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
- call sg_advance;
- mov SINDEX, SCB_RESIDUAL_SGPTR[0];
- test DATA_COUNT_ODD, 0x1 jz . + 2;
- or SINDEX, ODD_SEG;
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
- or SINDEX, LAST_SEG;
- mov SG_CACHE_PRE, SINDEX;
- /* Load the segment by writing DFCNTRL again */
- mov DFCNTRL, DMAPARAMS;
- }
- ret;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ /* Does the hardware have space for another SG entry? */
+ test DFSTATUS, PRELOAD_AVAIL jz return;
+ bmov HADDR, CCSGRAM, 4;
+ bmov SINDEX, CCSGRAM, 1;
+ test SINDEX, 0x1 jz . + 2;
+ xor DATA_COUNT_ODD, 0x1;
+ bmov HCNT[0], SINDEX, 1;
+ bmov HCNT[1], CCSGRAM, 2;
+ bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
+ call sg_advance;
+ mov SINDEX, SCB_RESIDUAL_SGPTR[0];
+ test DATA_COUNT_ODD, 0x1 jz . + 2;
+ or SINDEX, ODD_SEG;
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
+ or SINDEX, LAST_SEG;
+ mov SG_CACHE_PRE, SINDEX;
+ /* Load the segment by writing DFCNTRL again */
+ mov DFCNTRL, DMAPARAMS;
}
+ ret;
+}
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
/*
@@ -1149,12 +1157,6 @@ data_phase_finish:
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
test SSTAT1, REQINIT jz .;
test SSTAT1,PHASEMIS jz data_phase_loop;
-
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- /* Kill off any pending prefetch */
- clr CCSGCTL;
- test CCSGCTL, CCSGEN jnz .;
- }
}
data_phase_done:
@@ -1166,8 +1168,7 @@ data_phase_done:
*/
if ((ahc->features & AHC_CMD_CHAN) != 0) {
/* Kill off any pending prefetch */
- clr CCSGCTL;
- test CCSGCTL, CCSGEN jnz .;
+ call disable_ccsgen;
}
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
@@ -1648,12 +1649,27 @@ mesgin_identify:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
mov ARG_1 call findSCB;
} else {
- mov SCBPTR, RETURN_1;
+ mov SCBPTR, ARG_1;
}
if ((ahc->flags & AHC_SCB_BTT) != 0) {
jmp setup_SCB_id_lun_okay;
} else {
- jmp setup_SCB_id_okay;
+ /*
+ * We only allow one untagged command per-target
+ * at a time. So, if the lun doesn't match, look
+ * for a tag message.
+ */
+ mov A, SCB_LUN;
+ cmp SAVED_LUN, A je setup_SCB_id_lun_okay;
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ /*
+ * findSCB removes the SCB from the
+ * disconnected list, so we must replace
+ * it there should this SCB be for another
+ * lun.
+ */
+ call cleanup_scb;
+ }
}
/*
@@ -1710,10 +1726,14 @@ setup_SCB_id_lun_okay:
test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
and SCB_CONTROL,~DISCONNECTED;
test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged;
- mov A, SCBPTR;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mov A, SCBPTR;
+ }
mvi ARG_1, SCB_LIST_NULL;
mov SAVED_SCSIID call set_busy_target;
- mov SCBPTR, A;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mov SCBPTR, A;
+ }
setup_SCB_tagged:
mvi SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
call set_transfer_settings;
@@ -1724,7 +1744,7 @@ setup_SCB_tagged:
not_found_cleanup_scb:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
- call add_scb_to_free_list;
+ call cleanup_scb;
}
not_found:
mvi NO_MATCH call set_seqint;
@@ -2056,6 +2076,7 @@ dma_scb_hang_wait:
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
+ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
/*
* The PCI module no longer intends to perform
* a PCI transaction and HDONE has not come true.
@@ -2131,6 +2152,16 @@ dma_finish:
test DFCNTRL, HDMAEN jnz .;
ret;
+/*
+ * Restore an SCB that failed to match an incoming reselection
+ * to the correct/safe state. If the SCB is for a disconnected
+ * transaction, it must be returned to the disconnected list.
+ * If it is not in the disconnected state, it must be free.
+ */
+cleanup_scb:
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list;
+ }
add_scb_to_free_list:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
BEGIN_CRITICAL
diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.c b/sys/dev/aic7xxx/aic7xxx_93cx6.c
index 42078a5..684c608 100644
--- a/sys/dev/aic7xxx/aic7xxx_93cx6.c
+++ b/sys/dev/aic7xxx/aic7xxx_93cx6.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#5 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#7 $
*
* $FreeBSD$
*/
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c
index 1ccf51c..8d9fb21 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.c
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.c
@@ -123,7 +123,7 @@ ahc_attach(struct ahc_softc *ahc)
* declared it the primary channel.
*/
if ((ahc->features & AHC_TWIN) != 0
- && (ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) {
+ && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
bus_id = 1;
bus_id2 = 0;
} else {
@@ -214,7 +214,7 @@ ahc_attach(struct ahc_softc *ahc)
fail:
if ((ahc->features & AHC_TWIN) != 0
- && (ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) {
+ && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
ahc->platform_data->sim_b = sim;
ahc->platform_data->path_b = path;
ahc->platform_data->sim = sim2;
@@ -1239,12 +1239,12 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->flags |= SCB_ACTIVE;
if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
- pause_sequencer(ahc);
+ ahc_pause(ahc);
if ((ahc->flags & AHC_PAGESCBS) == 0)
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
ahc_outb(ahc, SCB_TAG, scb->hscb->tag);
ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else {
ahc_queue_scb(ahc, scb);
}
@@ -1423,7 +1423,7 @@ ahc_timeout(void *arg)
/* Previous timeout took care of me already */
printf("%s: Timedout SCB already complete. "
"Interrupts may not be functioning.\n", ahc_name(ahc));
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1440,11 +1440,7 @@ ahc_timeout(void *arg)
*/
last_phase = ahc_inb(ahc, LASTPHASE);
- for (i = 0; i < num_phases; i++) {
- if (last_phase == phase_table[i].phase)
- break;
- }
- printf("%s", phase_table[i].phasemsg);
+ printf("%s", ahc_lookup_phase_entry(last_phase)->phasemsg);
printf(", SEQADDR == 0x%x\n",
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
@@ -1534,6 +1530,7 @@ bus_reset:
ccbh = &scb->io_ctx->ccb_h;
scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, scb, newtimeout);
+ ahc_unpause(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1552,7 +1549,7 @@ bus_reset:
ahc_done(ahc, scb);
/* Will clear us from the bus */
- restart_sequencer(ahc);
+ ahc_restart(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1565,7 +1562,7 @@ bus_reset:
active_scb->flags |= SCB_DEVICE_RESET;
active_scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else {
int disconnected;
@@ -1579,7 +1576,7 @@ bus_reset:
/* Hung target selection. Goto busfree */
printf("%s: Hung target selection\n",
ahc_name(ahc));
- restart_sequencer(ahc);
+ ahc_restart(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1659,7 +1656,7 @@ bus_reset:
ahc_outb(ahc, SCBPTR, saved_scbptr);
scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, (caddr_t)scb, 2 * hz);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else {
/* Go "immediatly" to the bus reset */
/* This shouldn't happen */
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.h b/sys/dev/aic7xxx/aic7xxx_freebsd.h
index 1aeba2d..59b6e97 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.h
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.h
@@ -49,7 +49,7 @@
#include <sys/queue.h>
#if NPCI > 0
-#define AHC_SUPPORT_PCI 1
+#define AHC_PCI_CONFIG 1
#ifdef AHC_ALLOW_MEMIO
#include <machine/bus_memio.h>
#endif
@@ -404,7 +404,7 @@ ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
}
/********************************** PCI ***************************************/
-#ifdef AHC_SUPPORT_PCI
+#ifdef AHC_PCI_CONFIG
static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
int reg, int width);
static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
@@ -446,10 +446,21 @@ ahc_get_pci_bus(ahc_dev_softc_t pci)
{
return (pci_get_bus(pci));
}
+
+typedef enum
+{
+ AHC_POWER_STATE_D0,
+ AHC_POWER_STATE_D1,
+ AHC_POWER_STATE_D2,
+ AHC_POWER_STATE_D3
+} ahc_power_state;
+
+void ahc_power_state_change(struct ahc_softc *ahc,
+ ahc_power_state new_state);
#endif
/******************************** VL/EISA *************************************/
int aic7770_map_registers(struct ahc_softc *ahc);
-int aic7770_map_int(struct ahc_softc *ahc);
+int aic7770_map_int(struct ahc_softc *ahc, int irq);
/********************************* Debug **************************************/
static __inline void ahc_print_path(struct ahc_softc *, struct scb *);
diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h
index a13e376..16edaba 100644
--- a/sys/dev/aic7xxx/aic7xxx_inline.h
+++ b/sys/dev/aic7xxx/aic7xxx_inline.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#15 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#17 $
*
* $FreeBSD$
*/
@@ -37,10 +37,10 @@
#define _AIC7XXX_INLINE_H_
/************************* Sequencer Execution Control ************************/
-static __inline int sequencer_paused(struct ahc_softc *ahc);
+static __inline int ahc_is_paused(struct ahc_softc *ahc);
static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
-static __inline void pause_sequencer(struct ahc_softc *ahc);
-static __inline void unpause_sequencer(struct ahc_softc *ahc);
+static __inline void ahc_pause(struct ahc_softc *ahc);
+static __inline void ahc_unpause(struct ahc_softc *ahc);
/*
* Work around any chip bugs related to halting sequencer execution.
@@ -62,7 +62,7 @@ ahc_pause_bug_fix(struct ahc_softc *ahc)
* Returns non-zero status if the sequencer is stopped.
*/
static __inline int
-sequencer_paused(struct ahc_softc *ahc)
+ahc_is_paused(struct ahc_softc *ahc)
{
return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
}
@@ -75,7 +75,7 @@ sequencer_paused(struct ahc_softc *ahc)
* for critical sections.
*/
static __inline void
-pause_sequencer(struct ahc_softc *ahc)
+ahc_pause(struct ahc_softc *ahc)
{
ahc_outb(ahc, HCNTRL, ahc->pause);
@@ -83,7 +83,7 @@ pause_sequencer(struct ahc_softc *ahc)
* Since the sequencer can disable pausing in a critical section, we
* must loop until it actually stops.
*/
- while (sequencer_paused(ahc) == 0)
+ while (ahc_is_paused(ahc) == 0)
;
ahc_pause_bug_fix(ahc);
@@ -100,7 +100,7 @@ pause_sequencer(struct ahc_softc *ahc)
* condition.
*/
static __inline void
-unpause_sequencer(struct ahc_softc *ahc)
+ahc_unpause(struct ahc_softc *ahc)
{
if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
ahc_outb(ahc, HCNTRL, ahc->unpause);
@@ -345,10 +345,10 @@ ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
} else {
if ((ahc->features & AHC_AUTOPAUSE) == 0)
- pause_sequencer(ahc);
+ ahc_pause(ahc);
ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
if ((ahc->features & AHC_AUTOPAUSE) == 0)
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
}
@@ -412,14 +412,23 @@ ahc_intr(struct ahc_softc *ahc)
* completion queues. This avoids a costly PCI bus read in
* most cases.
*/
- intstat = 0;
- if ((queuestat = ahc_check_cmdcmpltqueues(ahc)) != 0)
+ if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
+ && (queuestat = ahc_check_cmdcmpltqueues(ahc)) != 0)
intstat = CMDCMPLT;
-
- if ((intstat & INT_PEND) == 0
- || (ahc->flags & AHC_ALL_INTERRUPTS) != 0) {
-
+ else {
intstat = ahc_inb(ahc, INTSTAT);
+ /*
+ * We can't generate queuestat once above
+ * or we are exposed to a race when our
+ * interrupt is shared with another device.
+ * if instat showed a command complete interrupt,
+ * but our first generation of queue stat
+ * "just missed" the delivery of this transaction,
+ * we would clear the command complete interrupt
+ * below without ever servicing the completed
+ * command.
+ */
+ queuestat = ahc_check_cmdcmpltqueues(ahc);
#if AHC_PCI_CONFIG > 0
if (ahc->unsolicited_ints > 500
&& (ahc->chip & AHC_PCI) != 0
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index 1ccf51c..8d9fb21 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -123,7 +123,7 @@ ahc_attach(struct ahc_softc *ahc)
* declared it the primary channel.
*/
if ((ahc->features & AHC_TWIN) != 0
- && (ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) {
+ && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
bus_id = 1;
bus_id2 = 0;
} else {
@@ -214,7 +214,7 @@ ahc_attach(struct ahc_softc *ahc)
fail:
if ((ahc->features & AHC_TWIN) != 0
- && (ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) {
+ && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
ahc->platform_data->sim_b = sim;
ahc->platform_data->path_b = path;
ahc->platform_data->sim = sim2;
@@ -1239,12 +1239,12 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->flags |= SCB_ACTIVE;
if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
- pause_sequencer(ahc);
+ ahc_pause(ahc);
if ((ahc->flags & AHC_PAGESCBS) == 0)
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
ahc_outb(ahc, SCB_TAG, scb->hscb->tag);
ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else {
ahc_queue_scb(ahc, scb);
}
@@ -1423,7 +1423,7 @@ ahc_timeout(void *arg)
/* Previous timeout took care of me already */
printf("%s: Timedout SCB already complete. "
"Interrupts may not be functioning.\n", ahc_name(ahc));
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1440,11 +1440,7 @@ ahc_timeout(void *arg)
*/
last_phase = ahc_inb(ahc, LASTPHASE);
- for (i = 0; i < num_phases; i++) {
- if (last_phase == phase_table[i].phase)
- break;
- }
- printf("%s", phase_table[i].phasemsg);
+ printf("%s", ahc_lookup_phase_entry(last_phase)->phasemsg);
printf(", SEQADDR == 0x%x\n",
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
@@ -1534,6 +1530,7 @@ bus_reset:
ccbh = &scb->io_ctx->ccb_h;
scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, scb, newtimeout);
+ ahc_unpause(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1552,7 +1549,7 @@ bus_reset:
ahc_done(ahc, scb);
/* Will clear us from the bus */
- restart_sequencer(ahc);
+ ahc_restart(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1565,7 +1562,7 @@ bus_reset:
active_scb->flags |= SCB_DEVICE_RESET;
active_scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else {
int disconnected;
@@ -1579,7 +1576,7 @@ bus_reset:
/* Hung target selection. Goto busfree */
printf("%s: Hung target selection\n",
ahc_name(ahc));
- restart_sequencer(ahc);
+ ahc_restart(ahc);
ahc_unlock(ahc, &s);
return;
}
@@ -1659,7 +1656,7 @@ bus_reset:
ahc_outb(ahc, SCBPTR, saved_scbptr);
scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, (caddr_t)scb, 2 * hz);
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
} else {
/* Go "immediatly" to the bus reset */
/* This shouldn't happen */
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h
index 1aeba2d..59b6e97 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.h
+++ b/sys/dev/aic7xxx/aic7xxx_osm.h
@@ -49,7 +49,7 @@
#include <sys/queue.h>
#if NPCI > 0
-#define AHC_SUPPORT_PCI 1
+#define AHC_PCI_CONFIG 1
#ifdef AHC_ALLOW_MEMIO
#include <machine/bus_memio.h>
#endif
@@ -404,7 +404,7 @@ ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
}
/********************************** PCI ***************************************/
-#ifdef AHC_SUPPORT_PCI
+#ifdef AHC_PCI_CONFIG
static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
int reg, int width);
static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
@@ -446,10 +446,21 @@ ahc_get_pci_bus(ahc_dev_softc_t pci)
{
return (pci_get_bus(pci));
}
+
+typedef enum
+{
+ AHC_POWER_STATE_D0,
+ AHC_POWER_STATE_D1,
+ AHC_POWER_STATE_D2,
+ AHC_POWER_STATE_D3
+} ahc_power_state;
+
+void ahc_power_state_change(struct ahc_softc *ahc,
+ ahc_power_state new_state);
#endif
/******************************** VL/EISA *************************************/
int aic7770_map_registers(struct ahc_softc *ahc);
-int aic7770_map_int(struct ahc_softc *ahc);
+int aic7770_map_int(struct ahc_softc *ahc, int irq);
/********************************* Debug **************************************/
static __inline void ahc_print_path(struct ahc_softc *, struct scb *);
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index 15cf078..02a73d4 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#16 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#19 $
*
* $FreeBSD$
*/
@@ -63,84 +63,84 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
return (id);
}
-#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
-#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
-#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
-#define ID_9005_SISL_MASK 0x000FFFFF00000000ull
-#define ID_9005_SISL_ID 0x0005900500000000ull
-#define ID_AIC7850 0x5078900400000000ull
-#define ID_AHA_2910_15_20_30C 0x5078900478509004ull
-#define ID_AIC7855 0x5578900400000000ull
-#define ID_AIC7859 0x3860900400000000ull
-#define ID_AHA_2930CU 0x3860900438699004ull
-#define ID_AIC7860 0x6078900400000000ull
-#define ID_AIC7860C 0x6078900478609004ull
-#define ID_AHA_1480A 0x6075900400000000ull
-#define ID_AHA_2940AU_0 0x6178900400000000ull
-#define ID_AHA_2940AU_1 0x6178900478619004ull
-#define ID_AHA_2940AU_CN 0x2178900478219004ull
-#define ID_AHA_2930C_VAR 0x6038900438689004ull
-
-#define ID_AIC7870 0x7078900400000000ull
-#define ID_AHA_2940 0x7178900400000000ull
-#define ID_AHA_3940 0x7278900400000000ull
-#define ID_AHA_398X 0x7378900400000000ull
-#define ID_AHA_2944 0x7478900400000000ull
-#define ID_AHA_3944 0x7578900400000000ull
-#define ID_AHA_4944 0x7678900400000000ull
-
-#define ID_AIC7880 0x8078900400000000ull
-#define ID_AIC7880_B 0x8078900478809004ull
-#define ID_AHA_2940U 0x8178900400000000ull
-#define ID_AHA_3940U 0x8278900400000000ull
-#define ID_AHA_2944U 0x8478900400000000ull
-#define ID_AHA_3944U 0x8578900400000000ull
-#define ID_AHA_398XU 0x8378900400000000ull
-#define ID_AHA_4944U 0x8678900400000000ull
-#define ID_AHA_2940UB 0x8178900478819004ull
-#define ID_AHA_2930U 0x8878900478889004ull
-#define ID_AHA_2940U_PRO 0x8778900478879004ull
-#define ID_AHA_2940U_CN 0x0078900478009004ull
-
-#define ID_AIC7895 0x7895900478959004ull
-#define ID_AIC7895_ARO 0x7890900478939004ull
-#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull
-#define ID_AHA_2940U_DUAL 0x7895900478919004ull
-#define ID_AHA_3940AU 0x7895900478929004ull
-#define ID_AHA_3944AU 0x7895900478949004ull
-
-#define ID_AIC7890 0x001F9005000F9005ull
-#define ID_AIC7890_ARO 0x00139005000F9005ull
-#define ID_AAA_131U2 0x0013900500039005ull
-#define ID_AHA_2930U2 0x0011900501819005ull
-#define ID_AHA_2940U2B 0x00109005A1009005ull
-#define ID_AHA_2940U2_OEM 0x0010900521809005ull
-#define ID_AHA_2940U2 0x00109005A1809005ull
-#define ID_AHA_2950U2B 0x00109005E1009005ull
-
-#define ID_AIC7892 0x008F9005FFFF9005ull
-#define ID_AIC7892_ARO 0x00839005FFFF9005ull
-#define ID_AHA_29160 0x00809005E2A09005ull
-#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull
-#define ID_AHA_29160N 0x0080900562A09005ull
-#define ID_AHA_29160C 0x0080900562209005ull
-#define ID_AHA_29160B 0x00809005E2209005ull
-#define ID_AHA_19160B 0x0081900562A19005ull
-
-#define ID_AIC7896 0x005F9005FFFF9005ull
-#define ID_AIC7896_ARO 0x00539005FFFF9005ull
-#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull
-#define ID_AHA_3950U2B_1 0x00509005F5009005ull
-#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull
-#define ID_AHA_3950U2D_1 0x00519005B5009005ull
-
-#define ID_AIC7899 0x00CF9005FFFF9005ull
-#define ID_AIC7899_ARO 0x00C39005FFFF9005ull
-#define ID_AHA_3960D 0x00C09005F6209005ull /* AKA AHA-39160 */
-#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull
-
-#define ID_AIC7810 0x1078900400000000ull
-#define ID_AIC7815 0x7815900400000000ull
+#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
+#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
+#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
+#define ID_9005_SISL_MASK 0x000FFFFF00000000ull
+#define ID_9005_SISL_ID 0x0005900500000000ull
+#define ID_AIC7850 0x5078900400000000ull
+#define ID_AHA_2902_04_10_15_20_30C 0x5078900478509004ull
+#define ID_AIC7855 0x5578900400000000ull
+#define ID_AIC7859 0x3860900400000000ull
+#define ID_AHA_2930CU 0x3860900438699004ull
+#define ID_AIC7860 0x6078900400000000ull
+#define ID_AIC7860C 0x6078900478609004ull
+#define ID_AHA_1480A 0x6075900400000000ull
+#define ID_AHA_2940AU_0 0x6178900400000000ull
+#define ID_AHA_2940AU_1 0x6178900478619004ull
+#define ID_AHA_2940AU_CN 0x2178900478219004ull
+#define ID_AHA_2930C_VAR 0x6038900438689004ull
+
+#define ID_AIC7870 0x7078900400000000ull
+#define ID_AHA_2940 0x7178900400000000ull
+#define ID_AHA_3940 0x7278900400000000ull
+#define ID_AHA_398X 0x7378900400000000ull
+#define ID_AHA_2944 0x7478900400000000ull
+#define ID_AHA_3944 0x7578900400000000ull
+#define ID_AHA_4944 0x7678900400000000ull
+
+#define ID_AIC7880 0x8078900400000000ull
+#define ID_AIC7880_B 0x8078900478809004ull
+#define ID_AHA_2940U 0x8178900400000000ull
+#define ID_AHA_3940U 0x8278900400000000ull
+#define ID_AHA_2944U 0x8478900400000000ull
+#define ID_AHA_3944U 0x8578900400000000ull
+#define ID_AHA_398XU 0x8378900400000000ull
+#define ID_AHA_4944U 0x8678900400000000ull
+#define ID_AHA_2940UB 0x8178900478819004ull
+#define ID_AHA_2930U 0x8878900478889004ull
+#define ID_AHA_2940U_PRO 0x8778900478879004ull
+#define ID_AHA_2940U_CN 0x0078900478009004ull
+
+#define ID_AIC7895 0x7895900478959004ull
+#define ID_AIC7895_ARO 0x7890900478939004ull
+#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull
+#define ID_AHA_2940U_DUAL 0x7895900478919004ull
+#define ID_AHA_3940AU 0x7895900478929004ull
+#define ID_AHA_3944AU 0x7895900478949004ull
+
+#define ID_AIC7890 0x001F9005000F9005ull
+#define ID_AIC7890_ARO 0x00139005000F9005ull
+#define ID_AAA_131U2 0x0013900500039005ull
+#define ID_AHA_2930U2 0x0011900501819005ull
+#define ID_AHA_2940U2B 0x00109005A1009005ull
+#define ID_AHA_2940U2_OEM 0x0010900521809005ull
+#define ID_AHA_2940U2 0x00109005A1809005ull
+#define ID_AHA_2950U2B 0x00109005E1009005ull
+
+#define ID_AIC7892 0x008F9005FFFF9005ull
+#define ID_AIC7892_ARO 0x00839005FFFF9005ull
+#define ID_AHA_29160 0x00809005E2A09005ull
+#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull
+#define ID_AHA_29160N 0x0080900562A09005ull
+#define ID_AHA_29160C 0x0080900562209005ull
+#define ID_AHA_29160B 0x00809005E2209005ull
+#define ID_AHA_19160B 0x0081900562A19005ull
+
+#define ID_AIC7896 0x005F9005FFFF9005ull
+#define ID_AIC7896_ARO 0x00539005FFFF9005ull
+#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull
+#define ID_AHA_3950U2B_1 0x00509005F5009005ull
+#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull
+#define ID_AHA_3950U2D_1 0x00519005B5009005ull
+
+#define ID_AIC7899 0x00CF9005FFFF9005ull
+#define ID_AIC7899_ARO 0x00C39005FFFF9005ull
+#define ID_AHA_3960D 0x00C09005F6209005ull
+#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull
+
+#define ID_AIC7810 0x1078900400000000ull
+#define ID_AIC7815 0x7815900400000000ull
#define DEVID_9005_TYPE(id) ((id) & 0xF)
#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
@@ -212,8 +212,7 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000
#define SUBID_9005_CARD_SEDIFF_MASK 0x8000
-static ahc_device_setup_t ahc_aic7850_setup;
-static ahc_device_setup_t ahc_aic7855_setup;
+static ahc_device_setup_t ahc_aic785X_setup;
static ahc_device_setup_t ahc_aic7860_setup;
static ahc_device_setup_t ahc_apa1480_setup;
static ahc_device_setup_t ahc_aic7870_setup;
@@ -239,10 +238,10 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
{
/* aic7850 based controllers */
{
- ID_AHA_2910_15_20_30C,
+ ID_AHA_2902_04_10_15_20_30C,
ID_ALL_MASK,
- "Adaptec 2910/15/20/30C SCSI adapter",
- ahc_aic7850_setup
+ "Adaptec 2902/04/10/15/20/30C SCSI adapter",
+ ahc_aic785X_setup
},
/* aic7860 based controllers */
{
@@ -544,13 +543,13 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
ID_AIC7850 & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
"Adaptec aic7850 SCSI adapter",
- ahc_aic7850_setup
+ ahc_aic785X_setup
},
{
ID_AIC7855 & ID_DEV_VENDOR_MASK,
ID_DEV_VENDOR_MASK,
"Adaptec aic7855 SCSI adapter",
- ahc_aic7855_setup
+ ahc_aic785X_setup
},
{
ID_AIC7859 & ID_DEV_VENDOR_MASK,
@@ -636,6 +635,7 @@ const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
#define DEVCONFIG 0x40
#define SCBSIZE32 0x00010000ul /* aic789X only */
+#define REXTVALID 0x00001000ul /* ultra cards only */
#define MPORTMODE 0x00000400ul /* aic7870 only */
#define RAMPSM 0x00000200ul /* aic7870 only */
#define VOLSENSE 0x00000100ul
@@ -652,16 +652,6 @@ const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
#define CACHESIZE 0x0000003ful /* only 5 bits */
#define LATTIME 0x0000ff00ul
-typedef enum
-{
- AHC_POWER_STATE_D0,
- AHC_POWER_STATE_D1,
- AHC_POWER_STATE_D2,
- AHC_POWER_STATE_D3
-} ahc_power_state;
-
-static void ahc_power_state_change(struct ahc_softc *ahc,
- ahc_power_state new_state);
static int ahc_ext_scbram_present(struct ahc_softc *ahc);
static void ahc_scbram_config(struct ahc_softc *ahc, int enable,
int pcheck, int fast, int large);
@@ -771,7 +761,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
/* Remeber how the card was setup in case there is no SEEPROM */
if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
- pause_sequencer(ahc);
+ ahc_pause(ahc);
if ((ahc->features & AHC_ULTRA2) != 0)
our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
else
@@ -887,6 +877,20 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if ((sxfrctl1 & STPWEN) != 0)
ahc->flags |= AHC_TERM_ENB_A;
+ /*
+ * We cannot perform ULTRA speeds without
+ * the presense of the external precision
+ * resistor.
+ */
+ if ((ahc->features & AHC_ULTRA) != 0) {
+ uint32_t devconfig;
+
+ devconfig = ahc_pci_read_config(ahc->dev_softc,
+ DEVCONFIG, /*bytes*/4);
+ if ((devconfig & REXTVALID) == 0)
+ ahc->flags |= AHC_ULTRA_DISABLED;
+ }
+
/* Core initialization */
error = ahc_init(ahc);
if (error != 0)
@@ -900,41 +904,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
return (0);
}
-static void
-ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
-{
- uint32_t cap;
- u_int cap_offset;
-
- /*
- * Traverse the capability list looking for
- * the power management capability.
- */
- cap = 0;
- cap_offset = ahc_pci_read_config(ahc->dev_softc,
- PCIR_CAP_PTR, /*bytes*/1);
- while (cap_offset != 0) {
-
- cap = ahc_pci_read_config(ahc->dev_softc,
- cap_offset, /*bytes*/4);
- if ((cap & 0xFF) == 1
- && ((cap >> 16) & 0x3) > 0) {
- uint32_t pm_control;
-
- pm_control = ahc_pci_read_config(ahc->dev_softc,
- cap_offset + 4,
- /*bytes*/4);
- pm_control &= ~0x3;
- pm_control |= new_state;
- ahc_pci_write_config(ahc->dev_softc,
- cap_offset + 4,
- pm_control, /*bytes*/2);
- break;
- }
- cap_offset = (cap >> 8) & 0xFF;
- }
-}
-
/*
* Test for the presense of external sram in an
* "unshared" configuration.
@@ -1184,32 +1153,37 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
}
sd.sd_chip = C56_66;
}
+ release_seeprom(&sd);
}
-#if 0
if (!have_seeprom) {
/*
* Pull scratch ram settings and treat them as
* if they are the contents of an seeprom if
* the 'ADPT' signature is found in SCB2.
+ * We manually compose the data as 16bit values
+ * to avoid endian issues.
*/
ahc_outb(ahc, SCBPTR, 2);
if (ahc_inb(ahc, SCB_BASE) == 'A'
&& ahc_inb(ahc, SCB_BASE + 1) == 'D'
&& ahc_inb(ahc, SCB_BASE + 2) == 'P'
&& ahc_inb(ahc, SCB_BASE + 3) == 'T') {
- uint8_t *sc_bytes;
+ uint16_t *sc_data;
int i;
- sc_bytes = (uint8_t *)&sc;
- for (i = 0; i < 64; i++)
- sc_bytes[i] = ahc_inb(ahc, TARG_SCSIRATE + i);
- /* Byte 0x1c is stored in byte 4 of SCB2 */
- sc_bytes[0x1c] = ahc_inb(ahc, SCB_BASE + 4);
+ sc_data = (uint16_t *)&sc;
+ for (i = 0; i < 32; i++) {
+ uint16_t val;
+ int j;
+
+ j = i * 2;
+ val = ahc_inb(ahc, SRAM_BASE + j)
+ | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
+ }
have_seeprom = verify_cksum(&sc);
}
}
-#endif
if (!have_seeprom) {
if (bootverbose)
@@ -1295,9 +1269,8 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
if (sc.adapter_control & CFRESETB)
scsi_conf |= RESET_SCSI;
- if ((sc.adapter_control & CFCHNLBPRIMARY) != 0
- && (ahc->features & AHC_MULTI_FUNC) != 0)
- ahc->flags |= AHC_CHANNEL_B_PRIMARY;
+ ahc->flags |=
+ (sc.adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
if (sc.bios_control & CFEXTEND)
ahc->flags |= AHC_EXTENDED_TRANS_A;
@@ -1312,7 +1285,8 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
ultraenb = 0;
}
- if (sc.signature == CFSIGNATURE) {
+ if (sc.signature == CFSIGNATURE
+ || sc.signature == CFSIGNATURE2) {
uint32_t devconfig;
/* Honor the STPWLEVEL settings */
@@ -1356,10 +1330,11 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
have_autoterm = FALSE;
}
- if (have_autoterm)
+ if (have_autoterm) {
+ acquire_seeprom(ahc, &sd);
configure_termination(ahc, &sd, adapter_control, sxfrctl1);
-
- release_seeprom(&sd);
+ release_seeprom(&sd);
+ }
}
static void
@@ -1800,28 +1775,22 @@ ahc_pci_intr(struct ahc_softc *ahc)
ahc_outb(ahc, CLRINT, CLRPARERR);
}
- unpause_sequencer(ahc);
+ ahc_unpause(ahc);
}
static int
-ahc_aic7850_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
+ahc_aic785X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
{
+ uint8_t rev;
+
probe_config->channel = 'A';
probe_config->chip = AHC_AIC7850;
probe_config->features = AHC_AIC7850_FE;
probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG
| AHC_PCI_MWI_BUG;
- return (0);
-}
-
-static int
-ahc_aic7855_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
-{
- probe_config->channel = 'A';
- probe_config->chip = AHC_AIC7855;
- probe_config->features = AHC_AIC7855_FE;
- probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG
- | AHC_PCI_MWI_BUG;
+ rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+ if (rev >= 1)
+ probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG;
return (0);
}
OpenPOWER on IntegriCloud