Exemplo n.º 1
0
void
ahc_pci_resume(struct ahc_softc *ahc)
{
	
	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
			     ahc->bus_softc.pci_softc.devconfig, 4);
	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
			     ahc->bus_softc.pci_softc.command, 1);
	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
			     ahc->bus_softc.pci_softc.csize_lattime, 1);
	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
		struct	seeprom_descriptor sd;
		u_int	sxfrctl1;

		sd.sd_ahc = ahc;
		sd.sd_control_offset = SEECTL;		
		sd.sd_status_offset = SEECTL;		
		sd.sd_dataout_offset = SEECTL;		

		ahc_acquire_seeprom(ahc, &sd);
		configure_termination(ahc, &sd,
				      ahc->seep_config->adapter_control,
				      &sxfrctl1);
		ahc_release_seeprom(&sd);
	}
}
Exemplo n.º 2
0
static int
ahc_aic7895_setup(struct ahc_softc *ahc)
{
	ahc_dev_softc_t pci;
	uint8_t rev;

	pci = ahc->dev_softc;
	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
	
	rev = ahc_pci_read_config(pci, PCIR_REVID, 1);
	if (rev >= 4) {
		ahc->chip = AHC_AIC7895C;
		ahc->features = AHC_AIC7895C_FE;
	} else  {
		u_int command;

		ahc->chip = AHC_AIC7895;
		ahc->features = AHC_AIC7895_FE;

		
		command = ahc_pci_read_config(pci, PCIR_COMMAND, 1);
		command |= PCIM_CMD_MWRICEN;
		ahc_pci_write_config(pci, PCIR_COMMAND, command, 1);
		ahc->bugs |= AHC_PCI_MWI_BUG;
	}
	
	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
		  |  AHC_CACHETHEN_BUG;

#if 0
	uint32_t devconfig;

	
	ahc_pci_write_config(pci, CSIZE_LATTIME, 0, 1);
	devconfig = ahc_pci_read_config(pci, DEVCONFIG, 1);
	devconfig |= MRDCEN;
	ahc_pci_write_config(pci, DEVCONFIG, devconfig, 1);
#endif
	ahc->flags |= AHC_NEWEEPROM_FMT;
	ahc->instruction_ram_size = 512;
	return (0);
}
Exemplo n.º 3
0
static void
ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
		  int fast, int large)
{
	uint32_t devconfig;

	if (ahc->features & AHC_MULTI_FUNC) {
		
		ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
	}

	ahc->flags &= ~AHC_LSCBS_ENABLED;
	if (large)
		ahc->flags |= AHC_LSCBS_ENABLED;
	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);
	if ((ahc->features & AHC_ULTRA2) != 0) {
		u_int dscommand0;

		dscommand0 = ahc_inb(ahc, DSCOMMAND0);
		if (enable)
			dscommand0 &= ~INTSCBRAMSEL;
		else
			dscommand0 |= INTSCBRAMSEL;
		if (large)
			dscommand0 &= ~USCBSIZE32;
		else
			dscommand0 |= USCBSIZE32;
		ahc_outb(ahc, DSCOMMAND0, dscommand0);
	} else {
		if (fast)
			devconfig &= ~EXTSCBTIME;
		else
			devconfig |= EXTSCBTIME;
		if (enable)
			devconfig &= ~SCBRAMSEL;
		else
			devconfig |= SCBRAMSEL;
		if (large)
			devconfig &= ~SCBSIZE32;
		else
			devconfig |= SCBSIZE32;
	}
	if (pcheck)
		devconfig |= EXTSCBPEN;
	else
		devconfig &= ~EXTSCBPEN;

	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, 4);
}
Exemplo n.º 4
0
int
ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
{
	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;

	pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);

	error = ahc_pci_map_registers(ahc);
	if (error != 0)
		return (error);

	
	ahc_intr_enable(ahc, FALSE);

	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);

	
	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {

		if (bootverbose)
			printf("%s: Enabling 39Bit Addressing\n",
			       ahc_name(ahc));
		devconfig |= DACEN;
	}
	
	
	devconfig |= PCIERRGENDIS;

	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, 4);

	
	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 2);
	command |= PCIM_CMD_BUSMASTEREN;

	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 2);

	
	ahc->flags |= AHC_PAGESCBS;

	error = ahc_softc_init(ahc);
	if (error != 0)
		return (error);

	
	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;

	
	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, FALSE);
	if (error != 0)
		return (ENXIO);

	if ((ahc->features & AHC_DT) != 0) {
		u_int sfunct;

		
		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);

		
		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN
					  |TARGCRCENDEN);
	}

	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
	dscommand0 |= MPARCKEN|CACHETHEN;
	if ((ahc->features & AHC_ULTRA2) != 0) {

		
		dscommand0 &= ~DPARCKEN;
	}

	
	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,
				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, 1);
		ahc->pci_cachesize = 0;
	}

	
	if ((ahc->features & AHC_ULTRA) != 0) {
		uint32_t devconfig;

		devconfig = ahc_pci_read_config(ahc->dev_softc,
						DEVCONFIG, 4);
		if ((devconfig & REXTVALID) == 0)
			ahc->features &= ~AHC_ULTRA;
	}

	
	check_extport(ahc, &sxfrctl1);

	
	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) {
		
		
		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 {
			
 			our_id = 0x07;
			sxfrctl1 = STPWEN;
		}
		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);

		ahc->our_id = our_id;
	}

	
	ahc_probe_ext_scbram(ahc);

	
	if ((sxfrctl1 & STPWEN) != 0)
		ahc->flags |= AHC_TERM_ENB_A;

	
	ahc->bus_softc.pci_softc.devconfig =
	    ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);
	ahc->bus_softc.pci_softc.command =
	    ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 1);
	ahc->bus_softc.pci_softc.csize_lattime =
	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, 1);
	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
	if ((ahc->features & AHC_DT) != 0) {
		u_int sfunct;

		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
		ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);
		ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);
		ahc_outb(ahc, SFUNCT, sfunct);
		ahc->bus_softc.pci_softc.crccontrol1 =
		    ahc_inb(ahc, CRCCONTROL1);
	}
	if ((ahc->features & AHC_MULTI_FUNC) != 0)
		ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);

	if ((ahc->features & AHC_ULTRA2) != 0)
		ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);

	
	error = ahc_init(ahc);
	if (error != 0)
		return (error);
	ahc->init_level++;

	
	return ahc_pci_map_int(ahc);
}
Exemplo n.º 5
0
static void
ahc_pci_intr(struct ahc_softc *ahc)
{
	u_int error;
	u_int status1;

	error = ahc_inb(ahc, ERROR);
	if ((error & PCIERRSTAT) == 0)
		return;

	status1 = ahc_pci_read_config(ahc->dev_softc,
				      PCIR_STATUS + 1, 1);

	printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
	      ahc_name(ahc),
	      ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));

	if (status1 & DPE) {
		ahc->pci_target_perr_count++;
		printf("%s: Data Parity Error Detected during address "
		       "or write data phase\n", ahc_name(ahc));
	}
	if (status1 & SSE) {
		printf("%s: Signal System Error Detected\n", ahc_name(ahc));
	}
	if (status1 & RMA) {
		printf("%s: Received a Master Abort\n", ahc_name(ahc));
	}
	if (status1 & RTA) {
		printf("%s: Received a Target Abort\n", ahc_name(ahc));
	}
	if (status1 & STA) {
		printf("%s: Signaled a Target Abort\n", ahc_name(ahc));
	}
	if (status1 & DPR) {
		printf("%s: Data Parity Error has been reported via PERR#\n",
		       ahc_name(ahc));
	}

	
	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
			     status1, 1);

	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
		printf("%s: Latched PCIERR interrupt with "
		       "no status bits set\n", ahc_name(ahc)); 
	} else {
		ahc_outb(ahc, CLRINT, CLRPARERR);
	}

	if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) {
		printf(
"%s: WARNING WARNING WARNING WARNING\n"
"%s: Too many PCI parity errors observed as a target.\n"
"%s: Some device on this bus is generating bad parity.\n"
"%s: This is an error *observed by*, not *generated by*, this controller.\n"
"%s: PCI parity error checking has been disabled.\n"
"%s: WARNING WARNING WARNING WARNING\n",
		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc));
		ahc->seqctl |= FAILDIS;
		ahc_outb(ahc, SEQCTL, ahc->seqctl);
	}
	ahc_unpause(ahc);
}
Exemplo n.º 6
0
static void
ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
{
	
	int	 i;
	int	 max_targ = sc->max_targets & CFMAXTARG;
	u_int	 scsi_conf;
	uint16_t discenable;
	uint16_t ultraenb;

	discenable = 0;
	ultraenb = 0;
	if ((sc->adapter_control & CFULTRAEN) != 0) {
		
		for (i = 0; i < max_targ; i++) {
			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
				ahc->flags |= AHC_NEWEEPROM_FMT;
				break;
			}
		}
	}

	for (i = 0; i < max_targ; i++) {
		u_int     scsirate;
		uint16_t target_mask;

		target_mask = 0x01 << i;
		if (sc->device_flags[i] & CFDISC)
			discenable |= target_mask;
		if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
				ultraenb |= target_mask;
		} else if ((sc->adapter_control & CFULTRAEN) != 0) {
			ultraenb |= target_mask;
		}
		if ((sc->device_flags[i] & CFXFER) == 0x04
		 && (ultraenb & target_mask) != 0) {
			
			sc->device_flags[i] &= ~CFXFER;
		 	ultraenb &= ~target_mask;
		}
		if ((ahc->features & AHC_ULTRA2) != 0) {
			u_int offset;

			if (sc->device_flags[i] & CFSYNCH)
				offset = MAX_OFFSET_ULTRA2;
			else 
				offset = 0;
			ahc_outb(ahc, TARG_OFFSET + i, offset);

			
			scsirate = (sc->device_flags[i] & CFXFER)
				 | ((ultraenb & target_mask) ? 0x8 : 0x0);
			if (sc->device_flags[i] & CFWIDEB)
				scsirate |= WIDEXFER;
		} else {
			scsirate = (sc->device_flags[i] & CFXFER) << 4;
			if (sc->device_flags[i] & CFSYNCH)
				scsirate |= SOFS;
			if (sc->device_flags[i] & CFWIDEB)
				scsirate |= WIDEXFER;
		}
		ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
	}
	ahc->our_id = sc->brtime_id & CFSCSIID;

	scsi_conf = (ahc->our_id & 0x7);
	if (sc->adapter_control & CFSPARITY)
		scsi_conf |= ENSPCHK;
	if (sc->adapter_control & CFRESETB)
		scsi_conf |= RESET_SCSI;

	ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;

	if (sc->bios_control & CFEXTEND)
		ahc->flags |= AHC_EXTENDED_TRANS_A;

	if (sc->bios_control & CFBIOSEN)
		ahc->flags |= AHC_BIOS_ENABLED;
	if (ahc->features & AHC_ULTRA
	 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
		
		if (!(sc->adapter_control & CFULTRAEN))
			
			ultraenb = 0;
	}

	if (sc->signature == CFSIGNATURE
	 || sc->signature == CFSIGNATURE2) {
		uint32_t devconfig;

		
		devconfig = ahc_pci_read_config(ahc->dev_softc,
						DEVCONFIG, 4);
		devconfig &= ~STPWLEVEL;
		if ((sc->bios_control & CFSTPWLEVEL) != 0)
			devconfig |= STPWLEVEL;
		ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
				     devconfig, 4);
	}
	
	ahc_outb(ahc, SCSICONF, scsi_conf);
	ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
	ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
	ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
	ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
}
Exemplo n.º 7
0
int
ahc_pci_test_register_access(struct ahc_softc *ahc)
{
	int	 error;
	u_int	 status1;
	uint32_t cmd;
	uint8_t	 hcntrl;

	error = EIO;

	
	cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 2);
	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
			     cmd & ~PCIM_CMD_SERRESPEN, 2);

	
	hcntrl = ahc_inb(ahc, HCNTRL);

	if (hcntrl == 0xFF)
		goto fail;

	if ((hcntrl & CHIPRST) != 0) {
		
		ahc->flags |= AHC_NO_BIOS_INIT;
	}

	
	hcntrl &= ~CHIPRST;
	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
	while (ahc_is_paused(ahc) == 0)
		;

	
	status1 = ahc_pci_read_config(ahc->dev_softc,
				      PCIR_STATUS + 1, 1);
	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
			     status1, 1);
	ahc_outb(ahc, CLRINT, CLRPARERR);

	ahc_outb(ahc, SEQCTL, PERRORDIS);
	ahc_outb(ahc, SCBPTR, 0);
	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
		goto fail;

	status1 = ahc_pci_read_config(ahc->dev_softc,
				      PCIR_STATUS + 1, 1);
	if ((status1 & STA) != 0)
		goto fail;

	error = 0;

