pcireg_t cls, reg40, reg44;
sii3112_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa){	struct pciide_channel *cp;	bus_size_t cmdsize, ctlsize;	pcireg_t interface, scs_cmd, cfgctl;	pcireg_t cls, reg40, reg44;	int channel;	struct pciide_satalink *sl = sc->sc_cookie;	if (pciide_chipen(sc, pa) == 0)		return;	/* Allocate memory for private data */	sc->sc_cookie = malloc(sizeof(struct pciide_satalink), M_DEVBUF,	    M_NOWAIT);	sl = sc->sc_cookie;	bzero(sl, sizeof(*sl));#define	SII3112_RESET_BITS						\	(SCS_CMD_PBM_RESET | SCS_CMD_ARB_RESET |			\	 SCS_CMD_FF1_RESET | SCS_CMD_FF0_RESET |			\	 SCS_CMD_IDE1_RESET | SCS_CMD_IDE0_RESET)	/*	 * Reset everything and then unblock all of the interrupts.	 */	scs_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD);	pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD,		       scs_cmd | SII3112_RESET_BITS);	delay(50 * 1000);	pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD,		       scs_cmd & SCS_CMD_BA5_EN);	delay(50 * 1000);	if (scs_cmd & SCS_CMD_BA5_EN) {		if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x14,				   PCI_MAPREG_TYPE_MEM |				   PCI_MAPREG_MEM_TYPE_32BIT, 0,				   &sl->ba5_st, &sl->ba5_sh,				   NULL, NULL, 0) != 0)			printf(": unable to map BA5 register space\n");		else			sl->ba5_en = 1;	} else {		cfgctl = pci_conf_read(pa->pa_pc, pa->pa_tag,				       SII3112_PCI_CFGCTL);		pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_PCI_CFGCTL,			       cfgctl | CFGCTL_BA5INDEN);	}	printf(": DMA");	pciide_mapreg_dma(sc, pa);	printf("\n");	/*	 * Rev. <= 0x01 of the 3112 have a bug that can cause data	 * corruption if DMA transfers cross an 8K boundary.  This is	 * apparently hard to tickle, but we'll go ahead and play it	 * safe.	 */	if (sc->sc_rev <= 0x01) {		sc->sc_dma_maxsegsz = 8192;		sc->sc_dma_boundary = 8192;	}	/*	 * When the Silicon Image 3112 retries a PCI memory read command,	 * it may retry it as a memory read multiple command under some	 * circumstances.  This can totally confuse some PCI controllers,	 * so ensure that it will never do this by making sure that the	 * Read Threshold (FIFO Read Request Control) field of the FIFO	 * Valid Byte Count and Control registers for both channels (BA5	 * offset 0x40 and 0x44) are set to be at least as large as the	 * cacheline size register.	 */	cls = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);	cls = (cls >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK;	cls *= 4;	if (cls > 224) {		cls = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);		cls &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);		cls |= ((224/4) << PCI_CACHELINE_SHIFT);		pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, cls);		cls = 224;	}	if (cls < 32)		cls = 32;	cls = (cls + 31) / 32;	reg40 = ba5_read_4(sc, 0x40);	reg44 = ba5_read_4(sc, 0x44);	if ((reg40 & 0x7) < cls)		ba5_write_4(sc, 0x40, (reg40 & ~0x07) | cls);	if ((reg44 & 0x7) < cls)		ba5_write_4(sc, 0x44, (reg44 & ~0x07) | cls);	sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32;	sc->sc_wdcdev.PIO_cap = 4;	if (sc->sc_dma_ok) {		sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;		sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;		sc->sc_wdcdev.irqack = pciide_irqack;		sc->sc_wdcdev.DMA_cap = 2;		sc->sc_wdcdev.UDMA_cap = 6;	}	sc->sc_wdcdev.set_modes = sii3112_setup_channel;	/* We can use SControl and SStatus to probe for drives. */	sc->sc_wdcdev.drv_probe = sii3112_drv_probe;	sc->sc_wdcdev.channels = sc->wdc_chanarray;	sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;	/*	 * The 3112 either identifies itself as a RAID storage device	 * or a Misc storage device.  Fake up the interface bits for	 * what our driver expects.	 */	if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {		interface = PCI_INTERFACE(pa->pa_class);	} else {		interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |		    PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);	}	for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {		cp = &sc->pciide_channels[channel];		if (pciide_chansetup(sc, channel, interface) == 0)			continue;		pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,		    pciide_pci_intr);		if (cp->hw_ok == 0)			continue;		sc->sc_wdcdev.set_modes(&cp->wdc_channel);	}}