Example #1
0
void
wdc_obio_ata4_adjust_timing(struct channel_softc *chp)
{
	struct ata_drive_datas *drvp;
	u_int conf;
	int drive;
	int piomode = -1, dmamode = -1;
	int min_cycle, min_active;
	int cycle_tick, act_tick, inact_tick;
	int udmamode = -1;

	for (drive = 0; drive < 2; drive++) {
		drvp = &chp->ch_drive[drive];
		if ((drvp->drive_flags & DRIVE) == 0)
			continue;
		if (piomode == -1 || piomode > drvp->PIO_mode)
			piomode = drvp->PIO_mode;
		if (drvp->drive_flags & DRIVE_DMA)
			if (dmamode == -1 || dmamode > drvp->DMA_mode)
				dmamode = drvp->DMA_mode;
		if (drvp->drive_flags & DRIVE_UDMA) {
			if (udmamode == -1 || udmamode > drvp->UDMA_mode)
				udmamode = drvp->UDMA_mode;
		} else
			udmamode = -2;
	}
	if (piomode == -1)
		return; /* No drive */
	for (drive = 0; drive < 2; drive++) {
		drvp = &chp->ch_drive[drive];
		if (drvp->drive_flags & DRIVE) {
			drvp->PIO_mode = piomode;
			if (drvp->drive_flags & DRIVE_DMA)
				drvp->DMA_mode = dmamode;
			if (drvp->drive_flags & DRIVE_UDMA) {
				if (udmamode == -2)
					drvp->drive_flags &= ~DRIVE_UDMA;
				else
					drvp->UDMA_mode = udmamode;
			}
		}
	}

	if (udmamode == -2)
		udmamode = -1;

	min_cycle = pio_timing[piomode].cycle;
	min_active = pio_timing[piomode].active;

	cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
	act_tick = ATA4_TIME_TO_TICK(min_active);
	inact_tick = cycle_tick - act_tick;
	/* mask: 0x000003ff */
	conf = (inact_tick << 5) | act_tick;
	if (dmamode != -1) {
		/* there are active  DMA mode */

		min_cycle = dma_timing[dmamode].cycle;
		min_active = dma_timing[dmamode].active;
		cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
		act_tick = ATA4_TIME_TO_TICK(min_active);
		inact_tick = cycle_tick - act_tick;
		/* mask: 0x001ffc00 */
		conf |= (act_tick << 10) | (inact_tick << 15);
	}
	if (udmamode != -1) {
		min_cycle = udma_timing[udmamode].cycle;
		min_active = udma_timing[udmamode].active;
		act_tick = ATA4_TIME_TO_TICK(min_active);
		cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
		/* mask: 0x1ff00000 */
		conf |= (cycle_tick << 21) | (act_tick << 25) | 0x100000;
	}

	bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
#if 0
	printf("ata4 conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
	    conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
#endif
}
void
ata4_adjust_timing(struct ata_channel *chp)
{
	struct wdc_obio_softc *sc = (struct wdc_obio_softc *)chp->ch_atac;
	int drive;
	int min_cycle = 0, min_active = 0;
	int cycle_tick = 0, act_tick = 0, inact_tick = 0;

	for (drive = 0; drive < 2; drive++) {
		u_int conf = 0;
		struct ata_drive_datas *drvp;

		drvp = &chp->ch_drive[drive];
		/* set up pio mode timings */

		if (drvp->drive_type != ATA_DRIVET_NONE) {
			int piomode = drvp->PIO_mode;
			min_cycle = pio_timing[piomode].cycle;
			min_active = pio_timing[piomode].active;

			cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
			act_tick = ATA4_TIME_TO_TICK(min_active);
			inact_tick = cycle_tick - act_tick;
			/* mask: 0x000003ff */
			conf |= (inact_tick << 5) | act_tick;
		}
		/* set up dma mode timings */
		if (drvp->drive_flags & ATA_DRIVE_DMA) {
			int dmamode = drvp->DMA_mode;
			min_cycle = dma_timing[dmamode].cycle;
			min_active = dma_timing[dmamode].active;
			cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
			act_tick = ATA4_TIME_TO_TICK(min_active);
			inact_tick = cycle_tick - act_tick;
			/* mask: 0x001ffc00 */
			conf |= (act_tick << 10) | (inact_tick << 15);
		}
		/* set up udma mode timings */
		if (drvp->drive_flags & ATA_DRIVE_UDMA) {
			int udmamode = drvp->UDMA_mode;
			min_cycle = udma_timing[udmamode].cycle;
			min_active = udma_timing[udmamode].active;
			act_tick = ATA4_TIME_TO_TICK(min_active);
			cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
			/* mask: 0x1ff00000 */
			conf |= (cycle_tick << 21) | (act_tick << 25) | 0x100000;
		}
#ifdef DEBUG
		if (conf) {
			printf("ata4 conf[%d] = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
					drive, conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
		}
#endif
		sc->sc_dmaconf[drive] = conf;
	}
	sc->sc_wdcdev.select = 0;
	if (sc->sc_dmaconf[0]) {
		wdc_obio_select(chp,0);
		if (sc->sc_dmaconf[1] &&
		    (sc->sc_dmaconf[0] != sc->sc_dmaconf[1])) {
			sc->sc_wdcdev.select = wdc_obio_select;
		}
	} else if (sc->sc_dmaconf[1]) {
		wdc_obio_select(chp,1);
	}
}