From owner-FreeBSD-users-jp@jp.freebsd.org  Fri Aug 24 02:44:20 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id CAA71966;
	Fri, 24 Aug 2001 02:44:20 +0900 (JST)
	(envelope-from owner-FreeBSD-users-jp@jp.FreeBSD.org)
Received: from mail.katsurajima.seya.yokohama.jp (mail.katsurajima.seya.yokohama.jp [210.164.211.67])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id CAA71961
	for <freebsd-users-jp@jp.FreeBSD.ORG>; Fri, 24 Aug 2001 02:44:18 +0900 (JST)
	(envelope-from raven@katsurajima.seya.yokohama.jp)
Received: from monster.katsurajima.seya.yokohama.jp (gw-global.katsurajima.seya.yokohama.jp [192.168.2.3])
	by mail.katsurajima.seya.yokohama.jp (Postfix) with ESMTP
	id 8CEAA1D8C08; Fri, 24 Aug 2001 02:43:42 +0900 (JST)
Received: from zenchan.katsurajima.seya.yokohama.jp (zenchan [192.168.1.3])
	by monster.katsurajima.seya.yokohama.jp (8.9.3/3.7W05/05/99) with SMTP id CAA51898;
	Fri, 24 Aug 2001 02:43:42 +0900 (JST)
Date: Fri, 24 Aug 2001 02:43:18 +0900
From: Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
To: FreeBSD-multimedia@FreeBSD.ORG
Cc: freebsd-users-jp@jp.FreeBSD.ORG
Message-Id: <20010824024318.13add558.raven@katsurajima.seya.yokohama.jp>
X-Mailer: Sylpheed version 0.4.66 (GTK+ 1.2.10; i386--freebsd5.0)
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
Reply-To: FreeBSD-users-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: FreeBSD-users-jp 63731
Subject: [FreeBSD-users-jp 63731] 4.4-RC ich sound driver bug fix
Errors-To: owner-FreeBSD-users-jp@jp.freebsd.org
Sender: owner-FreeBSD-users-jp@jp.freebsd.org
X-Originator: raven@katsurajima.seya.yokohama.jp

Hellow.

I fixed sound driver for Intel ICH AC'97. Changed points are

- FIFO buffer control method is now been strict. By this change, CPU
  and DMA are never conflict on same buffer block. Many troubles
  are occured by this conflict.

- Not use ICH's PICB(Position In Current Buffer) function for getting
  hardware pointer. This function seems to be buggy, and not only
  untrused on the value, but also getting trouble. On the other hand,
  this driver cannot check playing position under block size. But many
  case, this is not so big problem.

- and few little fixes

I checked this driver with xmms, xine, rollemup and timidity++. Under
first 3 programs, there is no problem and very stable on my notebook
PC(Toshiba DynaBookSS3440). But timidity++ plays with crick noise.(I
have not checked yet why)

It may be better to reboot by power off/on than by reboot command, after
attemp patch and rebuild kernel. It is because of clearing illeagal
condition caused by old driver.

This patch is tested only on 4.4-RC. But may work on -CURRENT.

Please check it.
-- 
Katsurajima "Raven" Naoto($B7KEg(B $BD>?M(B)
Family Emblem: Circle and Left 3 Clove-TOMOE($B4]$K:8;0$DCz;RGC(B)
e-mail: raven@katsurajima.seya.yokohama.jp

--- cut here
*** sys/dev/sound/pci/ich.c.orig	Wed Aug  1 14:37:30 2001
--- sys/dev/sound/pci/ich.c	Thu Aug 23 10:32:55 2001
***************
*** 53,58 ****
--- 53,59 ----
  	u_int32_t num, run;
  	u_int32_t blksz, blkcnt;
  	u_int32_t regbase, spdreg;
+ 	u_int32_t civ;
  
  	struct snd_dbuf *buffer;
  	struct pcm_channel *channel;
***************
*** 296,302 ****
  
  	ch->blksz = blocksize;
  	ich_filldtbl(ch);
! 	ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ICH_DTBL_LENGTH - 1, 1);
  
  	return ch->blksz;
  }
--- 297,303 ----
  
  	ch->blksz = blocksize;
  	ich_filldtbl(ch);
! 	ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
  
  	return ch->blksz;
  }
