--- linux-2.4.18.SuSE/drivers/ide/ide-dma.c Wed Mar 27 10:58:32 2002 +++ linux-2.4.18.SuSE.axp/drivers/ide/ide-dma.c Fri Apr 5 12:41:34 2002 @@ -326,6 +326,9 @@ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } +#if defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_GENERIC) +extern int have_pyxis_pagecross_bug; +#endif /* * ide_build_dmatable() prepares a dma request. * Returns 0 if all went okay, returns 1 otherwise. @@ -377,6 +380,25 @@ xcount = bcount & 0xffff; if (is_trm290_chipset) xcount = ((xcount >> 2) - 1) << 16; + + /* garloff@suse.de, 2001-12-11: Don't cross page boundaries + * on boards with pyxis dma read page bound cross bug + * when writing (DMA read) */ +#if defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_GENERIC) + if (have_pyxis_pagecross_bug && func == ide_dma_write + && HWIF(drive)->pci_dev->bus->number == 0) { + if (xcount ==0) + xcount = 0x10000; + while ((cur_addr & (PAGE_SIZE-1)) + xcount > PAGE_SIZE) { + u32 newcnt = PAGE_SIZE - (cur_addr & (PAGE_SIZE-1)); + if (count++ >= PRD_ENTRIES) + goto use_pio_instead; + *table++ = cpu_to_le32(newcnt); + *table++ = cpu_to_le32(cur_addr += newcnt); + xcount -= newcnt; + } + } +#endif if (xcount == 0x0000) { /* * Most chipsets correctly interpret a length @@ -389,12 +411,16 @@ goto use_pio_instead; *table++ = cpu_to_le32(0x8000); - *table++ = cpu_to_le32(cur_addr + 0x8000); + *table++ = cpu_to_le32(cur_addr += 0x8000); xcount = 0x8000; } - *table++ = cpu_to_le32(xcount); - cur_addr += bcount; + cur_addr += xcount; cur_len -= bcount; + // *table++ = cpu_to_le32(xcount | (cur_len? 0: 0x80000000)); + /* garloff@suse.de, 2001-12-11: We don't mark the last PDR segment + * with EOT bit (31) in length field, but let the drive + * send us an interrupt. */ + *table++ = cpu_to_le32(xcount); } sg++; --- linux-2.4.18.SuSE/arch/alpha/kernel/core_cia.c Sun Oct 21 19:30:58 2001 +++ linux-2.4.18.SuSE.axp/arch/alpha/kernel/core_cia.c Fri Apr 5 12:38:47 2002 @@ -388,6 +388,14 @@ *(vip)CIA_IOC_PCI_T1_BASE = virt_to_phys(ppte) >> 2; } +/* garloff@suse.de, 2001-12-11: + * Flag set, if we suffer PYXIS page crossing corruption on DMA reads. + * Note: All PCI devices sitting on primary PCI bus doing busmaster DMA + * should check this flag and adjust their SG tables accordingly for reads + * from memory (i.e. writes to device). See ide-dma.c code for an example. + */ +int have_pyxis_pagecross_bug; + static void __init verify_tb_operation(void) { @@ -565,6 +573,8 @@ /* Clean up after the tests. */ arena->ptes[4] = 0; arena->ptes[5] = 0; + *(vip)CIA_IOC_TBn_PAGEm(0,0) = 0; + *(vip)CIA_IOC_TB_TAGn(0) = 0; if (use_tbia_try2) { alpha_mv.mv_pci_tbi = cia_pci_tbi_try2; @@ -760,6 +770,9 @@ hwrpb_update_checksum(hwrpb); do_init_arch(1); + /* Normally, we should check for the presence of this bug, + * but there's no easy way to detect it. KG, 2001-12-18. */ + have_pyxis_pagecross_bug = 1; } void __init --- linux-2.4.18.SuSE/arch/alpha/kernel/alpha_ksyms.c Wed Mar 27 10:58:30 2002 +++ linux-2.4.18.SuSE.axp/arch/alpha/kernel/alpha_ksyms.c Fri Apr 5 13:10:59 2002 @@ -263,7 +263,12 @@ EXPORT_SYMBOL(get_wchan); -#ifdef CONFIG_ALPHA_IRONGATE +#if defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_GENERIC) +extern int have_pyxis_pagecross_bug; +EXPORT_SYMBOL_NOVERS(have_pyxis_pagecross_bug); +#endif + +# ifdef CONFIG_ALPHA_IRONGATE EXPORT_SYMBOL(irongate_ioremap); EXPORT_SYMBOL(irongate_iounmap); #endif