From 48e7ce94218314de565745911b2e1641c46fa5d3 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Mon, 14 Oct 2002 11:37:59 -0700 Subject: [PATCH] alpha ISA dma and MAX_DMA_ADDRESS Thanks David Miller, Jay Estabrook and Richard Henderson for reviewing the patch and for corrections. Description: The ISA dma falls into 2 classes. 1. True busmastering (aka DMA_MODE_CASCADE) when the ISA device generate bus addresses by itself. Obviously, such devices are limited to lower 16 Mb as there are only 24 address lines on the ISA bus. Drivers for these devices pass NULL pdev argument to pci mapping functions, and we must always use dma_mask = 0x00ffffff in this case. 2. ISA devices using i8237 DMA controller functionality: floppy, all soundcards (AFAIK) and a lot of other cheap ISA cards. In this case actual device doing DMA is a PCI-to-ISA bridge. Quite a few of ISA bridges can do 32-bit DMA (using "high page" extensions), and alpha traditionally uses this. I propose the following: introduce 'struct pci_dev *isa_bridge' global variable; this will be pointer to either real bridge device found by pci probing code, or a fake device in special cases (like jensen running generic kernel). isa_bridge->dma_mask will be set depending on DMA capabilities of particular bridge (either using generic quirk list or in an arch specific manner). This would allow devices like floppy and audio utilize 32-bit DMA just by replacing 'NULL' with 'isa_bridge' in the pci mapping calls. Also, this helps to resolve ISA dma vs. MAX_DMA_ADDRESS mess on alpha. Setting MAX_DMA_ADDRESS depending on the number of address lines on the ISA bridge became bogus since early 2.4 when we started to use the SG windows. Basically, if we have a working iommu, we don't have any dma limitations. All we need is a correct dma_mask to choose proper dma window. OTOH, there are 'iommuless' alphas (rx164, nautilus, possibly early miata) which need to have 16 Mb GFP_DMA zone (just like i386) even if their ISA bridge is 32-bit. Proposed changes: - rename all XXX_MAX_DMA_ADDRESS to XXX_MAX_ISA_DMA_ADDRESS; alpha_mv.max_dma_address - ditto (it's about 90% of the patch); - ISA bridge on nautilus does support 32-bit dma; - MAX_DMA_ADDRESS is 16 Mb if there is no iommu, ~0UL (unlimited) otherwise; - if needed, fall back to GFP_DMA allocations in pci_alloc_consistent(); - pci_dma_supported() also returns success if GFP_DMA is helpful; - isa_bridge stuff. Used only by floppy as yet. Ivan. --- include/asm-alpha/dma.h | 33 ++++++++++++++++++--------------- include/asm-alpha/floppy.h | 4 ++-- include/asm-alpha/machvec.h | 2 +- include/linux/pci.h | 6 ++++++ 4 files changed, 27 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/asm-alpha/dma.h b/include/asm-alpha/dma.h index 97daf7d786aa..dc46ba5b4f1c 100644 --- a/include/asm-alpha/dma.h +++ b/include/asm-alpha/dma.h @@ -85,44 +85,47 @@ /* The maximum address for ISA DMA transfer on Alpha XL, due to an hardware SIO limitation, is 64MB. */ -#define ALPHA_XL_MAX_DMA_ADDRESS (IDENT_ADDR+0x04000000UL) +#define ALPHA_XL_MAX_ISA_DMA_ADDRESS 0x04000000UL -/* The maximum address for ISA DMA transfer on RUFFIAN and NAUTILUS, +/* The maximum address for ISA DMA transfer on RUFFIAN, due to an hardware SIO limitation, is 16MB. */ -#define ALPHA_RUFFIAN_MAX_DMA_ADDRESS (IDENT_ADDR+0x01000000UL) -#define ALPHA_NAUTILUS_MAX_DMA_ADDRESS (IDENT_ADDR+0x01000000UL) +#define ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS 0x01000000UL /* The maximum address for ISA DMA transfer on SABLE, and some ALCORs, due to an hardware SIO chip limitation, is 2GB. */ -#define ALPHA_SABLE_MAX_DMA_ADDRESS (IDENT_ADDR+0x80000000UL) -#define ALPHA_ALCOR_MAX_DMA_ADDRESS (IDENT_ADDR+0x80000000UL) +#define ALPHA_SABLE_MAX_ISA_DMA_ADDRESS 0x80000000UL +#define ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS 0x80000000UL /* Maximum address for all the others is the complete 32-bit bus address space. */ -#define ALPHA_MAX_DMA_ADDRESS (IDENT_ADDR+0x100000000UL) +#define ALPHA_MAX_ISA_DMA_ADDRESS 0x100000000UL #ifdef CONFIG_ALPHA_GENERIC -# define MAX_DMA_ADDRESS (alpha_mv.max_dma_address) +# define MAX_ISA_DMA_ADDRESS (alpha_mv.max_isa_dma_address) #else # if defined(CONFIG_ALPHA_XL) -# define MAX_DMA_ADDRESS ALPHA_XL_MAX_DMA_ADDRESS +# define MAX_ISA_DMA_ADDRESS ALPHA_XL_MAX_ISA_DMA_ADDRESS # elif defined(CONFIG_ALPHA_RUFFIAN) -# define MAX_DMA_ADDRESS ALPHA_RUFFIAN_MAX_DMA_ADDRESS -# elif defined(CONFIG_ALPHA_NAUTILUS) -# define MAX_DMA_ADDRESS ALPHA_NAUTILUS_MAX_DMA_ADDRESS +# define MAX_ISA_DMA_ADDRESS ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS # elif defined(CONFIG_ALPHA_SABLE) -# define MAX_DMA_ADDRESS ALPHA_SABLE_MAX_DMA_ADDRESS +# define MAX_ISA_DMA_ADDRESS ALPHA_SABLE_MAX_DMA_ISA_ADDRESS # elif defined(CONFIG_ALPHA_ALCOR) -# define MAX_DMA_ADDRESS ALPHA_ALCOR_MAX_DMA_ADDRESS +# define MAX_ISA_DMA_ADDRESS ALPHA_ALCOR_MAX_DMA_ISA_ADDRESS # else -# define MAX_DMA_ADDRESS ALPHA_MAX_DMA_ADDRESS +# define MAX_ISA_DMA_ADDRESS ALPHA_MAX_ISA_DMA_ADDRESS # endif #endif +/* If we have the iommu, we don't have any address limitations on DMA. + Otherwise (Nautilus, RX164), we have to have 0-16 Mb DMA zone + like i386. */ +#define MAX_DMA_ADDRESS (alpha_mv.mv_pci_tbi ? \ + ~0UL : IDENT_ADDR + 0x01000000) + /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ #define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ diff --git a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h index 88049a927ddd..db527586c23f 100644 --- a/include/asm-alpha/floppy.h +++ b/include/asm-alpha/floppy.h @@ -51,12 +51,12 @@ alpha_fd_dma_setup(char *addr, unsigned long size, int mode, int io) if (bus_addr && (addr != prev_addr || size != prev_size || dir != prev_dir)) { /* different from last time -- unmap prev */ - pci_unmap_single(NULL, bus_addr, prev_size, prev_dir); + pci_unmap_single(isa_bridge, bus_addr, prev_size, prev_dir); bus_addr = 0; } if (!bus_addr) /* need to map it */ - bus_addr = pci_map_single(NULL, addr, size, dir); + bus_addr = pci_map_single(isa_bridge, addr, size, dir); /* remember this one as prev */ prev_addr = addr; diff --git a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h index ca6bbf25cb12..5becb8ef34eb 100644 --- a/include/asm-alpha/machvec.h +++ b/include/asm-alpha/machvec.h @@ -34,7 +34,7 @@ struct alpha_machine_vector int nr_irqs; int rtc_port; int max_asn; - unsigned long max_dma_address; + unsigned long max_isa_dma_address; unsigned long irq_probe_mask; unsigned long iack_sc; unsigned long min_io_address; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0d3d8f622b26..b49dd6f113a7 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -643,6 +643,10 @@ void pci_pool_destroy (struct pci_pool *pool); void *pci_pool_alloc (struct pci_pool *pool, int flags, dma_addr_t *handle); void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr); +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) +extern struct pci_dev *isa_bridge; +#endif + #endif /* CONFIG_PCI */ /* Include architecture-dependent settings and functions */ @@ -703,6 +707,8 @@ static inline int pci_enable_wake(struct pci_dev *dev, u32 state, int enable) { #define pci_for_each_dev(dev) \ for(dev = NULL; 0; ) +#define isa_bridge ((struct pci_dev *)NULL) + #else /* -- cgit v1.2.3