⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciide.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct pciide_softc *sc = v;	int error, seg;	struct pciide_dma_maps *dma_maps =	    &sc->pciide_channels[channel].dma_maps[drive];	error = bus_dmamap_load(sc->sc_dmat,	    dma_maps->dmamap_xfer,	    databuf, datalen, NULL, BUS_DMA_NOWAIT);	if (error) {		printf("%s:%d: unable to load xfer DMA map for"		    "drive %d, error=%d\n", sc->sc_wdcdev.sc_dev.dv_xname,		    channel, drive, error);		return error;	}#ifndef __OpenBSD__	bus_dmamap_sync(sc->sc_dmat, dma_maps->dmamap_xfer,	    0,	    dma_maps->dmamap_xfer->dm_mapsize,			    (flags & WDC_DMA_READ) ?	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);#else	bus_dmamap_sync(sc->sc_dmat, dma_maps->dmamap_xfer,	    (flags & WDC_DMA_READ) ?	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);#endif	for (seg = 0; seg < dma_maps->dmamap_xfer->dm_nsegs; seg++) {#ifdef DIAGNOSTIC		/* A segment must not cross a 64k boundary */		{		u_long phys = dma_maps->dmamap_xfer->dm_segs[seg].ds_addr;		u_long len = dma_maps->dmamap_xfer->dm_segs[seg].ds_len;		if ((phys & ~IDEDMA_BYTE_COUNT_MASK) !=		    ((phys + len - 1) & ~IDEDMA_BYTE_COUNT_MASK)) {			printf("pciide_dma: segment %d physical addr 0x%lx"			    " len 0x%lx not properly aligned\n",			    seg, phys, len);			panic("pciide_dma: buf align");		}		}#endif		dma_maps->dma_table[seg].base_addr =		    htopci(dma_maps->dmamap_xfer->dm_segs[seg].ds_addr | 0x00000000);		dma_maps->dma_table[seg].byte_count =		    htopci(dma_maps->dmamap_xfer->dm_segs[seg].ds_len &		    IDEDMA_BYTE_COUNT_MASK);		WDCDEBUG_PRINT(("\t seg %d len %d addr 0x%x\n",		   seg, pcitoh(dma_maps->dma_table[seg].byte_count),		   pcitoh(dma_maps->dma_table[seg].base_addr)), DEBUG_DMA);	}	dma_maps->dma_table[dma_maps->dmamap_xfer->dm_nsegs -1].byte_count |=	    htopci(IDEDMA_BYTE_COUNT_EOT);#ifndef __OpenBSD__	bus_dmamap_sync(sc->sc_dmat, dma_maps->dmamap_table, 	    0,	    dma_maps->dmamap_table->dm_mapsize,	    BUS_DMASYNC_PREWRITE);#else	bus_dmamap_sync(sc->sc_dmat, dma_maps->dmamap_table, 	    BUS_DMASYNC_PREWRITE);#endif	/* Maps are ready. Start DMA function */#ifdef DIAGNOSTIC	if (dma_maps->dmamap_table->dm_segs[0].ds_addr & ~IDEDMA_TBL_MASK) {		printf("pciide_dma_init: addr 0x%lx not properly aligned\n",		    dma_maps->dmamap_table->dm_segs[0].ds_addr);		panic("pciide_dma_init: table align");	}#endif	/* Clear status bits */	bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_CTL + IDEDMA_SCH_OFFSET * channel,	    bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,		IDEDMA_CTL + IDEDMA_SCH_OFFSET * channel));/* XXX CMD MRDMODE pending bits clear */	bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    (IDEDMA_CTL-1) + IDEDMA_SCH_OFFSET * channel,	    bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,		(IDEDMA_CTL-1) + IDEDMA_SCH_OFFSET * channel));	/* Write table addr */printf("dma table start at 0x%08x\n", dma_maps->dmamap_table->dm_segs[0].ds_addr);	bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_TBL + IDEDMA_SCH_OFFSET * channel,	    dma_maps->dmamap_table->dm_segs[0].ds_addr | 0x80000000); /* XXX */	/* set read/write */	bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_CMD + IDEDMA_SCH_OFFSET * channel,	    (flags & WDC_DMA_READ) ? IDEDMA_CMD_WRITE: 0);	return 0;}voidpciide_dma_start(v, channel, drive, flags)	void *v;	int channel, drive, flags;{	struct pciide_softc *sc = v;	WDCDEBUG_PRINT(("pciide_dma_start\n"),DEBUG_XFERS);	bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_CMD + IDEDMA_SCH_OFFSET * channel,	    bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,		IDEDMA_CMD + IDEDMA_SCH_OFFSET * channel) | IDEDMA_CMD_START);}intpciide_dma_finish(v, channel, drive, flags)	void *v;	int channel, drive;	int flags;{	struct pciide_softc *sc = v;	u_int8_t status;	struct pciide_dma_maps *dma_maps =	    &sc->pciide_channels[channel].dma_maps[drive];	/* Unload the map of the data buffer */#ifndef __OpenBSD__	bus_dmamap_sync(sc->sc_dmat, dma_maps->dmamap_xfer, 	    0,	    dma_maps->dmamap_xfer->dm_mapsize,	    (flags & WDC_DMA_READ) ?	    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);#else	bus_dmamap_sync(sc->sc_dmat, dma_maps->dmamap_xfer, 	    (flags & WDC_DMA_READ) ?	    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);#endif	bus_dmamap_unload(sc->sc_dmat, dma_maps->dmamap_xfer);	status = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_CTL + IDEDMA_SCH_OFFSET * channel);	WDCDEBUG_PRINT(("pciide_dma_finish: status 0x%x\n", status),	    DEBUG_XFERS);	WDCDEBUG_PRINT(("pciide: command/status register=%x\n",	    pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG)), DEBUG_XFERS);	/* stop DMA channel */	bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_CMD + IDEDMA_SCH_OFFSET * channel,	    bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,		IDEDMA_CMD + IDEDMA_SCH_OFFSET * channel) & ~IDEDMA_CMD_START);	/* Clear status bits */	bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,	    IDEDMA_CTL + IDEDMA_SCH_OFFSET * channel,	    status);	if ((status & IDEDMA_CTL_ERR) != 0) {		printf("%s:%d:%d: Bus-Master DMA error: status=0x%x\n",		    sc->sc_wdcdev.sc_dev.dv_xname, channel, drive, status);		return -1;	}	if ((flags & WDC_DMA_POLL) == 0 && (status & IDEDMA_CTL_INTR) == 0) {		printf("%s:%d:%d: Bus-Master DMA error: missing interrupt, "		    "status=0x%x\n", sc->sc_wdcdev.sc_dev.dv_xname, channel,		    drive, status);		return -1;	}	if ((status & IDEDMA_CTL_ACT) != 0) {		/* data underrun, may be a valid condition for ATAPI */		return 1;	}	return 0;}#endif/* some common code used by several chip_map */intpciide_chansetup(sc, channel, interface)	struct pciide_softc *sc;	int channel;	pcireg_t interface;{	struct pciide_channel *cp = &sc->pciide_channels[channel];	sc->wdc_chanarray[channel] = &cp->wdc_channel;	cp->name = PCIIDE_CHANNEL_NAME(channel);	cp->wdc_channel.channel = channel;	cp->wdc_channel.wdc = &sc->sc_wdcdev;	cp->wdc_channel.ch_queue =	    malloc(sizeof(struct channel_queue), M_DEVBUF, M_NOWAIT);	if (cp->wdc_channel.ch_queue == NULL) {		printf("%s: %s "			"cannot allocate memory for command queue",		sc->sc_wdcdev.sc_dev.dv_xname, cp->name);		 return 0;	}	cp->hw_ok = 1;	return 1;}/* some common code used by several chip channel_map */voidpciide_mapchan(pa, cp, interface, cmdsizep, ctlsizep, pci_intr)	struct pci_attach_args *pa;	struct pciide_channel *cp;	pcireg_t interface;	bus_size_t *cmdsizep, *ctlsizep;	int (*pci_intr) __P((void *));{	struct channel_softc *wdc_cp = &cp->wdc_channel;	if (interface & PCIIDE_INTERFACE_PCI(wdc_cp->channel))		cp->hw_ok = pciide_mapregs_native(pa, cp, cmdsizep, ctlsizep,		    pci_intr);	else		cp->hw_ok = pciide_mapregs_compat(pa, cp,		    wdc_cp->channel, cmdsizep, ctlsizep);	if (cp->hw_ok == 0)		return;	wdc_cp->data32iot = wdc_cp->cmd_iot;	wdc_cp->data32ioh = wdc_cp->cmd_ioh;	wdcattach(wdc_cp);}/* * Generic code to call to know if a channel can be disabled. Return 1 * if channel can be disabled, 0 if not */intpciiide_chan_candisable(cp)	struct pciide_channel *cp;{	struct channel_softc *wdc_cp = &cp->wdc_channel;	if ((wdc_cp->ch_drive[0].drive_flags & DRIVE) == 0 &&	    (wdc_cp->ch_drive[1].drive_flags & DRIVE) == 0) {		cp->hw_ok = 0;		return 1;	}	return 0;}/* * generic code to map the compat intr if hw_ok=1 and it is a compat channel. * Set hw_ok=0 on failure */voidpciide_map_compat_intr(pa, cp, compatchan, interface)	struct pci_attach_args *pa;	struct pciide_channel *cp;	int compatchan, interface;{#ifndef PMON	struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;	struct channel_softc *wdc_cp = &cp->wdc_channel;	if (cp->hw_ok == 0)		return;	if ((interface & PCIIDE_INTERFACE_PCI(wdc_cp->channel)) != 0)		return;	cp->ih = pciide_machdep_compat_intr_establish(&sc->sc_wdcdev.sc_dev,	    pa, compatchan, pciide_compat_intr, cp);	if (cp->ih == NULL) {		printf("%s: no compatibility interrupt for use by %s\n",		    sc->sc_wdcdev.sc_dev.dv_xname, cp->name);		cp->hw_ok = 0;	}#endif}voidpciide_print_channels(nchannels, interface)	int nchannels;	pcireg_t interface;{	int i;	for (i = 0; i < nchannels; i++) {		printf(", %s %s to %s", PCIIDE_CHANNEL_NAME(i),		    (interface & PCIIDE_INTERFACE_SETTABLE(i)) ?   		    "cfg" : "wired",		    (interface & PCIIDE_INTERFACE_PCI(i)) ? "native-PCI" :		    "compat");		    }	printf("\n");}voidpciide_print_modes(cp)	struct pciide_channel *cp;{	struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;	int drive;	struct channel_softc *chp;	struct ata_drive_datas *drvp;	chp = &cp->wdc_channel;	for (drive = 0; drive < 2; drive++) {		drvp = &chp->ch_drive[drive];		if ((drvp->drive_flags & DRIVE) == 0)			continue;		printf("%s(%s:%d:%d): using PIO mode %d",		    drvp->drive_name,		    sc->sc_wdcdev.sc_dev.dv_xname,		    chp->channel, drive, drvp->PIO_mode);		if (drvp->drive_flags & DRIVE_DMA)			printf(", DMA mode %d", drvp->DMA_mode);		if (drvp->drive_flags & DRIVE_UDMA)			printf(", Ultra-DMA mode %d", drvp->UDMA_mode);		if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA))			printf(" (using DMA data transfers)");		printf("\n");	}}voiddefault_chip_map(sc, pa)	struct pciide_softc *sc;	struct pci_attach_args *pa;{	struct pciide_channel *cp;	pcireg_t interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc,				    sc->sc_tag, PCI_CLASS_REG));	pcireg_t csr;	int channel;#ifndef PMON	int drive;	struct ata_drive_datas *drvp;	u_int8_t idedma_ctl;#endif	bus_size_t cmdsize, ctlsize;	char *failreason;	if (pciide_chipen(sc, pa) == 0)		return;	if (interface & PCIIDE_INTERFACE_BUS_MASTER_DMA) {		printf(": DMA");		if (sc->sc_pp == &default_product_desc &&		    (sc->sc_wdcdev.sc_dev.dv_cfdata->cf_flags &		    PCIIDE_OPTIONS_DMA) == 0) {			printf(" (unsupported)");			sc->sc_dma_ok = 0;		} else {			pciide_mapreg_dma(sc, pa);		if (sc->sc_dma_ok != 0)			printf(", (partial support)");		}	} else {		printf(": no DMA");		sc->sc_dma_ok = 0;	}	if (sc->sc_dma_ok)		sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;	sc->sc_wdcdev.PIO_cap = 0;	sc->sc_wdcdev.DMA_cap = 0;	sc->sc_wdcdev.channels = sc->wdc_chanarray;	sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;	sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;	pciide_print_channels(sc->sc_wdcdev.nchannels, interface);	for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {		cp = &sc->pciide_channels[channel];		if (pciide_chansetup(sc, channel, interface) == 0)		    continue;		if (interface & PCIIDE_INTERFACE_PCI(channel)) {			cp->hw_ok = pciide_mapregs_native(pa, cp, &cmdsize,			    &ctlsize, pciide_pci_intr);		} else {			cp->hw_ok = pciide_mapregs_compat(pa, cp,			    channel, &cmdsize, &ctlsize);		}		if (cp->hw_ok == 0)			continue;		/*		 * Check to see if something appears to be there.		 */		failreason = NULL;		if (!wdcprobe(&cp->wdc_channel)) {			failreason = "not responding; disabled or no drives?";			goto next;		}		/*		 * Now, make sure it's actually attributable to this PCI IDE		 * channel by trying to access the channel again while the		 * PCI IDE controller's I/O space is disabled.  (If the		 * channel no longer appears to be there, it belongs to		 * this controller.)  YUCK!		 */		csr = pci_conf_read(sc->sc_pc, sc->sc_tag,	  	    PCI_COMMAND_STATUS_REG);		pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG,		    csr & ~PCI_COMMAND_IO_ENABLE);		if (wdcprobe(&cp->wdc_channel))			failreason = "other hardware responding at addresses";		pci_conf_write(sc->sc_pc, sc->sc_tag,		    PCI_COMMAND_STATUS_REG, csr);next:		if (failreason) {			printf("%s: %s ignored (%s)\n",			    sc->sc_wdcdev.sc_dev.dv_xname, cp->name,			    failreason);			cp->hw_ok = 0;			bus_space_unmap(cp->wdc_channel.cmd_iot,			    cp->wdc_channel.cmd_ioh, cmdsize);			bus_space_unmap(cp->wdc_channel.ctl_iot,			    cp->wdc_channel.ctl_ioh, ctlsize);		} else {			pciide_map_compat_intr(pa, cp, channel, interface);		}		if (cp->hw_ok) {			cp->wdc_channel.data32iot = cp->wdc_channel.cmd_iot;			cp->wdc_channel.data32ioh = cp->wdc_channel.cmd_ioh;			wdcattach(&cp->wdc_channel);		}	}#ifndef PMON	if (sc->sc_dma_ok == 0)		return;	/* Allocate DMA maps */	for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {		idedma_ctl = 0;		cp = &sc->pciide_channels[channel];		for (drive = 0; drive < 2; drive++) {			drvp = &cp->wdc_channel.ch_drive[drive];			/* If no drive, skip */			if ((drvp->drive_flags & DRIVE) == 0)				continue;			if ((drvp->drive_flags & DRIVE_DMA) == 0)				continue;			if (pciide_dma_table_setup(sc, channel, drive) != 0) {				/* Abort DMA setup */				printf("%s:%d:%d: cannot allocate DMA maps, "				    "using PIO transfers\n",

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -