diff options
Diffstat (limited to 'sys/dev/aic7xxx')
-rw-r--r-- | sys/dev/aic7xxx/ahc_eisa.c | 2 | ||||
-rw-r--r-- | sys/dev/aic7xxx/ahc_pci.c | 35 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7770.c | 29 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 182 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 86 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.reg | 7 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 169 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_93cx6.c | 2 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_freebsd.c | 25 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_freebsd.h | 17 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_inline.h | 41 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.c | 25 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.h | 17 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_pci.c | 289 |
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 *)≻ - 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 *)≻ + 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); } |