fail:
	
	status1 = ahc_pci_read_config(ahc->dev_softc,
				      PCIR_STATUS + 1, 1);
	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
			     status1, 1);
	ahc_outb(ahc, CLRINT, CLRPARERR);
	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, 2);
	return (error);
}
Exemplo n.º 8
0
int
ahc_pci_map_registers(struct ahc_softc *ahc)
{
	uint32_t command;
	u_long	 base;
	uint8_t	__iomem *maddr;
	int	 error;

	/*
	 * If its allowed, we prefer memory mapped access.
	 */
	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4);
	command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
	base = 0;
	maddr = NULL;
	error = ahc_linux_pci_reserve_mem_region(ahc, &base, &maddr);
	if (error == 0) {
		ahc->platform_data->mem_busaddr = base;
		ahc->tag = BUS_SPACE_MEMIO;
		ahc->bsh.maddr = maddr;
		ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
				     command | PCIM_CMD_MEMEN, 4);

		/*
		 * Do a quick test to see if memory mapped
		 * I/O is functioning correctly.
		 */
		if (ahc_pci_test_register_access(ahc) != 0) {

			printf("aic7xxx: PCI Device %d:%d:%d "
			       "failed memory mapped test.  Using PIO.\n",
			       ahc_get_pci_bus(ahc->dev_softc),
			       ahc_get_pci_slot(ahc->dev_softc),
			       ahc_get_pci_function(ahc->dev_softc));
			iounmap(maddr);
			release_mem_region(ahc->platform_data->mem_busaddr,
					   0x1000);
			ahc->bsh.maddr = NULL;
			maddr = NULL;
		} else
			command |= PCIM_CMD_MEMEN;
	} else {
		printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx "
		       "unavailable. Cannot memory map device.\n",
		       ahc_get_pci_bus(ahc->dev_softc),
		       ahc_get_pci_slot(ahc->dev_softc),
		       ahc_get_pci_function(ahc->dev_softc),
		       base);
	}

	/*
	 * We always prefer memory mapped access.
	 */
	if (maddr == NULL) {

		error = ahc_linux_pci_reserve_io_region(ahc, &base);
		if (error == 0) {
			ahc->tag = BUS_SPACE_PIO;
			ahc->bsh.ioport = base;
			command |= PCIM_CMD_PORTEN;
		} else {
			printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] "
			       "unavailable. Cannot map device.\n",
			       ahc_get_pci_bus(ahc->dev_softc),
			       ahc_get_pci_slot(ahc->dev_softc),
			       ahc_get_pci_function(ahc->dev_softc),
			       base);
		}
	}
	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);
	return (error);
}