patch-2.4.22 linux-2.4.22/arch/ia64/sn/io/pciba.c
Next file: linux-2.4.22/arch/ia64/sn/io/pciio.c
Previous file: linux-2.4.22/arch/ia64/sn/io/pci_dma.c
Back to the patch index
Back to the overall index
- Lines: 917
- Date:
1969-12-31 16:00:00.000000000 -0800
- Orig file:
linux-2.4.21/arch/ia64/sn/io/pciba.c
- Orig date:
2003-06-13 07:51:30.000000000 -0700
diff -urN linux-2.4.21/arch/ia64/sn/io/pciba.c linux-2.4.22/arch/ia64/sn/io/pciba.c
@@ -1,916 +0,0 @@
-/*
- * arch/ia64/sn/io/pciba.c
- *
- * IRIX PCIBA-inspired user mode PCI interface
- *
- * requires: devfs
- *
- * device nodes show up in /dev/pci/BB/SS.F (where BB is the bus the
- * device is on, SS is the slot the device is in, and F is the
- * device's function on a multi-function card).
- *
- * when compiled into the kernel, it will only be initialized by the
- * sgi sn1 specific initialization code. in this case, device nodes
- * are under /dev/hw/..../
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved.
- *
- * 03262001 - Initial version by Chad Talbott
- */
-
-
-/* jesse's beefs:
-
- register_pci_device should be documented
-
- grossness with do_swap should be documented
-
- big, gross union'ized node_data should be replaced with independent
- structures
-
- replace global list of nodes with global lists of resources. could
- use object oriented approach of allocating and cleaning up
- resources.
-
-*/
-
-
-#include <linux/config.h>
-#ifndef CONFIG_DEVFS_FS
-# error PCIBA requires devfs
-#endif
-
-#include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/pci.h>
-#include <linux/list.h>
-
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mman.h>
-#include <linux/init.h>
-#include <linux/raw.h>
-#include <linux/capability.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/pgalloc.h>
-#include <asm/page.h>
-
-#include <asm/sn/pci/pciba.h>
-
-
-MODULE_DESCRIPTION("User mode PCI interface");
-MODULE_AUTHOR("Chad Talbott");
-
-
-#undef DEBUG_PCIBA
-/* #define DEBUG_PCIBA */
-
-#undef TRACE_PCIBA
-/* #define TRACE_PCIBA */
-
-#if defined(DEBUG_PCIBA)
-# define DPRINTF(x...) printk(KERN_DEBUG x)
-#else
-# define DPRINTF(x...)
-#endif
-
-#if defined(TRACE_PCIBA)
-# if defined(__GNUC__)
-# define TRACE() printk(KERN_DEBUG "%s:%d:%s\n", \
- __FILE__, __LINE__, __FUNCTION__)
-# else
-# define TRACE() printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__)
-# endif
-#else
-# define TRACE()
-#endif
-
-
-typedef enum { failure, success } status;
-typedef enum { false, true } boolean;
-
-
-/* major data structures:
-
- struct node_data -
-
- one for each file registered with devfs. contains everything
- that any file's fops would need to know about.
-
- struct dma_allocation -
-
- a single DMA allocation. only the 'dma' nodes care about
- these. they are there primarily to allow the driver to look
- up the kernel virtual address of dma buffers allocated by
- pci_alloc_consistent, as the application is only given the
- physical address (to program the device's dma, presumably) and
- cannot supply the kernel virtual address when freeing the
- buffer.
-
- it's also useful to maintain a list of buffers allocated
- through a specific node to allow some sanity checking by this
- driver. this prevents (for example) a broken application from
- freeing buffers that it didn't allocate, or buffers allocated
- on another node.
-
- global_node_list -
-
- a list of all nodes allocated. this allows the driver to free
- all the memory it has 'kmalloc'd in case of an error, or on
- module removal.
-
- global_dma_list -
-
- a list of all dma buffers allocated by this driver. this
- allows the driver to 'pci_free_consistent' all buffers on
- module removal or error.
-
-*/
-
-
-struct node_data {
- /* flat list of all the device nodes. makes it easy to free
- them all when we're unregistered */
- struct list_head global_node_list;
- devfs_handle_t devfs_handle;
-
- void (* cleanup)(struct node_data *);
-
- union {
- struct {
- struct pci_dev * dev;
- struct list_head dma_allocs;
- boolean mmapped;
- } dma;
- struct {
- struct pci_dev * dev;
- u32 saved_rom_base_reg;
- boolean mmapped;
- } rom;
- struct {
- struct resource * res;
- } base;
- struct {
- struct pci_dev * dev;
- } config;
- } u;
-};
-
-struct dma_allocation {
- struct list_head list;
-
- dma_addr_t handle;
- void * va;
- size_t size;
-};
-
-
-static LIST_HEAD(global_node_list);
-static LIST_HEAD(global_dma_list);
-
-
-/* module entry points */
-int __init pciba_init(void);
-void __exit pciba_exit(void);
-
-static status __init register_with_devfs(void);
-static void __exit unregister_with_devfs(void);
-
-static status __init register_pci_device(devfs_handle_t device_dir_handle,
- struct pci_dev * dev);
-
-/* file operations */
-static int generic_open(struct inode * inode, struct file * file);
-static int rom_mmap(struct file * file, struct vm_area_struct * vma);
-static int rom_release(struct inode * inode, struct file * file);
-static int base_mmap(struct file * file, struct vm_area_struct * vma);
-static int config_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd,
- unsigned long arg);
-static int dma_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd,
- unsigned long arg);
-static int dma_mmap(struct file * file, struct vm_area_struct * vma);
-
-/* support routines */
-static int mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va);
-static int mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va);
-
-#ifdef DEBUG_PCIBA
-static void dump_nodes(struct list_head * nodes);
-static void dump_allocations(struct list_head * dalp);
-#endif
-
-/* file operations for each type of node */
-static struct file_operations rom_fops = {
- owner: THIS_MODULE,
- mmap: rom_mmap,
- open: generic_open,
- release: rom_release
-};
-
-
-static struct file_operations base_fops = {
- owner: THIS_MODULE,
- mmap: base_mmap,
- open: generic_open
-};
-
-
-static struct file_operations config_fops = {
- owner: THIS_MODULE,
- ioctl: config_ioctl,
- open: generic_open
-};
-
-static struct file_operations dma_fops = {
- owner: THIS_MODULE,
- ioctl: dma_ioctl,
- mmap: dma_mmap,
- open: generic_open
-};
-
-
-module_init(pciba_init);
-module_exit(pciba_exit);
-
-
-int __init
-pciba_init(void)
-{
- TRACE();
-
- if (register_with_devfs() == failure)
- return 1; /* failure */
-
- printk("PCIBA (a user mode PCI interface) initialized.\n");
-
- return 0; /* success */
-}
-
-
-void __exit
-pciba_exit(void)
-{
- TRACE();
-
- /* FIXME: should also free all that memory that we allocated
- ;) */
- unregister_with_devfs();
-}
-
-
-# if 0
-static void __exit
-free_nodes(void)
-{
- struct node_data * nd;
-
- TRACE();
-
- list_for_each(nd, &node_list) {
- kfree(list_entry(nd, struct nd, node_list));
- }
-}
-#endif
-
-
-static devfs_handle_t pciba_devfs_handle;
-
-
-extern devfs_handle_t
-devfn_to_vertex(unsigned char busnum, unsigned int devfn);
-
-static status __init
-register_with_devfs(void)
-{
- struct pci_dev * dev;
- devfs_handle_t device_dir_handle;
-
- TRACE();
-
- /* FIXME: don't forget /dev/.../pci/mem & /dev/.../pci/io */
-
- pci_for_each_dev(dev) {
- device_dir_handle = devfn_to_vertex(dev->bus->number,
- dev->devfn);
- if (device_dir_handle == NULL)
- return failure;
-
- if (register_pci_device(device_dir_handle, dev) == failure) {
- devfs_unregister(pciba_devfs_handle);
- return failure;
- }
- }
-
- return success;
-}
-
-static void __exit
-unregister_with_devfs(void)
-{
- struct list_head * lhp;
- struct node_data * nd;
-
- TRACE();
-
- list_for_each(lhp, &global_node_list) {
- nd = list_entry(lhp, struct node_data, global_node_list);
- devfs_unregister(nd->devfs_handle);
- }
-
-}
-
-
-struct node_data * new_node(void)
-{
- struct node_data * node;
-
- TRACE();
-
- node = kmalloc(sizeof(struct node_data), GFP_KERNEL);
- if (node == NULL)
- return NULL;
- list_add(&node->global_node_list, &global_node_list);
- return node;
-}
-
-
-void dma_cleanup(struct node_data * dma_node)
-{
- TRACE();
-
- /* FIXME: should free these allocations */
-#ifdef DEBUG_PCIBA
- dump_allocations(&dma_node->u.dma.dma_allocs);
-#endif
- devfs_unregister(dma_node->devfs_handle);
-}
-
-
-void init_dma_node(struct node_data * node,
- struct pci_dev * dev, devfs_handle_t dh)
-{
- TRACE();
-
- node->devfs_handle = dh;
- node->u.dma.dev = dev;
- node->cleanup = dma_cleanup;
- INIT_LIST_HEAD(&node->u.dma.dma_allocs);
-}
-
-
-void rom_cleanup(struct node_data * rom_node)
-{
- TRACE();
-
- if (rom_node->u.rom.mmapped)
- pci_write_config_dword(rom_node->u.rom.dev,
- PCI_ROM_ADDRESS,
- rom_node->u.rom.saved_rom_base_reg);
- devfs_unregister(rom_node->devfs_handle);
-}
-
-
-void init_rom_node(struct node_data * node,
- struct pci_dev * dev, devfs_handle_t dh)
-{
- TRACE();
-
- node->devfs_handle = dh;
- node->u.rom.dev = dev;
- node->cleanup = rom_cleanup;
- node->u.rom.mmapped = false;
-}
-
-
-static status __init
-register_pci_device(devfs_handle_t device_dir_handle, struct pci_dev * dev)
-{
- struct node_data * nd;
- char devfs_path[20];
- devfs_handle_t node_devfs_handle;
- int ri;
-
- TRACE();
-
-
- /* register nodes for all the device's base address registers */
- for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {
- if (pci_resource_len(dev, ri) != 0) {
- sprintf(devfs_path, "base/%d", ri);
- if (devfs_register(device_dir_handle, devfs_path,
- DEVFS_FL_NONE,
- 0, 0,
- S_IFREG | S_IRUSR | S_IWUSR,
- &base_fops,
- &dev->resource[ri]) == NULL)
- return failure;
- }
- }
-
- /* register a node corresponding to the first MEM resource on
- the device */
- for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {
- if (dev->resource[ri].flags & IORESOURCE_MEM &&
- pci_resource_len(dev, ri) != 0) {
- if (devfs_register(device_dir_handle, "mem",
- DEVFS_FL_NONE, 0, 0,
- S_IFREG | S_IRUSR | S_IWUSR,
- &base_fops,
- &dev->resource[ri]) == NULL)
- return failure;
- break;
- }
- }
-
- /* also register a node corresponding to the first IO resource
- on the device */
- for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {
- if (dev->resource[ri].flags & IORESOURCE_IO &&
- pci_resource_len(dev, ri) != 0) {
- if (devfs_register(device_dir_handle, "io",
- DEVFS_FL_NONE, 0, 0,
- S_IFREG | S_IRUSR | S_IWUSR,
- &base_fops,
- &dev->resource[ri]) == NULL)
- return failure;
- break;
- }
- }
-
- /* register a node corresponding to the device's ROM resource,
- if present */
- if (pci_resource_len(dev, PCI_ROM_RESOURCE) != 0) {
- nd = new_node();
- if (nd == NULL)
- return failure;
- node_devfs_handle = devfs_register(device_dir_handle, "rom",
- DEVFS_FL_NONE, 0, 0,
- S_IFREG | S_IRUSR,
- &rom_fops, nd);
- if (node_devfs_handle == NULL)
- return failure;
- init_rom_node(nd, dev, node_devfs_handle);
- }
-
- /* register a node that allows ioctl's to read and write to
- the device's config space */
- if (devfs_register(device_dir_handle, "config", DEVFS_FL_NONE,
- 0, 0, S_IFREG | S_IRUSR | S_IWUSR,
- &config_fops, dev) == NULL)
- return failure;
-
-
- /* finally, register a node that allows ioctl's to allocate
- and free DMA buffers, as well as memory map those
- buffers. */
- nd = new_node();
- if (nd == NULL)
- return failure;
- node_devfs_handle =
- devfs_register(device_dir_handle, "dma", DEVFS_FL_NONE,
- 0, 0, S_IFREG | S_IRUSR | S_IWUSR,
- &dma_fops, nd);
- if (node_devfs_handle == NULL)
- return failure;
- init_dma_node(nd, dev, node_devfs_handle);
-
-#ifdef DEBUG_PCIBA
- dump_nodes(&global_node_list);
-#endif
-
- return success;
-}
-
-
-static int
-generic_open(struct inode * inode, struct file * file)
-{
- TRACE();
-
- /* FIXME: should check that they're not trying to open the ROM
- writable */
-
- return 0; /* success */
-}
-
-
-static int
-rom_mmap(struct file * file, struct vm_area_struct * vma)
-{
- unsigned long pci_pa;
- struct node_data * nd;
-
- TRACE();
-
- nd = (struct node_data * )file->private_data;
-
- pci_pa = pci_resource_start(nd->u.rom.dev, PCI_ROM_RESOURCE);
-
- if (!nd->u.rom.mmapped) {
- nd->u.rom.mmapped = true;
- DPRINTF("Enabling ROM address decoder.\n");
- DPRINTF(
-"rom_mmap: FIXME: some cards do not allow both ROM and memory addresses to\n"
-"rom_mmap: FIXME: be enabled simultaneously, as they share a decoder.\n");
- pci_read_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS,
- &nd->u.rom.saved_rom_base_reg);
- DPRINTF("ROM base address contains %x\n",
- nd->u.rom.saved_rom_base_reg);
- pci_write_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS,
- nd->u.rom.saved_rom_base_reg |
- PCI_ROM_ADDRESS_ENABLE);
- }
-
- return mmap_pci_address(vma, pci_pa);
-}
-
-
-static int
-rom_release(struct inode * inode, struct file * file)
-{
- struct node_data * nd;
-
- TRACE();
-
- nd = (struct node_data * )file->private_data;
-
- if (nd->u.rom.mmapped) {
- nd->u.rom.mmapped = false;
- DPRINTF("Disabling ROM address decoder.\n");
- pci_write_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS,
- nd->u.rom.saved_rom_base_reg);
- }
- return 0; /* indicate success */
-}
-
-
-static int
-base_mmap(struct file * file, struct vm_area_struct * vma)
-{
- struct resource * resource;
-
- TRACE();
-
- resource = (struct resource *)file->private_data;
-
- return mmap_pci_address(vma, resource->start);
-}
-
-
-static int
-config_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd,
- unsigned long arg)
-{
- struct pci_dev * dev;
-
- union cfg_data {
- uint8_t byte;
- uint16_t word;
- uint32_t dword;
- } read_data, write_data;
-
- int dir, size, offset;
-
- TRACE();
-
- DPRINTF("cmd = %x (DIR = %x, TYPE = %x, NR = %x, SIZE = %x)\n",
- cmd,
- _IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
- DPRINTF("arg = %lx\n", arg);
-
- dev = (struct pci_dev *)file->private_data;
-
- /* PCIIOCCFG{RD,WR}: read and/or write PCI configuration
- space. If both, the read happens first (this becomes a swap
- operation, atomic with respect to other updates through
- this path). */
-
- dir = _IOC_DIR(cmd);
-
-#define do_swap(suffix, type) \
- do { \
- if (dir & _IOC_READ) { \
- pci_read_config_##suffix(dev, _IOC_NR(cmd), \
- &read_data.suffix); \
- } \
- if (dir & _IOC_WRITE) { \
- get_user(write_data.suffix, (type)arg); \
- pci_write_config_##suffix(dev, _IOC_NR(cmd), \
- write_data.suffix); \
- } \
- if (dir & _IOC_READ) { \
- put_user(read_data.suffix, (type)arg); \
- } \
- } while (0)
-
- size = _IOC_SIZE(cmd);
- offset = _IOC_NR(cmd);
-
- DPRINTF("sanity check\n");
- if (((size > 0) || (size <= 4)) &&
- ((offset + size) <= 256) &&
- (dir & (_IOC_READ | _IOC_WRITE))) {
-
- switch (size)
- {
- case 1:
- do_swap(byte, uint8_t *);
- break;
- case 2:
- do_swap(word, uint16_t *);
- break;
- case 4:
- do_swap(dword, uint32_t *);
- break;
- default:
- DPRINTF("invalid ioctl\n");
- return -EINVAL;
- }
- } else
- return -EINVAL;
-
- return 0;
-}
-
-
-#ifdef DEBUG_PCIBA
-static void
-dump_allocations(struct list_head * dalp)
-{
- struct dma_allocation * dap;
- struct list_head * p;
-
- printk("{\n");
- list_for_each(p, dalp) {
- dap = list_entry(p, struct dma_allocation,
- list);
- printk(" handle = %lx, va = %p\n",
- dap->handle, dap->va);
- }
- printk("}\n");
-}
-
-static void
-dump_nodes(struct list_head * nodes)
-{
- struct node_data * ndp;
- struct list_head * p;
-
- printk("{\n");
- list_for_each(p, nodes) {
- ndp = list_entry(p, struct node_data,
- global_node_list);
- printk(" %p\n", (void *)ndp);
- }
- printk("}\n");
-}
-
-
-#if 0
-#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
-
-static void
-test_list(void)
-{
- u64 i;
- LIST_HEAD(the_list);
-
- for (i = 0; i < 5; i++) {
- struct dma_allocation * new_alloc;
- NEW(new_alloc);
- new_alloc->va = (void *)i;
- new_alloc->handle = 5*i;
- printk("%d - the_list->next = %lx\n", i, the_list.next);
- list_add(&new_alloc->list, &the_list);
- }
- dump_allocations(&the_list);
-}
-#endif
-#endif
-
-
-static LIST_HEAD(dma_buffer_list);
-
-
-static int
-dma_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd,
- unsigned long arg)
-{
- struct node_data * nd;
- uint64_t argv;
- int result;
- struct dma_allocation * dma_alloc;
- struct list_head * iterp;
-
- TRACE();
-
- DPRINTF("cmd = %x\n", cmd);
- DPRINTF("arg = %lx\n", arg);
-
- nd = (struct node_data *)file->private_data;
-
-#ifdef DEBUG_PCIBA
- DPRINTF("at dma_ioctl entry\n");
- dump_allocations(&nd->u.dma.dma_allocs);
-#endif
-
- switch (cmd) {
- case PCIIOCDMAALLOC:
- /* PCIIOCDMAALLOC: allocate a chunk of physical memory
- and set it up for DMA. Return the PCI address that
- gets to it. */
- DPRINTF("case PCIIOCDMAALLOC (%lx)\n", PCIIOCDMAALLOC);
-
- if ( (result = get_user(argv, (uint64_t *)arg)) )
- return result;
- DPRINTF("argv (size of buffer) = %lx\n", argv);
-
- dma_alloc = (struct dma_allocation *)
- kmalloc(sizeof(struct dma_allocation), GFP_KERNEL);
- if (dma_alloc == NULL)
- return -ENOMEM;
-
- dma_alloc->size = (size_t)argv;
- dma_alloc->va = pci_alloc_consistent(nd->u.dma.dev,
- dma_alloc->size,
- &dma_alloc->handle);
- DPRINTF("dma_alloc->va = %p, dma_alloc->handle = %lx\n",
- dma_alloc->va, dma_alloc->handle);
- if (dma_alloc->va == NULL) {
- kfree(dma_alloc);
- return -ENOMEM;
- }
-
- list_add(&dma_alloc->list, &nd->u.dma.dma_allocs);
- if ( (result = put_user((uint64_t)dma_alloc->handle,
- (uint64_t *)arg)) ) {
- DPRINTF("put_user failed\n");
- pci_free_consistent(nd->u.dma.dev, (size_t)argv,
- dma_alloc->va, dma_alloc->handle);
- kfree(dma_alloc);
- return result;
- }
-
-#ifdef DEBUG_PCIBA
- DPRINTF("after insertion\n");
- dump_allocations(&nd->u.dma.dma_allocs);
-#endif
- break;
-
- case PCIIOCDMAFREE:
- DPRINTF("case PCIIOCDMAFREE (%lx)\n", PCIIOCDMAFREE);
-
- if ( (result = get_user(argv, (uint64_t *)arg)) ) {
- DPRINTF("get_user failed\n");
- return result;
- }
-
- DPRINTF("argv (physical address of DMA buffer) = %lx\n", argv);
- list_for_each(iterp, &nd->u.dma.dma_allocs) {
- struct dma_allocation * da =
- list_entry(iterp, struct dma_allocation, list);
- if (da->handle == argv) {
- pci_free_consistent(nd->u.dma.dev, da->size,
- da->va, da->handle);
- list_del(&da->list);
- kfree(da);
-#ifdef DEBUG_PCIBA
- DPRINTF("after deletion\n");
- dump_allocations(&nd->u.dma.dma_allocs);
-#endif
- return 0; /* success */
- }
- }
- /* previously allocated dma buffer wasn't found */
- DPRINTF("attempt to free invalid dma handle\n");
- return -EINVAL;
-
- default:
- DPRINTF("undefined ioctl\n");
- return -EINVAL;
- }
-
- DPRINTF("success\n");
- return 0;
-}
-
-
-static int
-dma_mmap(struct file * file, struct vm_area_struct * vma)
-{
- struct node_data * nd;
- struct list_head * iterp;
- int result;
-
- TRACE();
-
- nd = (struct node_data *)file->private_data;
-
- DPRINTF("vma->vm_start is %lx\n", vma->vm_start);
- DPRINTF("vma->vm_end is %lx\n", vma->vm_end);
- DPRINTF("offset = %lx\n", vma->vm_pgoff);
-
- /* get kernel virtual address for the dma buffer (necessary
- * for the mmap). */
- list_for_each(iterp, &nd->u.dma.dma_allocs) {
- struct dma_allocation * da =
- list_entry(iterp, struct dma_allocation, list);
- /* why does mmap shift its offset argument? */
- if (da->handle == vma->vm_pgoff << PAGE_SHIFT) {
- DPRINTF("found dma handle\n");
- if ( (result = mmap_kernel_address(vma,
- da->va)) ) {
- return result; /* failure */
- } else {
- /* it seems like at least one of these
- should show up in user land....
- I'm missing something */
- *(char *)da->va = 0xaa;
- strncpy(da->va, " Toastie!", da->size);
- if (put_user(0x18badbeeful,
- (u64 *)vma->vm_start))
- DPRINTF("put_user failed?!\n");
- return 0; /* success */
- }
-
- }
- }
- DPRINTF("attempt to mmap an invalid dma handle\n");
- return -EINVAL;
-}
-
-
-static int
-mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va)
-{
- unsigned long pci_pa;
-
- TRACE();
-
- DPRINTF("vma->vm_start is %lx\n", vma->vm_start);
- DPRINTF("vma->vm_end is %lx\n", vma->vm_end);
-
- /* the size of the vma doesn't necessarily correspond to the
- size specified in the mmap call. So we can't really do any
- kind of sanity check here. This is a dangerous driver, and
- it's very easy for a user process to kill the machine. */
-
- DPRINTF("PCI base at virtual address %lx\n", pci_va);
- /* the __pa macro is intended for region 7 on IA64, so it
- doesn't work for region 6 */
- /* pci_pa = __pa(pci_va); */
- /* should be replaced by __tpa or equivalent (preferably a
- generic equivalent) */
- pci_pa = pci_va & ~0xe000000000000000ul;
- DPRINTF("PCI base at physical address %lx\n", pci_pa);
-
- /* there are various arch-specific versions of this function
- defined in linux/drivers/char/mem.c, but it would be nice
- if all architectures put it in pgtable.h. it's defined
- there for ia64.... */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO;
-
- return io_remap_page_range(vma->vm_start, pci_pa,
- vma->vm_end-vma->vm_start,
- vma->vm_page_prot);
-}
-
-
-static int
-mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va)
-{
- unsigned long kernel_pa;
-
- TRACE();
-
- DPRINTF("vma->vm_start is %lx\n", vma->vm_start);
- DPRINTF("vma->vm_end is %lx\n", vma->vm_end);
-
- /* the size of the vma doesn't necessarily correspond to the
- size specified in the mmap call. So we can't really do any
- kind of sanity check here. This is a dangerous driver, and
- it's very easy for a user process to kill the machine. */
-
- DPRINTF("mapping virtual address %p\n", kernel_va);
- kernel_pa = __pa(kernel_va);
- DPRINTF("mapping physical address %lx\n", kernel_pa);
-
- vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO;
-
- return remap_page_range(vma->vm_start, kernel_pa,
- vma->vm_end-vma->vm_start,
- vma->vm_page_prot);
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)