📄 aic7xxx_pci.c
字号:
/* aic7896/97 based controllers */ { ID_AHA_3950U2B_0, ID_ALL_MASK, "Adaptec 3950B Ultra2 SCSI adapter", ahc_aic7896_setup }, { ID_AHA_3950U2B_1, ID_ALL_MASK, "Adaptec 3950B Ultra2 SCSI adapter", ahc_aic7896_setup }, { ID_AHA_3950U2D_0, ID_ALL_MASK, "Adaptec 3950D Ultra2 SCSI adapter", ahc_aic7896_setup }, { ID_AHA_3950U2D_1, ID_ALL_MASK, "Adaptec 3950D Ultra2 SCSI adapter", ahc_aic7896_setup }, { ID_AIC7896_ARO, ID_ALL_MASK, "Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)", ahc_aic7896_setup }, /* aic7899 based controllers */ { ID_AHA_3960D, ID_ALL_MASK, "Adaptec 3960D Ultra160 SCSI adapter", ahc_aic7899_setup }, { ID_AHA_3960D_CPQ, ID_ALL_MASK, "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", ahc_aic7899_setup }, { ID_AIC7899_ARO, ID_ALL_MASK, "Adaptec aic7899 Ultra160 SCSI adapter (ARO)", ahc_aic7899_setup }, /* Generic chip probes for devices we don't know 'exactly' */ { ID_AIC7850 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7850 SCSI adapter", ahc_aic785X_setup }, { ID_AIC7855 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7855 SCSI adapter", ahc_aic785X_setup }, { ID_AIC7859 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7859 SCSI adapter", ahc_aic7860_setup }, { ID_AIC7860 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7860 Ultra SCSI adapter", ahc_aic7860_setup }, { ID_AIC7870 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7870 SCSI adapter", ahc_aic7870_setup }, { ID_AIC7880 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7880 Ultra SCSI adapter", ahc_aic7880_setup }, { ID_AIC7890 & ID_9005_GENERIC_MASK, ID_9005_GENERIC_MASK, "Adaptec aic7890/91 Ultra2 SCSI adapter", ahc_aic7890_setup }, { ID_AIC7892 & ID_9005_GENERIC_MASK, ID_9005_GENERIC_MASK, "Adaptec aic7892 Ultra160 SCSI adapter", ahc_aic7892_setup }, { ID_AIC7895 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7895 Ultra SCSI adapter", ahc_aic7895_setup }, { ID_AIC7896 & ID_9005_GENERIC_MASK, ID_9005_GENERIC_MASK, "Adaptec aic7896/97 Ultra2 SCSI adapter", ahc_aic7896_setup }, { ID_AIC7899 & ID_9005_GENERIC_MASK, ID_9005_GENERIC_MASK, "Adaptec aic7899 Ultra160 SCSI adapter", ahc_aic7899_setup }, { ID_AIC7810 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7810 RAID memory controller", ahc_raid_setup }, { ID_AIC7815 & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec aic7815 RAID memory controller", ahc_raid_setup }};const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); #define AHC_394X_SLOT_CHANNEL_A 4#define AHC_394X_SLOT_CHANNEL_B 5#define AHC_398X_SLOT_CHANNEL_A 4#define AHC_398X_SLOT_CHANNEL_B 8#define AHC_398X_SLOT_CHANNEL_C 12#define AHC_494X_SLOT_CHANNEL_A 4#define AHC_494X_SLOT_CHANNEL_B 5#define AHC_494X_SLOT_CHANNEL_C 6#define AHC_494X_SLOT_CHANNEL_D 7#define DEVCONFIG 0x40#define PCIERRGENDIS 0x80000000ul#define SCBSIZE32 0x00010000ul /* aic789X only */#define REXTVALID 0x00001000ul /* ultra cards only */#define MPORTMODE 0x00000400ul /* aic7870+ only */#define RAMPSM 0x00000200ul /* aic7870+ only */#define VOLSENSE 0x00000100ul#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/#define SCBRAMSEL 0x00000080ul#define MRDCEN 0x00000040ul#define EXTSCBTIME 0x00000020ul /* aic7870 only */#define EXTSCBPEN 0x00000010ul /* aic7870 only */#define BERREN 0x00000008ul#define DACEN 0x00000004ul#define STPWLEVEL 0x00000002ul#define DIFACTNEGEN 0x00000001ul /* aic7870 only */#define CSIZE_LATTIME 0x0c#define CACHESIZE 0x0000003ful /* only 5 bits */#define LATTIME 0x0000ff00ul/* PCI STATUS definitions */#define DPE 0x80#define SSE 0x40#define RMA 0x20#define RTA 0x10#define STA 0x08#define DPR 0x01static int ahc_9005_subdevinfo_valid(uint16_t vendor, uint16_t device, uint16_t subvendor, uint16_t subdevice);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);static void ahc_probe_ext_scbram(struct ahc_softc *ahc);static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);static void ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc);static void configure_termination(struct ahc_softc *ahc, struct seeprom_descriptor *sd, u_int adapter_control, u_int *sxfrctl1);static void ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, int *enableSEC_high, int *enablePRI_low, int *enablePRI_high, int *eeprom_present);static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, int *internal68_present, int *externalcable_present, int *eeprom_present);static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, int *externalcable_present, int *eeprom_present);static void write_brdctl(struct ahc_softc *ahc, uint8_t value);static uint8_t read_brdctl(struct ahc_softc *ahc);static void ahc_pci_intr(struct ahc_softc *ahc);static int ahc_pci_chip_init(struct ahc_softc *ahc);static int ahc_pci_suspend(struct ahc_softc *ahc);static int ahc_pci_resume(struct ahc_softc *ahc);static intahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, uint16_t subdevice, uint16_t subvendor){ int result; /* Default to invalid. */ result = 0; if (vendor == 0x9005 && subvendor == 0x9005 && subdevice != device && SUBID_9005_TYPE_KNOWN(subdevice) != 0) { switch (SUBID_9005_TYPE(subdevice)) { case SUBID_9005_TYPE_MB: break; case SUBID_9005_TYPE_CARD: case SUBID_9005_TYPE_LCCARD: /* * Currently only trust Adaptec cards to * get the sub device info correct. */ if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA) result = 1; break; case SUBID_9005_TYPE_RAID: break; default: break; } } return (result);}struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t pci){ uint64_t full_id; uint16_t device; uint16_t vendor; uint16_t subdevice; uint16_t subvendor; struct ahc_pci_identity *entry; u_int i; vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahc_compose_id(device, vendor, subdevice, subvendor); /* * If the second function is not hooked up, ignore it. * Unfortunately, not all MB vendors implement the * subdevice ID as per the Adaptec spec, so do our best * to sanity check it prior to accepting the subdevice * ID as valid. */ if (ahc_get_pci_function(pci) > 0 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice) && SUBID_9005_MFUNCENB(subdevice) == 0) return (NULL); for (i = 0; i < ahc_num_pci_devs; i++) { entry = &ahc_pci_ident_table[i]; if (entry->full_id == (full_id & entry->id_mask)) { /* Honor exclusion entries. */ if (entry->name == NULL) return (NULL); return (entry); } } return (NULL);}intahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry){ u_long l; u_int command; u_int our_id; u_int sxfrctl1; u_int scsiseq; u_int dscommand0; uint32_t devconfig; int error; uint8_t sblkctl; our_id = 0; error = entry->setup(ahc); if (error != 0) return (error); ahc->chip |= AHC_PCI; ahc->description = entry->name; ahc_power_state_change(ahc, AHC_POWER_STATE_D0); error = ahc_pci_map_registers(ahc); if (error != 0) return (error); /* * Before we continue probing the card, ensure that * its interrupts are *disabled*. We don't want * a misstep to hang the machine in an interrupt * storm. */ ahc_intr_enable(ahc, FALSE); devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); /* * If we need to support high memory, enable dual * address cycles. This bit must be set to enable * high address bit generation even if we are on a * 64bit bus (PCI64BIT set in devconfig). */ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { if (bootverbose) printf("%s: Enabling 39Bit Addressing\n", ahc_name(ahc)); devconfig |= DACEN; } /* Ensure that pci error generation, a test feature, is disabled. */ devconfig |= PCIERRGENDIS; ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Ensure busmastering is enabled */ command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); /* On all PCI adapters, we allow SCB paging */ ahc->flags |= AHC_PAGESCBS; error = ahc_softc_init(ahc); if (error != 0) return (error); /* * Disable PCI parity error checking. Users typically * do this to work around broken PCI chipsets that get * the parity timing wrong and thus generate lots of spurious * errors. The chip only allows us to disable *all* parity * error reporting when doing this, so CIO bus, scb ram, and * scratch ram parity errors will be ignored too. */ if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) ahc->seqctl |= FAILDIS; ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; ahc->bus_suspend = ahc_pci_suspend; ahc->bus_resume = ahc_pci_resume; /* Remeber how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { ahc_pause(ahc); if ((ahc->features & AHC_ULTRA2) != 0) our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; else our_id = ahc_inb(ahc, SCSIID) & OID; sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; scsiseq = ahc_inb(ahc, SCSISEQ); } else { sxfrctl1 = STPWEN; our_id = 7; scsiseq = 0; } error = ahc_reset(ahc, /*reinit*/FALSE); if (error != 0) return (ENXIO); if ((ahc->features & AHC_DT) != 0) { u_int sfunct; /* Perform ALT-Mode Setup */ sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); ahc_outb(ahc, OPTIONMODE, OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS); ahc_outb(ahc, SFUNCT, sfunct); /* Normal mode setup */ ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN |TARGCRCENDEN); } dscommand0 = ahc_inb(ahc, DSCOMMAND0); dscommand0 |= MPARCKEN|CACHETHEN; if ((ahc->features & AHC_ULTRA2) != 0) { /* * DPARCKEN doesn't work correctly on * some MBs so don't use it. */ dscommand0 &= ~DPARCKEN; } /* * Handle chips that must have cache line * streaming (dis/en)abled. */ if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) dscommand0 |= CACHETHEN; if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) dscommand0 &= ~CACHETHEN; ahc_outb(ahc, DSCOMMAND0, dscommand0); ahc->pci_cachesize = ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahc->pci_cachesize *= 4; if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 && ahc->pci_cachesize == 4) { ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 0, /*bytes*/1); ahc->pci_cachesize = 0; } /* * 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->features &= ~AHC_ULTRA; } /* See if we have a SEEPROM and perform auto-term */ check_extport(ahc, &sxfrctl1); /* * Take the LED out of diagnostic mode */ sblkctl = ahc_inb(ahc, SBLKCTL); ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); if ((ahc->features & AHC_ULTRA2) != 0) { ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); } else { ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); } if (ahc->flags & AHC_USEDEFAULTS) { /* * PCI Adapter default setup * Should only be used if the adapter does not have * a SEEPROM. */ /* See if someone else set us up already */ if ((ahc->flags & AHC_NO_BIOS_INIT) == 0 && scsiseq != 0) { printf("%s: Using left over BIOS settings\n", ahc_name(ahc)); ahc->flags &= ~AHC_USEDEFAULTS; ahc->flags |= AHC_BIOS_ENABLED; } else { /* * Assume only one connector and always turn * on termination. */ our_id = 0x07; sxfrctl1 = STPWEN; } ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); ahc->our_id = our_id; } /* * Take a look to see if we have external SRAM. * We currently do not attempt to use SRAM that is * shared among multiple controllers. */ ahc_probe_ext_scbram(ahc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -