Update of /cvsroot/alsa/alsa-kernel/pci
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28890

Modified Files:
        intel8x0.c 
Log Message:
- added the workaround for a hardware bug in intel 440MX B-stepping.








Index: intel8x0.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/intel8x0.c,v
retrieving revision 1.105
retrieving revision 1.106
diff -u -r1.105 -r1.106
--- intel8x0.c  26 Jan 2004 10:58:37 -0000      1.105
+++ intel8x0.c  26 Jan 2004 11:28:34 -0000      1.106
@@ -41,6 +41,9 @@
 #include <sound/mpu401.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
+/* for 440MX workaround */
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <[EMAIL PROTECTED]>");
 MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; 
Ali 5455");
@@ -401,6 +404,7 @@
            smp20bit: 1;
        int in_ac97_init: 1,
            in_sdin_init: 1;
+       int fix_nocache: 1; /* workaround for 440MX */
 
        ac97_bus_t *ac97_bus;
        ac97_t *ac97[3];
@@ -721,6 +725,23 @@
        iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
 }
 
+#ifdef __i386__
+/*
+ * Intel 82443MX running a 100MHz processor system bus has a hardware bug,
+ * which aborts PCI busmaster for audio transfer.  A workaround is to set
+ * the pages as non-cached.  For details, see the errata in
+ *     http://www.intel.com/design/chipsets/specupdt/245051.htm
+ */
+static void fill_nocache(void *buf, int size, int nocache)
+{
+       size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       change_page_attr(virt_to_page(buf), size, nocache ? PAGE_KERNEL_NOCACHE : 
PAGE_KERNEL);
+       global_flush_tlb();
+}
+#else
+#define fill_nocache(buf,size,nocache)
+#endif
+
 /*
  *  Interrupt handler
  */
@@ -888,11 +909,17 @@
 {
        intel8x0_t *chip = snd_pcm_substream_chip(substream);
        ichdev_t *ichdev = get_ichdev(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       size_t size = params_buffer_bytes(hw_params);
        int err;
 
+       if (chip->fix_nocache && runtime->dma_area && runtime->dma_bytes < size)
+               fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); /* clear */
        err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
        if (err < 0)
                return err;
+       if (chip->fix_nocache && err > 0)
+               fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
@@ -911,12 +938,15 @@
 
 static int snd_intel8x0_hw_free(snd_pcm_substream_t * substream)
 {
+       intel8x0_t *chip = snd_pcm_substream_chip(substream);
        ichdev_t *ichdev = get_ichdev(substream);
 
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
        }
+       if (chip->fix_nocache && substream->runtime->dma_area)
+               fill_nocache(substream->runtime->dma_area, 
substream->runtime->dma_bytes, 0);
        return snd_pcm_lib_free_pages(substream);
 }
 
@@ -2047,8 +2077,11 @@
        /* --- */
        synchronize_irq(chip->irq);
       __hw_end:
-       if (chip->bdbars)
+       if (chip->bdbars) {
+               if (chip->fix_nocache)
+                       fill_nocache(chip->bdbars, chip->bdbars_count * sizeof(u32) * 
ICH_MAX_FRAGS * 2, 0);
                snd_free_pci_pages(chip->pci, chip->bdbars_count * sizeof(u32) * 
ICH_MAX_FRAGS * 2, chip->bdbars, chip->bdbars_addr);
+       }
        if (chip->remap_addr)
                iounmap((void *) chip->remap_addr);
        if (chip->remap_bmaddr)
@@ -2337,6 +2370,9 @@
        snd_intel8x0_proc_init(chip);
        sprintf(chip->ac97_name, "%s - AC'97", card->shortname);
        sprintf(chip->ctrl_name, "%s - Controller", card->shortname);
+       if (pci->vendor == PCI_VENDOR_ID_INTEL &&
+           pci->device == PCI_DEVICE_ID_INTEL_440MX)
+               chip->fix_nocache = 1; /* enable workaround */
        if (device_type == DEVICE_ALI) {
                /* ALI5455 has no ac97 region */
                chip->bmaddr = pci_resource_start(pci, 0);
@@ -2445,6 +2481,9 @@
        }
        /* tables must be aligned to 8 bytes here, but the kernel pages
           are much bigger, so we don't care (on i386) */
+       /* workaround for 440MX */
+       if (chip->fix_nocache)
+               fill_nocache(chip->bdbars, chip->bdbars_count * sizeof(u32) * 
ICH_MAX_FRAGS * 2, 1);
        int_sta_masks = 0;
        for (i = 0; i < chip->bdbars_count; i++) {
                ichdev = &chip->ichd[i];



-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to