***************
*** 306,311 ****
--- 307,313 ----
  {
  	struct sc_chinfo *ch = data;
  	struct sc_info *sc = ch->parent;
+ 	u_int32_t st;
  
  	switch (go) {
  	case PCMTRIG_START:
***************
*** 314,319 ****
--- 316,327 ----
  		ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE | ICH_X_CR_FEIE, 1);
  		break;
  
+ 	case PCMTRIG_STOP:
+ 		ch->run = 0;
+ 		st = ich_rd(sc, ch->regbase + ICH_REG_X_CR, 1);
+ 		ich_wr(sc, ch->regbase + ICH_REG_X_CR, st & ~ICH_X_CR_RPBM, 1);
+ 		break;
+ 
  	case PCMTRIG_ABORT:
  		ich_resetchan(sc, ch->num);
  		ch->run = 0;
***************
*** 327,344 ****
  {
  	struct sc_chinfo *ch = data;
  	struct sc_info *sc = ch->parent;
! 	u_int32_t ci, ofs, pos;
  
- 	ofs = 0;
  	ci = 1234;
! 	while (ci != ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1)) {
  		ci = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
- 		ofs = ich_rd(sc, ch->regbase + ICH_REG_X_PICB, 2) * 2;
- 	}
  
! 	ofs = ch->blksz - ofs;
  	ci %= ch->blkcnt;
! 	pos = (ch->blksz * ci) + ofs;
  
  	return pos;
  }
--- 335,349 ----
  {
  	struct sc_chinfo *ch = data;
  	struct sc_info *sc = ch->parent;
! 	u_int32_t ci, pos;
  
  	ci = 1234;
! 	while (ci != ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1))
  		ci = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
  
! 	ch->civ = ci;
  	ci %= ch->blkcnt;
! 	pos = ch->blksz * ci;
  
  	return pos;
  }
***************
*** 371,377 ****
  {
  	struct sc_info *sc = (struct sc_info *)p;
  	struct sc_chinfo *ch;
! 	u_int32_t st, lvi;
  	int i;
  
  	for (i = 0; i < 3; i++) {
--- 376,382 ----
  {
  	struct sc_info *sc = (struct sc_info *)p;
  	struct sc_chinfo *ch;
! 	u_int32_t st, lvi, cbi, lbi;
  	int i;
  
  	for (i = 0; i < 3; i++) {
***************
*** 385,391 ****
  				if (ch->run)
  					chn_intr(ch->channel);
  				lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
! 				lvi++;
  				lvi %= ICH_DTBL_LENGTH;
  				ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
  			}
--- 390,405 ----
  				if (ch->run)
  					chn_intr(ch->channel);
  				lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
! 				cbi = ch->civ % ch->blkcnt;
! 				if (cbi == 0)
! 					cbi = ch->blkcnt - 1;
! 				else
! 					cbi--;
! 				lbi = lvi % ch->blkcnt;
! 				if (cbi >= lbi)
! 					lvi += cbi - lbi;
! 				else
! 					lvi += cbi + ch->blkcnt - lbi;
  				lvi %= ICH_DTBL_LENGTH;
  				ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
  			}
***************
*** 419,425 ****
  
  	ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
  
! 	if (ich_resetchan(sc, 0) || ich_resetchan(sc, 0))
  		return ENXIO;
  
  	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap))
--- 433,439 ----
  
  	ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
  
! 	if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1))
  		return ENXIO;
  
  	if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap))
***************
*** 475,481 ****
  	sc->dev = dev;
  
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
! 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
  	pci_write_config(dev, PCIR_COMMAND, data, 2);
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
  
--- 489,495 ----
  	sc->dev = dev;
  
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
! 	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
  	pci_write_config(dev, PCIR_COMMAND, data, 2);
  	data = pci_read_config(dev, PCIR_COMMAND, 2);
  
***************
*** 494,500 ****
  	sc->nabmbart = rman_get_bustag(sc->nabmbar);
  	sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
  
! 	if (bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  			       NULL, NULL, ICH_DEFAULT_BUFSZ, 1, 0x3ffff, 0, &sc->dmat) != 0) {
  		device_printf(dev, "unable to create dma tag\n");
  		goto bad;
--- 508,514 ----
  	sc->nabmbart = rman_get_bustag(sc->nabmbar);
  	sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
  
! 	if (bus_dma_tag_create(NULL, 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  			       NULL, NULL, ICH_DEFAULT_BUFSZ, 1, 0x3ffff, 0, &sc->dmat) != 0) {
  		device_printf(dev, "unable to create dma tag\n");
  		goto bad;
