📄 pciide.c
字号:
#ifndef PMONvoidamd756_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)); int channel; pcireg_t chanenable; bus_size_t cmdsize, ctlsize; if (pciide_chipen(sc, pa) == 0) return; printf(": DMA"); pciide_mapreg_dma(sc, pa); if (sc->sc_dma_ok) sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA; sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 | WDC_CAPABILITY_MODE; sc->sc_wdcdev.PIO_cap = 4; sc->sc_wdcdev.DMA_cap = 2; sc->sc_wdcdev.UDMA_cap = 4; sc->sc_wdcdev.set_modes = amd756_setup_channel; sc->sc_wdcdev.channels = sc->wdc_chanarray; sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS; chanenable = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_CHANSTATUS_EN); 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 ((chanenable & AMD756_CHAN_EN(channel)) == 0) { printf("%s: %s ignored (disabled)\n", sc->sc_wdcdev.sc_dev.dv_xname, cp->name); continue; } pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, pciide_pci_intr); if (pciiide_chan_candisable(cp)) chanenable &= ~AMD756_CHAN_EN(channel); pciide_map_compat_intr(pa, cp, channel, interface); if (cp->hw_ok == 0) continue; amd756_setup_channel(&cp->wdc_channel); } pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_CHANSTATUS_EN, chanenable); return;}voidamd756_setup_channel(chp) struct channel_softc *chp;{ u_int32_t udmatim_reg, datatim_reg; u_int8_t idedma_ctl; int mode, drive; struct ata_drive_datas *drvp; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc; idedma_ctl = 0; datatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_DATATIM); udmatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_UDMA); datatim_reg &= ~AMD756_DATATIM_MASK(chp->channel); udmatim_reg &= ~AMD756_UDMA_MASK(chp->channel); /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if ((drvp->drive_flags & DRIVE) == 0) continue; /* add timing values, setup DMA if needed */ if (((drvp->drive_flags & DRIVE_DMA) == 0 && (drvp->drive_flags & DRIVE_UDMA) == 0)) { mode = drvp->PIO_mode; goto pio; } if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) && (drvp->drive_flags & DRIVE_UDMA)) { /* use Ultra/DMA */ drvp->drive_flags &= ~DRIVE_DMA; udmatim_reg |= AMD756_UDMA_EN(chp->channel, drive) | AMD756_UDMA_EN_MTH(chp->channel, drive) | AMD756_UDMA_TIME(chp->channel, drive, amd756_udma_tim[drvp->UDMA_mode]); /* can use PIO timings, MW DMA unused */ mode = drvp->PIO_mode; } else { /* use Multiword DMA */ drvp->drive_flags &= ~DRIVE_UDMA; /* mode = min(pio, dma+2) */ if (drvp->PIO_mode <= (drvp->DMA_mode +2)) mode = drvp->PIO_mode; else mode = drvp->DMA_mode + 2; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);pio: /* setup PIO mode */ if (mode <= 2) { drvp->DMA_mode = 0; drvp->PIO_mode = 0; mode = 0; } else { drvp->PIO_mode = mode; drvp->DMA_mode = mode - 2; } datatim_reg |= AMD756_DATATIM_PULSE(chp->channel, drive, amd756_pio_set[mode]) | AMD756_DATATIM_RECOV(chp->channel, drive, amd756_pio_rec[mode]); } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, IDEDMA_CTL + (IDEDMA_SCH_OFFSET * chp->channel), idedma_ctl); } pciide_print_modes(cp); pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_DATATIM, datatim_reg); pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_UDMA, udmatim_reg);}#endif#ifndef PMONvoidapollo_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)); int channel; u_int32_t ideconf; bus_size_t cmdsize, ctlsize; if (pciide_chipen(sc, pa) == 0) return; printf(": DMA"); pciide_mapreg_dma(sc, pa); if (sc->sc_dma_ok) { sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA; if (sc->sc_pp->ide_product == PCI_PRODUCT_VIATECH_VT82C586A_IDE) sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA; } sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA32 | WDC_CAPABILITY_MODE; sc->sc_wdcdev.PIO_cap = 4; sc->sc_wdcdev.DMA_cap = 2; sc->sc_wdcdev.UDMA_cap = 2; sc->sc_wdcdev.set_modes = apollo_setup_channel; 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); WDCDEBUG_PRINT(("apollo_chip_map: old APO_IDECONF=0x%x, " "APO_CTLMISC=0x%x, APO_DATATIM=0x%x, APO_UDMA=0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, APO_IDECONF), pci_conf_read(sc->sc_pc, sc->sc_tag, APO_CTLMISC), pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM), pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA)), DEBUG_PROBE); for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) { cp = &sc->pciide_channels[channel]; if (pciide_chansetup(sc, channel, interface) == 0) continue; ideconf = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_IDECONF); if ((ideconf & APO_IDECONF_EN(channel)) == 0) { printf("%s: %s ignored (disabled)\n", sc->sc_wdcdev.sc_dev.dv_xname, cp->name); continue; } pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, pciide_pci_intr); if (cp->hw_ok == 0) continue; if (pciiide_chan_candisable(cp)) { ideconf &= ~APO_IDECONF_EN(channel); pci_conf_write(sc->sc_pc, sc->sc_tag, APO_IDECONF, ideconf); } pciide_map_compat_intr(pa, cp, channel, interface); if (cp->hw_ok == 0) continue; apollo_setup_channel(&sc->pciide_channels[channel].wdc_channel); } WDCDEBUG_PRINT(("apollo_chip_map: APO_DATATIM=0x%x, APO_UDMA=0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM), pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA)), DEBUG_PROBE);}voidapollo_setup_channel(chp) struct channel_softc *chp;{ u_int32_t udmatim_reg, datatim_reg; u_int8_t idedma_ctl; int mode, drive; struct ata_drive_datas *drvp; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc; idedma_ctl = 0; datatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_DATATIM); udmatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, APO_UDMA); datatim_reg &= ~APO_DATATIM_MASK(chp->channel); udmatim_reg &= ~AP0_UDMA_MASK(chp->channel); /* setup DMA if needed */ pciide_channel_dma_setup(cp); for (drive = 0; drive < 2; drive++) { drvp = &chp->ch_drive[drive]; /* If no drive, skip */ if ((drvp->drive_flags & DRIVE) == 0) continue; /* add timing values, setup DMA if needed */ if (((drvp->drive_flags & DRIVE_DMA) == 0 && (drvp->drive_flags & DRIVE_UDMA) == 0)) { mode = drvp->PIO_mode; goto pio; } if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) && (drvp->drive_flags & DRIVE_UDMA)) { /* use Ultra/DMA */ drvp->drive_flags &= ~DRIVE_DMA; udmatim_reg |= APO_UDMA_EN(chp->channel, drive) | APO_UDMA_EN_MTH(chp->channel, drive) | APO_UDMA_TIME(chp->channel, drive, apollo_udma_tim[drvp->UDMA_mode]); /* can use PIO timings, MW DMA unused */ mode = drvp->PIO_mode; } else { /* use Multiword DMA */ drvp->drive_flags &= ~DRIVE_UDMA; /* mode = min(pio, dma+2) */ if (drvp->PIO_mode <= (drvp->DMA_mode +2)) mode = drvp->PIO_mode; else mode = drvp->DMA_mode + 2; } idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);pio: /* setup PIO mode */ if (mode <= 2) { drvp->DMA_mode = 0; drvp->PIO_mode = 0; mode = 0; } else { drvp->PIO_mode = mode; drvp->DMA_mode = mode - 2; } datatim_reg |= APO_DATATIM_PULSE(chp->channel, drive, apollo_pio_set[mode]) | APO_DATATIM_RECOV(chp->channel, drive, apollo_pio_rec[mode]); } if (idedma_ctl != 0) { /* Add software bits in status register */ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, IDEDMA_CTL + (IDEDMA_SCH_OFFSET * chp->channel), idedma_ctl); } pciide_print_modes(cp); pci_conf_write(sc->sc_pc, sc->sc_tag, APO_DATATIM, datatim_reg); pci_conf_write(sc->sc_pc, sc->sc_tag, APO_UDMA, udmatim_reg);}#endifvoidcmd_channel_map(pa, sc, channel) struct pci_attach_args *pa; struct pciide_softc *sc; int channel;{ struct pciide_channel *cp = &sc->pciide_channels[channel]; bus_size_t cmdsize, ctlsize; u_int8_t ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CTRL); pcireg_t interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); 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; if (channel > 0) { cp->wdc_channel.ch_queue = sc->pciide_channels[0].wdc_channel.ch_queue; } else { 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; } /* * with a CMD PCI64x, if we get here, the first channel is enabled: * there's no way to disable the first channel without disabling * the whole device */ if (channel != 0 && (ctrl & CMD_CTRL_2PORT) == 0) { printf("%s: %s ignored (disabled)\n", sc->sc_wdcdev.sc_dev.dv_xname, cp->name); return; } pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, cmd_pci_intr); if (cp->hw_ok == 0) return; if (channel == 1) { if (pciiide_chan_candisable(cp)) { ctrl &= ~CMD_CTRL_2PORT; pciide_pci_write(pa->pa_pc, pa->pa_tag, CMD_CTRL, ctrl); } } pciide_map_compat_intr(pa, cp, channel, interface);}intcmd_pci_intr(arg) void *arg;{ struct pciide_softc *sc = arg; struct pciide_channel *cp; struct channel_softc *wdc_cp; int i, rv, crv; u_int32_t priirq, secirq; rv = 0; priirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CONF); secirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23); for (i = 0; i < sc->sc_wdcdev.nchannels; i++) { cp = &sc->pciide_channels[i]; wdc_cp = &cp->wdc_channel; /* If a compat channel skip. */ if (cp->compat) continue; if ((i == 0 && (priirq & CMD_CONF_DRV0_INTR)) || (i == 1 && (secirq & CMD_ARTTIM23_IRQ))) { crv = wdcintr(wdc_cp);#ifdef PMON if (crv == 0) rv = 0; else rv = 1;#else if (crv == 0) printf("%s:%d: bogus intr\n", sc->sc_wdcdev.sc_dev.dv_xname, i); else rv = 1;#endif /* PMON */ } } return rv;}voidcmd_chip_map(sc, pa) struct pciide_softc *sc; struct pci_attach_args *pa;{ int channel; pcireg_t interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); /* * For a CMD PCI064x, the use of PCI_COMMAND_IO_ENABLE * and base adresses registers can be disabled at * hardware level. In this case, the device is wired * in compat mode and its first channel is always enabled, * but we can't rely on PCI_COMMAND_IO_ENABLE. * In fact, it seems that the first channel of the CMD PCI0640 * can't be disabled. */#ifdef PCIIDE_CMD064x_DISABLE if (pciide_chipen(sc, pa) == 0) return;#endif printf(": no DMA"); sc->sc_dma_ok = 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++) { cmd_channel_map(pa, sc, channel); }}voidcmd0643_6_chip_map(sc, pa) struct pciide_softc *sc; struct pci_attach_args *pa;{ struct pciide_channel *cp; int channel; pcireg_t interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); /* * For a CMD PCI064x, the use of PCI_COMMAND_IO_ENABLE * and base adresses registers can be disabled at * hardware level. In this case, the device is wired * in compat mode and its first channel is always enabled, * but we can't rely on PCI_COMMAND_IO_ENABLE. * In fact, it seems that the first channel of the CMD PCI0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -