1005 lines · c
1/*2 * Product specific probe and attach routines for:3 * aic7901 and aic7902 SCSI controllers4 *5 * Copyright (c) 1994-2001 Justin T. Gibbs.6 * Copyright (c) 2000-2002 Adaptec Inc.7 * All rights reserved.8 *9 * Redistribution and use in source and binary forms, with or without10 * modification, are permitted provided that the following conditions11 * are met:12 * 1. Redistributions of source code must retain the above copyright13 * notice, this list of conditions, and the following disclaimer,14 * without modification.15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer16 * substantially similar to the "NO WARRANTY" disclaimer below17 * ("Disclaimer") and any redistribution must be conditioned upon18 * including a substantially similar Disclaimer requirement for further19 * binary redistribution.20 * 3. Neither the names of the above-listed copyright holders nor the names21 * of any contributors may be used to endorse or promote products derived22 * from this software without specific prior written permission.23 *24 * Alternatively, this software may be distributed under the terms of the25 * GNU General Public License ("GPL") version 2 as published by the Free26 * Software Foundation.27 *28 * NO WARRANTY29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT33 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE39 * POSSIBILITY OF SUCH DAMAGES.40 *41 * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#92 $42 */43 44#include "aic79xx_osm.h"45#include "aic79xx_inline.h"46#include "aic79xx_pci.h"47 48static inline uint64_t49ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)50{51 uint64_t id;52 53 id = subvendor54 | (subdevice << 16)55 | ((uint64_t)vendor << 32)56 | ((uint64_t)device << 48);57 58 return (id);59}60 61#define ID_AIC7902_PCI_REV_A4 0x362#define ID_AIC7902_PCI_REV_B0 0x1063#define SUBID_HP 0x0E1164 65#define DEVID_9005_HOSTRAID(id) ((id) & 0x80)66 67#define DEVID_9005_TYPE(id) ((id) & 0xF)68#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */69#define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */70#define DEVID_9005_TYPE_IROC 0x8 /* Raid(0,1,10) Card */71#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */72 73#define DEVID_9005_MFUNC(id) ((id) & 0x10)74 75#define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)76 77#define SUBID_9005_TYPE(id) ((id) & 0xF)78#define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */79#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */80 81#define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0)82 83#define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)84 85#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6)86#define SUBID_9005_SEEPTYPE_NONE 0x087#define SUBID_9005_SEEPTYPE_4K 0x188 89static ahd_device_setup_t ahd_aic7901_setup;90static ahd_device_setup_t ahd_aic7901A_setup;91static ahd_device_setup_t ahd_aic7902_setup;92static ahd_device_setup_t ahd_aic790X_setup;93 94static const struct ahd_pci_identity ahd_pci_ident_table[] =95{96 /* aic7901 based controllers */97 {98 ID_AHA_29320A,99 ID_ALL_MASK,100 "Adaptec 29320A Ultra320 SCSI adapter",101 ahd_aic7901_setup102 },103 {104 ID_AHA_29320ALP,105 ID_ALL_MASK,106 "Adaptec 29320ALP PCIx Ultra320 SCSI adapter",107 ahd_aic7901_setup108 },109 {110 ID_AHA_29320LPE,111 ID_ALL_MASK,112 "Adaptec 29320LPE PCIe Ultra320 SCSI adapter",113 ahd_aic7901_setup114 },115 /* aic7901A based controllers */116 {117 ID_AHA_29320LP,118 ID_ALL_MASK,119 "Adaptec 29320LP Ultra320 SCSI adapter",120 ahd_aic7901A_setup121 },122 /* aic7902 based controllers */ 123 {124 ID_AHA_29320,125 ID_ALL_MASK,126 "Adaptec 29320 Ultra320 SCSI adapter",127 ahd_aic7902_setup128 },129 {130 ID_AHA_29320B,131 ID_ALL_MASK,132 "Adaptec 29320B Ultra320 SCSI adapter",133 ahd_aic7902_setup134 },135 {136 ID_AHA_39320,137 ID_ALL_MASK,138 "Adaptec 39320 Ultra320 SCSI adapter",139 ahd_aic7902_setup140 },141 {142 ID_AHA_39320_B,143 ID_ALL_MASK,144 "Adaptec 39320 Ultra320 SCSI adapter",145 ahd_aic7902_setup146 },147 {148 ID_AHA_39320_B_DELL,149 ID_ALL_MASK,150 "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",151 ahd_aic7902_setup152 },153 {154 ID_AHA_39320A,155 ID_ALL_MASK,156 "Adaptec 39320A Ultra320 SCSI adapter",157 ahd_aic7902_setup158 },159 {160 ID_AHA_39320D,161 ID_ALL_MASK,162 "Adaptec 39320D Ultra320 SCSI adapter",163 ahd_aic7902_setup164 },165 {166 ID_AHA_39320D_HP,167 ID_ALL_MASK,168 "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",169 ahd_aic7902_setup170 },171 {172 ID_AHA_39320D_B,173 ID_ALL_MASK,174 "Adaptec 39320D Ultra320 SCSI adapter",175 ahd_aic7902_setup176 },177 {178 ID_AHA_39320D_B_HP,179 ID_ALL_MASK,180 "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",181 ahd_aic7902_setup182 },183 /* Generic chip probes for devices we don't know 'exactly' */184 {185 ID_AIC7901 & ID_9005_GENERIC_MASK,186 ID_9005_GENERIC_MASK,187 "Adaptec AIC7901 Ultra320 SCSI adapter",188 ahd_aic7901_setup189 },190 {191 ID_AIC7901A & ID_DEV_VENDOR_MASK,192 ID_DEV_VENDOR_MASK,193 "Adaptec AIC7901A Ultra320 SCSI adapter",194 ahd_aic7901A_setup195 },196 {197 ID_AIC7902 & ID_9005_GENERIC_MASK,198 ID_9005_GENERIC_MASK,199 "Adaptec AIC7902 Ultra320 SCSI adapter",200 ahd_aic7902_setup201 }202};203 204static const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table);205 206#define DEVCONFIG 0x40207#define PCIXINITPAT 0x0000E000ul208#define PCIXINIT_PCI33_66 0x0000E000ul209#define PCIXINIT_PCIX50_66 0x0000C000ul210#define PCIXINIT_PCIX66_100 0x0000A000ul211#define PCIXINIT_PCIX100_133 0x00008000ul212#define PCI_BUS_MODES_INDEX(devconfig) \213 (((devconfig) & PCIXINITPAT) >> 13)214static const char *pci_bus_modes[] =215{216 "PCI bus mode unknown",217 "PCI bus mode unknown",218 "PCI bus mode unknown",219 "PCI bus mode unknown",220 "PCI-X 101-133MHz",221 "PCI-X 67-100MHz",222 "PCI-X 50-66MHz",223 "PCI 33 or 66MHz"224};225 226#define TESTMODE 0x00000800ul227#define IRDY_RST 0x00000200ul228#define FRAME_RST 0x00000100ul229#define PCI64BIT 0x00000080ul230#define MRDCEN 0x00000040ul231#define ENDIANSEL 0x00000020ul232#define MIXQWENDIANEN 0x00000008ul233#define DACEN 0x00000004ul234#define STPWLEVEL 0x00000002ul235#define QWENDIANSEL 0x00000001ul236 237#define DEVCONFIG1 0x44238#define PREQDIS 0x01239 240#define CSIZE_LATTIME 0x0c241#define CACHESIZE 0x000000fful242#define LATTIME 0x0000ff00ul243 244static int ahd_check_extport(struct ahd_softc *ahd);245static void ahd_configure_termination(struct ahd_softc *ahd,246 u_int adapter_control);247static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);248static void ahd_pci_intr(struct ahd_softc *ahd);249 250const struct ahd_pci_identity *251ahd_find_pci_device(ahd_dev_softc_t pci)252{253 uint64_t full_id;254 uint16_t device;255 uint16_t vendor;256 uint16_t subdevice;257 uint16_t subvendor;258 const struct ahd_pci_identity *entry;259 u_int i;260 261 vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);262 device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);263 subvendor = ahd_pci_read_config(pci, PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);264 subdevice = ahd_pci_read_config(pci, PCI_SUBSYSTEM_ID, /*bytes*/2);265 full_id = ahd_compose_id(device,266 vendor,267 subdevice,268 subvendor);269 270 /*271 * Controllers, mask out the IROC/HostRAID bit272 */273 274 full_id &= ID_ALL_IROC_MASK;275 276 for (i = 0; i < ahd_num_pci_devs; i++) {277 entry = &ahd_pci_ident_table[i];278 if (entry->full_id == (full_id & entry->id_mask)) {279 /* Honor exclusion entries. */280 if (entry->name == NULL)281 return (NULL);282 return (entry);283 }284 }285 return (NULL);286}287 288int289ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)290{291 u_int command;292 uint32_t devconfig;293 uint16_t subvendor; 294 int error;295 296 ahd->description = entry->name;297 /*298 * Record if this is an HP board.299 */300 subvendor = ahd_pci_read_config(ahd->dev_softc,301 PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);302 if (subvendor == SUBID_HP)303 ahd->flags |= AHD_HP_BOARD;304 305 error = entry->setup(ahd);306 if (error != 0)307 return (error);308 309 devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);310 if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {311 ahd->chip |= AHD_PCI;312 /* Disable PCIX workarounds when running in PCI mode. */313 ahd->bugs &= ~AHD_PCIX_BUG_MASK;314 } else {315 ahd->chip |= AHD_PCIX;316 }317 ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];318 319 ahd_power_state_change(ahd, AHD_POWER_STATE_D0);320 321 error = ahd_pci_map_registers(ahd);322 if (error != 0)323 return (error);324 325 /*326 * If we need to support high memory, enable dual327 * address cycles. This bit must be set to enable328 * high address bit generation even if we are on a329 * 64bit bus (PCI64BIT set in devconfig).330 */331 if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {332 if (bootverbose)333 printk("%s: Enabling 39Bit Addressing\n",334 ahd_name(ahd));335 devconfig = ahd_pci_read_config(ahd->dev_softc,336 DEVCONFIG, /*bytes*/4);337 devconfig |= DACEN;338 ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,339 devconfig, /*bytes*/4);340 }341 342 /* Ensure busmastering is enabled */343 command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);344 command |= PCIM_CMD_BUSMASTEREN;345 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2);346 347 error = ahd_softc_init(ahd);348 if (error != 0)349 return (error);350 351 ahd->bus_intr = ahd_pci_intr;352 353 error = ahd_reset(ahd, /*reinit*/FALSE);354 if (error != 0)355 return (ENXIO);356 357 ahd->pci_cachesize =358 ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME,359 /*bytes*/1) & CACHESIZE;360 ahd->pci_cachesize *= 4;361 362 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);363 /* See if we have a SEEPROM and perform auto-term */364 error = ahd_check_extport(ahd);365 if (error != 0)366 return (error);367 368 /* Core initialization */369 error = ahd_init(ahd);370 if (error != 0)371 return (error);372 ahd->init_level++;373 374 /*375 * Allow interrupts now that we are completely setup.376 */377 return ahd_pci_map_int(ahd);378}379 380void __maybe_unused381ahd_pci_suspend(struct ahd_softc *ahd)382{383 /*384 * Save chip register configuration data for chip resets385 * that occur during runtime and resume events.386 */387 ahd->suspend_state.pci_state.devconfig =388 ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);389 ahd->suspend_state.pci_state.command =390 ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);391 ahd->suspend_state.pci_state.csize_lattime =392 ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);393 394}395 396void __maybe_unused397ahd_pci_resume(struct ahd_softc *ahd)398{399 ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,400 ahd->suspend_state.pci_state.devconfig, /*bytes*/4);401 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,402 ahd->suspend_state.pci_state.command, /*bytes*/1);403 ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,404 ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);405}406 407/*408 * Perform some simple tests that should catch situations where409 * our registers are invalidly mapped.410 */411int412ahd_pci_test_register_access(struct ahd_softc *ahd)413{414 uint32_t cmd;415 u_int targpcistat;416 u_int pci_status1;417 int error;418 uint8_t hcntrl;419 420 error = EIO;421 422 /*423 * Enable PCI error interrupt status, but suppress NMIs424 * generated by SERR raised due to target aborts.425 */426 cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);427 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,428 cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);429 430 /*431 * First a simple test to see if any432 * registers can be read. Reading433 * HCNTRL has no side effects and has434 * at least one bit that is guaranteed to435 * be zero so it is a good register to436 * use for this test.437 */438 hcntrl = ahd_inb(ahd, HCNTRL);439 if (hcntrl == 0xFF)440 goto fail;441 442 /*443 * Next create a situation where write combining444 * or read prefetching could be initiated by the445 * CPU or host bridge. Our device does not support446 * either, so look for data corruption and/or flaged447 * PCI errors. First pause without causing another448 * chip reset.449 */450 hcntrl &= ~CHIPRST;451 ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);452 while (ahd_is_paused(ahd) == 0)453 ;454 455 /* Clear any PCI errors that occurred before our driver attached. */456 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);457 targpcistat = ahd_inb(ahd, TARGPCISTAT);458 ahd_outb(ahd, TARGPCISTAT, targpcistat);459 pci_status1 = ahd_pci_read_config(ahd->dev_softc,460 PCIR_STATUS + 1, /*bytes*/1);461 ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,462 pci_status1, /*bytes*/1);463 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);464 ahd_outb(ahd, CLRINT, CLRPCIINT);465 466 ahd_outb(ahd, SEQCTL0, PERRORDIS);467 ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);468 if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)469 goto fail;470 471 if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {472 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);473 targpcistat = ahd_inb(ahd, TARGPCISTAT);474 if ((targpcistat & STA) != 0)475 goto fail;476 }477 478 error = 0;479 480fail:481 if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {482 483 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);484 targpcistat = ahd_inb(ahd, TARGPCISTAT);485 486 /* Silently clear any latched errors. */487 ahd_outb(ahd, TARGPCISTAT, targpcistat);488 pci_status1 = ahd_pci_read_config(ahd->dev_softc,489 PCIR_STATUS + 1, /*bytes*/1);490 ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,491 pci_status1, /*bytes*/1);492 ahd_outb(ahd, CLRINT, CLRPCIINT);493 }494 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);495 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);496 return (error);497}498 499/*500 * Check the external port logic for a serial eeprom501 * and termination/cable detection contrls.502 */503static int504ahd_check_extport(struct ahd_softc *ahd)505{506 struct vpd_config vpd;507 struct seeprom_config *sc;508 u_int adapter_control;509 int have_seeprom;510 int error;511 512 sc = ahd->seep_config;513 have_seeprom = ahd_acquire_seeprom(ahd);514 if (have_seeprom) {515 u_int start_addr;516 517 /*518 * Fetch VPD for this function and parse it.519 */520 if (bootverbose) 521 printk("%s: Reading VPD from SEEPROM...",522 ahd_name(ahd));523 524 /* Address is always in units of 16bit words */525 start_addr = ((2 * sizeof(*sc))526 + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;527 528 error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,529 start_addr, sizeof(vpd)/2,530 /*bytestream*/TRUE);531 if (error == 0)532 error = ahd_parse_vpddata(ahd, &vpd);533 if (bootverbose) 534 printk("%s: VPD parsing %s\n",535 ahd_name(ahd),536 error == 0 ? "successful" : "failed");537 538 if (bootverbose) 539 printk("%s: Reading SEEPROM...", ahd_name(ahd));540 541 /* Address is always in units of 16bit words */542 start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');543 544 error = ahd_read_seeprom(ahd, (uint16_t *)sc,545 start_addr, sizeof(*sc)/2,546 /*bytestream*/FALSE);547 548 if (error != 0) {549 printk("Unable to read SEEPROM\n");550 have_seeprom = 0;551 } else {552 have_seeprom = ahd_verify_cksum(sc);553 554 if (bootverbose) {555 if (have_seeprom == 0)556 printk ("checksum error\n");557 else558 printk ("done.\n");559 }560 }561 ahd_release_seeprom(ahd);562 }563 564 if (!have_seeprom) {565 u_int nvram_scb;566 567 /*568 * Pull scratch ram settings and treat them as569 * if they are the contents of an seeprom if570 * the 'ADPT', 'BIOS', or 'ASPI' signature is found571 * in SCB 0xFF. We manually compose the data as 16bit572 * values to avoid endian issues.573 */574 ahd_set_scbptr(ahd, 0xFF);575 nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);576 if (nvram_scb != 0xFF577 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'578 && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'579 && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'580 && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')581 || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'582 && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'583 && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'584 && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')585 || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'586 && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'587 && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'588 && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {589 uint16_t *sc_data;590 int i;591 592 ahd_set_scbptr(ahd, nvram_scb);593 sc_data = (uint16_t *)sc;594 for (i = 0; i < 64; i += 2)595 *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);596 have_seeprom = ahd_verify_cksum(sc);597 if (have_seeprom)598 ahd->flags |= AHD_SCB_CONFIG_USED;599 }600 }601 602#ifdef AHD_DEBUG603 if (have_seeprom != 0604 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {605 uint16_t *sc_data;606 int i;607 608 printk("%s: Seeprom Contents:", ahd_name(ahd));609 sc_data = (uint16_t *)sc;610 for (i = 0; i < (sizeof(*sc)); i += 2)611 printk("\n\t0x%.4x", sc_data[i]);612 printk("\n");613 }614#endif615 616 if (!have_seeprom) {617 if (bootverbose)618 printk("%s: No SEEPROM available.\n", ahd_name(ahd));619 ahd->flags |= AHD_USEDEFAULTS;620 error = ahd_default_config(ahd);621 adapter_control = CFAUTOTERM|CFSEAUTOTERM;622 kfree(ahd->seep_config);623 ahd->seep_config = NULL;624 } else {625 error = ahd_parse_cfgdata(ahd, sc);626 adapter_control = sc->adapter_control;627 }628 if (error != 0)629 return (error);630 631 ahd_configure_termination(ahd, adapter_control);632 633 return (0);634}635 636static void637ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)638{639 int error;640 u_int sxfrctl1;641 uint8_t termctl;642 uint32_t devconfig;643 644 devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);645 devconfig &= ~STPWLEVEL;646 if ((ahd->flags & AHD_STPWLEVEL_A) != 0)647 devconfig |= STPWLEVEL;648 if (bootverbose)649 printk("%s: STPWLEVEL is %s\n",650 ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");651 ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);652 653 /* Make sure current sensing is off. */654 if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {655 (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);656 }657 658 /*659 * Read to sense. Write to set.660 */661 error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);662 if ((adapter_control & CFAUTOTERM) == 0) {663 if (bootverbose)664 printk("%s: Manual Primary Termination\n",665 ahd_name(ahd));666 termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);667 if ((adapter_control & CFSTERM) != 0)668 termctl |= FLX_TERMCTL_ENPRILOW;669 if ((adapter_control & CFWSTERM) != 0)670 termctl |= FLX_TERMCTL_ENPRIHIGH;671 } else if (error != 0) {672 printk("%s: Primary Auto-Term Sensing failed! "673 "Using Defaults.\n", ahd_name(ahd));674 termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;675 }676 677 if ((adapter_control & CFSEAUTOTERM) == 0) {678 if (bootverbose)679 printk("%s: Manual Secondary Termination\n",680 ahd_name(ahd));681 termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);682 if ((adapter_control & CFSELOWTERM) != 0)683 termctl |= FLX_TERMCTL_ENSECLOW;684 if ((adapter_control & CFSEHIGHTERM) != 0)685 termctl |= FLX_TERMCTL_ENSECHIGH;686 } else if (error != 0) {687 printk("%s: Secondary Auto-Term Sensing failed! "688 "Using Defaults.\n", ahd_name(ahd));689 termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;690 }691 692 /*693 * Now set the termination based on what we found.694 */695 sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;696 ahd->flags &= ~AHD_TERM_ENB_A;697 if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {698 ahd->flags |= AHD_TERM_ENB_A;699 sxfrctl1 |= STPWEN;700 }701 /* Must set the latch once in order to be effective. */702 ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);703 ahd_outb(ahd, SXFRCTL1, sxfrctl1);704 705 error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);706 if (error != 0) {707 printk("%s: Unable to set termination settings!\n",708 ahd_name(ahd));709 } else if (bootverbose) {710 printk("%s: Primary High byte termination %sabled\n",711 ahd_name(ahd),712 (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");713 714 printk("%s: Primary Low byte termination %sabled\n",715 ahd_name(ahd),716 (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");717 718 printk("%s: Secondary High byte termination %sabled\n",719 ahd_name(ahd),720 (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");721 722 printk("%s: Secondary Low byte termination %sabled\n",723 ahd_name(ahd),724 (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");725 }726 return;727}728 729#define DPE 0x80730#define SSE 0x40731#define RMA 0x20732#define RTA 0x10733#define STA 0x08734#define DPR 0x01735 736static const char *split_status_source[] =737{738 "DFF0",739 "DFF1",740 "OVLY",741 "CMC",742};743 744static const char *pci_status_source[] =745{746 "DFF0",747 "DFF1",748 "SG",749 "CMC",750 "OVLY",751 "NONE",752 "MSI",753 "TARG"754};755 756static const char *split_status_strings[] =757{758 "%s: Received split response in %s.\n",759 "%s: Received split completion error message in %s\n",760 "%s: Receive overrun in %s\n",761 "%s: Count not complete in %s\n",762 "%s: Split completion data bucket in %s\n",763 "%s: Split completion address error in %s\n",764 "%s: Split completion byte count error in %s\n",765 "%s: Signaled Target-abort to early terminate a split in %s\n"766};767 768static const char *pci_status_strings[] =769{770 "%s: Data Parity Error has been reported via PERR# in %s\n",771 "%s: Target initial wait state error in %s\n",772 "%s: Split completion read data parity error in %s\n",773 "%s: Split completion address attribute parity error in %s\n",774 "%s: Received a Target Abort in %s\n",775 "%s: Received a Master Abort in %s\n",776 "%s: Signal System Error Detected in %s\n",777 "%s: Address or Write Phase Parity Error Detected in %s.\n"778};779 780static void781ahd_pci_intr(struct ahd_softc *ahd)782{783 uint8_t pci_status[8];784 ahd_mode_state saved_modes;785 u_int pci_status1;786 u_int intstat;787 u_int i;788 u_int reg;789 790 intstat = ahd_inb(ahd, INTSTAT);791 792 if ((intstat & SPLTINT) != 0)793 ahd_pci_split_intr(ahd, intstat);794 795 if ((intstat & PCIINT) == 0)796 return;797 798 printk("%s: PCI error Interrupt\n", ahd_name(ahd));799 saved_modes = ahd_save_modes(ahd);800 ahd_dump_card_state(ahd);801 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);802 for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {803 804 if (i == 5)805 continue;806 pci_status[i] = ahd_inb(ahd, reg);807 /* Clear latched errors. So our interrupt deasserts. */808 ahd_outb(ahd, reg, pci_status[i]);809 }810 811 for (i = 0; i < 8; i++) {812 u_int bit;813 814 if (i == 5)815 continue;816 817 for (bit = 0; bit < 8; bit++) {818 819 if ((pci_status[i] & (0x1 << bit)) != 0) {820 const char *s;821 822 s = pci_status_strings[bit];823 if (i == 7/*TARG*/ && bit == 3)824 s = "%s: Signaled Target Abort\n";825 printk(s, ahd_name(ahd), pci_status_source[i]);826 }827 } 828 }829 pci_status1 = ahd_pci_read_config(ahd->dev_softc,830 PCIR_STATUS + 1, /*bytes*/1);831 ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,832 pci_status1, /*bytes*/1);833 ahd_restore_modes(ahd, saved_modes);834 ahd_outb(ahd, CLRINT, CLRPCIINT);835 ahd_unpause(ahd);836}837 838static void839ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)840{841 uint8_t split_status[4];842 uint8_t split_status1[4];843 uint8_t sg_split_status[2];844 uint8_t sg_split_status1[2];845 ahd_mode_state saved_modes;846 u_int i;847 uint16_t pcix_status;848 849 /*850 * Check for splits in all modes. Modes 0 and 1851 * additionally have SG engine splits to look at.852 */853 pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS,854 /*bytes*/2);855 printk("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",856 ahd_name(ahd), pcix_status);857 saved_modes = ahd_save_modes(ahd);858 for (i = 0; i < 4; i++) {859 ahd_set_modes(ahd, i, i);860 861 split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);862 split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);863 /* Clear latched errors. So our interrupt deasserts. */864 ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);865 ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);866 if (i > 1)867 continue;868 sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);869 sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);870 /* Clear latched errors. So our interrupt deasserts. */871 ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);872 ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);873 }874 875 for (i = 0; i < 4; i++) {876 u_int bit;877 878 for (bit = 0; bit < 8; bit++) {879 880 if ((split_status[i] & (0x1 << bit)) != 0)881 printk(split_status_strings[bit], ahd_name(ahd),882 split_status_source[i]);883 884 if (i > 1)885 continue;886 887 if ((sg_split_status[i] & (0x1 << bit)) != 0)888 printk(split_status_strings[bit], ahd_name(ahd), "SG");889 }890 }891 /*892 * Clear PCI-X status bits.893 */894 ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS,895 pcix_status, /*bytes*/2);896 ahd_outb(ahd, CLRINT, CLRSPLTINT);897 ahd_restore_modes(ahd, saved_modes);898}899 900static int901ahd_aic7901_setup(struct ahd_softc *ahd)902{903 904 ahd->chip = AHD_AIC7901;905 ahd->features = AHD_AIC7901_FE;906 return (ahd_aic790X_setup(ahd));907}908 909static int910ahd_aic7901A_setup(struct ahd_softc *ahd)911{912 913 ahd->chip = AHD_AIC7901A;914 ahd->features = AHD_AIC7901A_FE;915 return (ahd_aic790X_setup(ahd));916}917 918static int919ahd_aic7902_setup(struct ahd_softc *ahd)920{921 ahd->chip = AHD_AIC7902;922 ahd->features = AHD_AIC7902_FE;923 return (ahd_aic790X_setup(ahd));924}925 926static int927ahd_aic790X_setup(struct ahd_softc *ahd)928{929 ahd_dev_softc_t pci;930 u_int rev;931 932 pci = ahd->dev_softc;933 rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1);934 if (rev < ID_AIC7902_PCI_REV_A4) {935 printk("%s: Unable to attach to unsupported chip revision %d\n",936 ahd_name(ahd), rev);937 ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);938 return (ENXIO);939 }940 ahd->channel = ahd_get_pci_function(pci) + 'A';941 if (rev < ID_AIC7902_PCI_REV_B0) {942 /*943 * Enable A series workarounds.944 */945 ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG946 | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG947 | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG948 | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG949 | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG950 | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG951 | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG952 | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG953 | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG954 | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG955 | AHD_FAINT_LED_BUG;956 957 /*958 * IO Cell parameter setup.959 */960 AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);961 962 if ((ahd->flags & AHD_HP_BOARD) == 0)963 AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);964 } else {965 /* This is revision B and newer. */966 extern uint32_t aic79xx_slowcrc;967 u_int devconfig1;968 969 ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS970 | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY971 | AHD_BUSFREEREV_BUG;972 ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;973 974 /* If the user requested that the SLOWCRC bit to be set. */975 if (aic79xx_slowcrc)976 ahd->features |= AHD_AIC79XXB_SLOWCRC;977 978 /*979 * Some issues have been resolved in the 7901B.980 */981 if ((ahd->features & AHD_MULTI_FUNC) != 0)982 ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;983 984 /*985 * IO Cell parameter setup.986 */987 AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);988 AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);989 AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);990 991 /*992 * Set the PREQDIS bit for H2B which disables some workaround993 * that doesn't work on regular PCI busses.994 * XXX - Find out exactly what this does from the hardware995 * folks!996 */997 devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);998 ahd_pci_write_config(pci, DEVCONFIG1,999 devconfig1|PREQDIS, /*bytes*/1);1000 devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);1001 }1002 1003 return (0);1004}1005