[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: (wdc_obio.c) ata-4 improves 40% in transfer



>○ ところで wd1 として MDMA が付いている時に、つまり次のような時に、
 ...
>○ 次のように止ってしまいます。

wdc を Ultra のタイミングにしちゃうので当然なんですが、もちろん
それでいいわけないのでこれ↓で遅いほうに合わせます。

この場合、たぶん dd で計る速度は以前よりかなり遅くなります。普通の
MDMA 並に、ってことですけど。

# 書きかけなので再配付には注意してください。以前の ADB のパッチみたい
# に連絡なしに commit しちゃうこまったちゃんがいますので。

*** wdc_obio.c~	Sat Jun 16 02:02:41 2001
--- wdc_obio.c	Sun Jul  1 20:47:48 2001
***************
*** 81,86 ****
--- 81,87 ----
  void wdc_obio_dma_start __P((void *, int, int));
  int wdc_obio_dma_finish __P((void *, int, int, int));
  static void adjust_timing __P((struct channel_softc *));
+ static void adjust_timing_ata4 __P((struct channel_softc *));
  
  struct cfattach wdc_obio_ca = {
  	sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach,
***************
*** 187,192 ****
--- 188,203 ----
  	sc->sc_wdcdev.dma_start = wdc_obio_dma_start;
  	sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish;
  	sc->sc_wdcdev.set_modes = adjust_timing;
+ 
+ 	if (strcmp(ca->ca_name, "ata-4") == 0) {
+ 		sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
+ 		sc->sc_wdcdev.UDMA_cap = 4;
+ 		sc->sc_wdcdev.set_modes = adjust_timing_ata4;
+ #if 1
+ 		printf("%s: ata-4\n", self->dv_xname);
+ #endif
+ 	}
+ 
  	chp->channel = 0;
  	chp->wdc = &sc->sc_wdcdev;
  	chp->ch_queue = malloc(sizeof(struct channel_queue),
***************
*** 212,221 ****
  
  	wdcattach(chp);
  
! 	/* modify DMA access timings */
! 	if (use_dma)
! 		adjust_timing(chp);
! 
  }
  
  /* Multiword DMA transfer timings */
--- 223,230 ----
  
  	wdcattach(chp);
  
! 	/* Modify access timings. */
! 	sc->sc_wdcdev.set_modes(chp);
  }
  
  /* Multiword DMA transfer timings */
***************
*** 236,242 ****
  	{ 120,  70 },	/* Mode 2 */
  };
  
! #define TIME_TO_TICK(time) howmany((time), 30)
  
  #define CONFIG_REG (0x200 >> 4)		/* IDE access timing register */
  
--- 245,252 ----
  	{ 120,  70 },	/* Mode 2 */
  };
  
! #define TIME_TO_TICK(time)	howmany(time, 30)
! #define TIME_TO_TICK_ATA4(time)	howmany((time) * 2, 15)
  
  #define CONFIG_REG (0x200 >> 4)		/* IDE access timing register */
  
***************
*** 295,300 ****
--- 305,395 ----
  		conf |=
  		    (half_tick << 21) | (inact_tick << 16) | (act_tick << 11);
  	}
+ 	bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
+ #if 0
+ 	printf("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
+ 	wdc_print_modes(chp);
+ }
+ 
+ void
+ adjust_timing_ata4(chp)
+ 	struct channel_softc *chp;
+ {
+ 	struct ata_drive_datas *drvp;
+ 	u_int conf;
+ 	int drive;
+ 	int piomode = -1, dmamode = -1, udmamode = -1;
+ 	int min_cycle, min_active;
+ 	int cycle_tick, act_tick, inact_tick;
+ 
+ 	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->DMA_mode)
+ 				udmamode = drvp->UDMA_mode;
+ 		} else
+ 			udmamode = -2;
+ 	}
+ 	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 < 0)
+ 					drvp->drive_flags &= ~DRIVE_UDMA;
+ 				else
+ 					drvp->UDMA_mode = udmamode;
+ 			}
+ 		}
+ 	}
+ 	min_cycle = pio_timing[piomode].cycle;
+ 	min_active = pio_timing[piomode].active;
+ 
+ 	cycle_tick = TIME_TO_TICK_ATA4(min_cycle);
+ 	act_tick = TIME_TO_TICK_ATA4(min_active);
+ 	inact_tick = cycle_tick - act_tick;
+ 
+ 	/* conf &= ~0x3ff; 5-5 */
+ 	conf = (inact_tick << 5) | act_tick;
+ 
+ 	if (dmamode >= 0) {
+ 		/* there are active DMA mode */
+ 
+ 		min_cycle = dma_timing[dmamode].cycle;
+ 		min_active = dma_timing[dmamode].active;
+ 
+ 		cycle_tick = TIME_TO_TICK_ATA4(min_cycle);
+ 		act_tick = TIME_TO_TICK_ATA4(min_active);
+ 		inact_tick = cycle_tick - act_tick;
+ 
+ 		/* XXX */
+ 		inact_tick = min(inact_tick, 31);
+ 
+ 		/* conf &= ~0x001ffc00; 1-5-5? */
+ 		conf |= inact_tick << 15 | act_tick << 10;
+ 	}
+ 
+ 	if (udmamode >= 0) {
+ 		/* XXX really? */
+ 		act_tick = 0;
+ 		cycle_tick = 0;
+ 
+ 		/* conf &= ~0x1ff00000; 4-4-1 */
+ 		conf |= act_tick << 25 | cycle_tick << 21 | 1 << 20;
+ 	}
+ 
  	bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
  #if 0
  	printf("conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",