pciba.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * arch/ia64/sn/io/pciba.c
  3.  *
  4.  * IRIX PCIBA-inspired user mode PCI interface
  5.  *
  6.  * requires: devfs
  7.  *
  8.  * device nodes show up in /dev/pci/BB/SS.F (where BB is the bus the
  9.  * device is on, SS is the slot the device is in, and F is the
  10.  * device's function on a multi-function card).
  11.  *
  12.  * when compiled into the kernel, it will only be initialized by the
  13.  * sgi sn1 specific initialization code.  in this case, device nodes
  14.  * are under /dev/hw/..../
  15.  *
  16.  * This file is subject to the terms and conditions of the GNU General
  17.  * Public License.  See the file "COPYING" in the main directory of
  18.  * this archive for more details.
  19.  *
  20.  * Copyright (C) 2001-2002 Silicon Graphics, Inc.  All rights reserved.
  21.  *
  22.  * 03262001 - Initial version by Chad Talbott
  23.  */
  24. /* jesse's beefs:
  25.    register_pci_device should be documented
  26.    
  27.    grossness with do_swap should be documented
  28.    
  29.    big, gross union'ized node_data should be replaced with independent
  30.    structures
  31.    replace global list of nodes with global lists of resources.  could
  32.    use object oriented approach of allocating and cleaning up
  33.    resources.
  34.    
  35. */
  36. #include <linux/config.h>
  37. #ifndef CONFIG_DEVFS_FS
  38. #  error PCIBA requires devfs
  39. #endif
  40. #include <linux/module.h>
  41. #include <linux/devfs_fs_kernel.h>
  42. #include <linux/pci.h>
  43. #include <linux/list.h>
  44. #include <linux/mm.h>
  45. #include <linux/slab.h>
  46. #include <linux/vmalloc.h>
  47. #include <linux/mman.h>
  48. #include <linux/init.h>
  49. #include <linux/raw.h>
  50. #include <linux/capability.h>
  51. #include <asm/uaccess.h>
  52. #include <asm/io.h>
  53. #include <asm/pgalloc.h>
  54. #include <asm/page.h>
  55. #include <asm/sn/pci/pciba.h>
  56. MODULE_DESCRIPTION("User mode PCI interface");
  57. MODULE_AUTHOR("Chad Talbott");
  58. #undef DEBUG_PCIBA
  59. /* #define DEBUG_PCIBA */
  60. #undef TRACE_PCIBA
  61. /* #define TRACE_PCIBA */
  62. #if defined(DEBUG_PCIBA)
  63. #  define DPRINTF(x...) printk(KERN_DEBUG x)
  64. #else
  65. #  define DPRINTF(x...)
  66. #endif
  67. #if defined(TRACE_PCIBA)
  68. #  if defined(__GNUC__)
  69. #    define TRACE() printk(KERN_DEBUG "%s:%d:%sn", 
  70.        __FILE__, __LINE__, __FUNCTION__)
  71. #  else
  72. #    define TRACE() printk(KERN_DEBUG "%s:%dn", __LINE__, __FILE__)
  73. #  endif
  74. #else
  75. #  define TRACE()
  76. #endif
  77. typedef enum { failure, success } status;
  78. typedef enum { false, true } boolean;
  79. /* major data structures:
  80.    struct node_data -
  81.    
  82.     one for each file registered with devfs.  contains everything
  83.     that any file's fops would need to know about.
  84.    struct dma_allocation -
  85.     a single DMA allocation.  only the 'dma' nodes care about
  86.     these.  they are there primarily to allow the driver to look
  87.     up the kernel virtual address of dma buffers allocated by
  88.     pci_alloc_consistent, as the application is only given the
  89.     physical address (to program the device's dma, presumably) and
  90.     cannot supply the kernel virtual address when freeing the
  91.     buffer.
  92. it's also useful to maintain a list of buffers allocated
  93. through a specific node to allow some sanity checking by this
  94. driver.  this prevents (for example) a broken application from
  95. freeing buffers that it didn't allocate, or buffers allocated
  96. on another node.
  97.    
  98.    global_node_list -
  99.     a list of all nodes allocated.  this allows the driver to free
  100.     all the memory it has 'kmalloc'd in case of an error, or on
  101.     module removal.
  102.    global_dma_list -
  103.         a list of all dma buffers allocated by this driver.  this
  104. allows the driver to 'pci_free_consistent' all buffers on
  105. module removal or error.
  106. */
  107. struct node_data {
  108. /* flat list of all the device nodes.  makes it easy to free
  109.    them all when we're unregistered */
  110. struct list_head global_node_list;
  111. devfs_handle_t devfs_handle;
  112. void (* cleanup)(struct node_data *);
  113. union {
  114. struct {
  115. struct pci_dev * dev;
  116. struct list_head dma_allocs;
  117. boolean mmapped;
  118. } dma;
  119. struct {
  120. struct pci_dev * dev;
  121. u32 saved_rom_base_reg;
  122. boolean mmapped;
  123. } rom;
  124. struct {
  125. struct resource * res;
  126. } base;
  127. struct {
  128. struct pci_dev * dev;
  129. } config;
  130. } u;
  131. };
  132. struct dma_allocation {
  133. struct list_head list;
  134. dma_addr_t handle;
  135. void * va;
  136. size_t size;
  137. };
  138. static LIST_HEAD(global_node_list);
  139. static LIST_HEAD(global_dma_list);
  140. /* module entry points */
  141. int __init pciba_init(void);
  142. void __exit pciba_exit(void);
  143. static status __init register_with_devfs(void);
  144. static void __exit unregister_with_devfs(void);
  145. static status __init register_pci_device(devfs_handle_t device_dir_handle,
  146.  struct pci_dev * dev);
  147. /* file operations */
  148. static int generic_open(struct inode * inode, struct file * file);
  149. static int rom_mmap(struct file * file, struct vm_area_struct * vma);
  150. static int rom_release(struct inode * inode, struct file * file);
  151. static int base_mmap(struct file * file, struct vm_area_struct * vma);
  152. static int config_ioctl(struct inode * inode, struct file * file, 
  153. unsigned int cmd, 
  154. unsigned long arg);
  155. static int dma_ioctl(struct inode * inode, struct file * file, 
  156.      unsigned int cmd, 
  157.      unsigned long arg);
  158. static int dma_mmap(struct file * file, struct vm_area_struct * vma);
  159. /* support routines */
  160. static int mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va);
  161. static int mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va);
  162. #ifdef DEBUG_PCIBA
  163. static void dump_nodes(struct list_head * nodes);
  164. static void dump_allocations(struct list_head * dalp);
  165. #endif
  166. /* file operations for each type of node */
  167. static struct file_operations rom_fops = {
  168. owner: THIS_MODULE,
  169. mmap: rom_mmap,
  170. open: generic_open,
  171. release: rom_release
  172. };
  173.  
  174. static struct file_operations base_fops = {
  175. owner: THIS_MODULE,
  176. mmap: base_mmap,
  177. open: generic_open
  178. };
  179. static struct file_operations config_fops = {
  180. owner: THIS_MODULE,
  181. ioctl: config_ioctl,
  182. open: generic_open
  183. };
  184. static struct file_operations dma_fops = {
  185. owner: THIS_MODULE,
  186. ioctl: dma_ioctl,
  187. mmap: dma_mmap,
  188. open: generic_open
  189. };
  190. module_init(pciba_init);
  191. module_exit(pciba_exit);
  192. int __init
  193. pciba_init(void)
  194. {
  195. TRACE();
  196. if (register_with_devfs() == failure)
  197. return 1; /* failure */
  198. printk("PCIBA (a user mode PCI interface) initialized.n");
  199. return 0; /* success */
  200. }
  201. void __exit
  202. pciba_exit(void)
  203. {
  204. TRACE();
  205. /* FIXME: should also free all that memory that we allocated
  206.            ;) */
  207. unregister_with_devfs();
  208. }
  209. # if 0
  210. static void __exit
  211. free_nodes(void)
  212. {
  213. struct node_data * nd;
  214. TRACE();
  215. list_for_each(nd, &node_list) {
  216. kfree(list_entry(nd, struct nd, node_list));
  217. }
  218. }
  219. #endif
  220. static devfs_handle_t pciba_devfs_handle;
  221. #if !defined(CONFIG_IA64_SGI_SN1)
  222. static status __init
  223. register_with_devfs(void)
  224. {
  225. struct pci_dev * dev;
  226. devfs_handle_t device_dir_handle;
  227. char devfs_path[40];
  228. TRACE();
  229. pciba_devfs_handle = devfs_mk_dir(NULL, "pci", NULL);
  230. if (pciba_devfs_handle == NULL)
  231. return failure;
  232. /* FIXME: don't forget /dev/pci/mem & /dev/pci/io */
  233. pci_for_each_dev(dev) {
  234. sprintf(devfs_path, "%02x/%02x.%x",
  235. dev->bus->number,
  236. PCI_SLOT(dev->devfn),
  237. PCI_FUNC(dev->devfn));
  238.     
  239. device_dir_handle =
  240. devfs_mk_dir(pciba_devfs_handle, devfs_path, NULL);
  241. if (device_dir_handle == NULL)
  242. return failure;
  243. if (register_pci_device(device_dir_handle, dev) == failure) {
  244. devfs_unregister(pciba_devfs_handle);
  245. return failure;
  246. }
  247. }
  248. return success;
  249. }
  250. #else
  251. extern devfs_handle_t
  252. devfn_to_vertex(unsigned char busnum, unsigned int devfn);
  253. static status __init
  254. register_with_devfs(void)
  255. {
  256. struct pci_dev * dev;
  257. devfs_handle_t device_dir_handle;
  258. TRACE();
  259. /* FIXME: don't forget /dev/.../pci/mem & /dev/.../pci/io */
  260. pci_for_each_dev(dev) {
  261. device_dir_handle = devfn_to_vertex(dev->bus->number,
  262.     dev->devfn);
  263. if (device_dir_handle == NULL)
  264. return failure;
  265. if (register_pci_device(device_dir_handle, dev) == failure) {
  266. devfs_unregister(pciba_devfs_handle);
  267. return failure;
  268. }
  269. }
  270. return success;
  271. }
  272. #endif /* CONFIG_IA64_SGI_SN1 */
  273. static void __exit
  274. unregister_with_devfs(void)
  275. {
  276. struct list_head * lhp;
  277. struct node_data * nd;
  278. TRACE();
  279. list_for_each(lhp, &global_node_list) {
  280. nd = list_entry(lhp, struct node_data, global_node_list);
  281. devfs_unregister(nd->devfs_handle);
  282. }
  283. }
  284. struct node_data * new_node(void)
  285. {
  286. struct node_data * node;
  287. TRACE();
  288. node = kmalloc(sizeof(struct node_data), GFP_KERNEL);
  289. if (node == NULL)
  290. return NULL;
  291. list_add(&node->global_node_list, &global_node_list);
  292. return node;
  293. }
  294. void dma_cleanup(struct node_data * dma_node)
  295. {
  296. TRACE();
  297. /* FIXME: should free these allocations */
  298. #ifdef DEBUG_PCIBA
  299. dump_allocations(&dma_node->u.dma.dma_allocs);
  300. #endif
  301. devfs_unregister(dma_node->devfs_handle);
  302. }
  303. void init_dma_node(struct node_data * node,
  304.    struct pci_dev * dev, devfs_handle_t dh)
  305. {
  306. TRACE();
  307. node->devfs_handle = dh;
  308. node->u.dma.dev = dev;
  309. node->cleanup = dma_cleanup;
  310. INIT_LIST_HEAD(&node->u.dma.dma_allocs);
  311. }
  312. void rom_cleanup(struct node_data * rom_node)
  313. {
  314. TRACE();
  315. if (rom_node->u.rom.mmapped)
  316. pci_write_config_dword(rom_node->u.rom.dev,
  317.        PCI_ROM_ADDRESS,
  318.        rom_node->u.rom.saved_rom_base_reg);
  319. devfs_unregister(rom_node->devfs_handle);
  320. }
  321. void init_rom_node(struct node_data * node,
  322.    struct pci_dev * dev, devfs_handle_t dh)
  323. {
  324. TRACE();
  325. node->devfs_handle = dh;
  326. node->u.rom.dev = dev;
  327. node->cleanup = rom_cleanup;
  328. node->u.rom.mmapped = false;
  329. }
  330. static status __init
  331. register_pci_device(devfs_handle_t device_dir_handle, struct pci_dev * dev)
  332. {
  333. struct node_data * nd;
  334. char devfs_path[20];
  335. devfs_handle_t node_devfs_handle;
  336. int ri;
  337. TRACE();
  338. /* register nodes for all the device's base address registers */
  339. for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {
  340. if (pci_resource_len(dev, ri) != 0) {
  341. sprintf(devfs_path, "base/%d", ri);
  342. if (devfs_register(device_dir_handle, devfs_path,
  343.    DEVFS_FL_NONE,
  344.    0, 0,
  345.    S_IFREG | S_IRUSR | S_IWUSR,
  346.    &base_fops, 
  347.    &dev->resource[ri]) == NULL)
  348. return failure;
  349. }
  350. }
  351. /* register a node corresponding to the first MEM resource on
  352.            the device */
  353. for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {
  354. if (dev->resource[ri].flags & IORESOURCE_MEM &&
  355.     pci_resource_len(dev, ri) != 0) {
  356. if (devfs_register(device_dir_handle, "mem",
  357.    DEVFS_FL_NONE, 0, 0,
  358.    S_IFREG | S_IRUSR | S_IWUSR,
  359.    &base_fops, 
  360.    &dev->resource[ri]) == NULL)
  361. return failure;
  362. break;
  363. }
  364. }
  365. /* also register a node corresponding to the first IO resource
  366.            on the device */
  367. for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {
  368. if (dev->resource[ri].flags & IORESOURCE_IO &&
  369.     pci_resource_len(dev, ri) != 0) {
  370. if (devfs_register(device_dir_handle, "io",
  371.    DEVFS_FL_NONE, 0, 0,
  372.    S_IFREG | S_IRUSR | S_IWUSR,
  373.    &base_fops, 
  374.    &dev->resource[ri]) == NULL)
  375. return failure;
  376. break;
  377. }
  378. }
  379. /* register a node corresponding to the device's ROM resource,
  380.            if present */
  381. if (pci_resource_len(dev, PCI_ROM_RESOURCE) != 0) {
  382. nd = new_node();
  383. if (nd == NULL)
  384. return failure;
  385. node_devfs_handle = devfs_register(device_dir_handle, "rom",
  386.    DEVFS_FL_NONE, 0, 0,
  387.    S_IFREG | S_IRUSR,
  388.    &rom_fops, nd);
  389. if (node_devfs_handle == NULL)
  390. return failure;
  391. init_rom_node(nd, dev, node_devfs_handle);
  392. }
  393. /* register a node that allows ioctl's to read and write to
  394.            the device's config space */
  395. if (devfs_register(device_dir_handle, "config", DEVFS_FL_NONE,
  396.    0, 0, S_IFREG | S_IRUSR | S_IWUSR,
  397.    &config_fops, dev) == NULL)
  398. return failure;
  399. /* finally, register a node that allows ioctl's to allocate
  400.            and free DMA buffers, as well as memory map those
  401.            buffers. */
  402. nd = new_node();
  403. if (nd == NULL)
  404. return failure;
  405. node_devfs_handle =
  406. devfs_register(device_dir_handle, "dma", DEVFS_FL_NONE,
  407.        0, 0, S_IFREG | S_IRUSR | S_IWUSR,
  408.        &dma_fops, nd);
  409. if (node_devfs_handle == NULL)
  410. return failure;
  411. init_dma_node(nd, dev, node_devfs_handle);
  412. #ifdef DEBUG_PCIBA
  413. dump_nodes(&global_node_list);
  414. #endif
  415. return success;
  416. }
  417. static int
  418. generic_open(struct inode * inode, struct file * file)
  419. {
  420. TRACE();
  421. /* FIXME: should check that they're not trying to open the ROM
  422.            writable */
  423. return 0; /* success */
  424. }
  425. static int
  426. rom_mmap(struct file * file, struct vm_area_struct * vma)
  427. {
  428. unsigned long pci_pa;
  429. struct node_data * nd;
  430. TRACE();
  431. nd = (struct node_data * )file->private_data;
  432. pci_pa = pci_resource_start(nd->u.rom.dev, PCI_ROM_RESOURCE);
  433. if (!nd->u.rom.mmapped) {
  434. nd->u.rom.mmapped = true;
  435. DPRINTF("Enabling ROM address decoder.n");
  436. DPRINTF(
  437. "rom_mmap: FIXME: some cards do not allow both ROM and memory addresses ton"
  438. "rom_mmap: FIXME: be enabled simultaneously, as they share a decoder.n");
  439. pci_read_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS,
  440.       &nd->u.rom.saved_rom_base_reg);
  441. DPRINTF("ROM base address contains %xn",
  442. nd->u.rom.saved_rom_base_reg);
  443. pci_write_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS,
  444.        nd->u.rom.saved_rom_base_reg |
  445.        PCI_ROM_ADDRESS_ENABLE);
  446. }
  447. return mmap_pci_address(vma, pci_pa);
  448. }
  449. static int
  450. rom_release(struct inode * inode, struct file * file)
  451. {
  452. struct node_data * nd;
  453. TRACE();
  454. nd = (struct node_data * )file->private_data;
  455. if (nd->u.rom.mmapped) {
  456. nd->u.rom.mmapped = false;
  457. DPRINTF("Disabling ROM address decoder.n");
  458. pci_write_config_dword(nd->u.rom.dev, PCI_ROM_ADDRESS,
  459.        nd->u.rom.saved_rom_base_reg);
  460. }
  461. return 0; /* indicate success */
  462. }
  463. static int
  464. base_mmap(struct file * file, struct vm_area_struct * vma)
  465. {
  466. struct resource * resource;
  467. TRACE();
  468. resource = (struct resource *)file->private_data;
  469. return mmap_pci_address(vma, resource->start);
  470. }
  471. static int
  472. config_ioctl(struct inode * inode, struct file * file, 
  473.      unsigned int cmd, 
  474.      unsigned long arg)
  475. {
  476. struct pci_dev * dev;
  477. union cfg_data {
  478. uint8_t byte;
  479. uint16_t word;
  480. uint32_t dword;
  481. } read_data, write_data;
  482. int dir, size, offset;
  483. TRACE();
  484. DPRINTF("cmd = %x (DIR = %x, TYPE = %x, NR = %x, SIZE = %x)n", 
  485. cmd, 
  486. _IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
  487. DPRINTF("arg = %lxn", arg);
  488. dev = (struct pci_dev *)file->private_data;
  489. /* PCIIOCCFG{RD,WR}: read and/or write PCI configuration
  490.    space. If both, the read happens first (this becomes a swap
  491.    operation, atomic with respect to other updates through
  492.    this path).  */
  493. dir = _IOC_DIR(cmd);
  494. #define do_swap(suffix, type)  
  495. do {
  496. if (dir & _IOC_READ) {
  497. pci_read_config_##suffix(dev, _IOC_NR(cmd), 
  498.  &read_data.suffix);
  499. }
  500. if (dir & _IOC_WRITE) {
  501. get_user(write_data.suffix, (type)arg);
  502. pci_write_config_##suffix(dev, _IOC_NR(cmd), 
  503.   write_data.suffix);
  504. }
  505. if (dir & _IOC_READ) {
  506. put_user(read_data.suffix, (type)arg);
  507. }
  508. } while (0)
  509. size = _IOC_SIZE(cmd);
  510. offset = _IOC_NR(cmd);
  511. DPRINTF("sanity checkn");
  512. if (((size > 0) || (size <= 4)) &&
  513.     ((offset + size) <= 256) &&
  514.     (dir & (_IOC_READ | _IOC_WRITE))) {
  515. switch (size)
  516. {
  517. case 1:
  518. do_swap(byte, uint8_t *);
  519. break;
  520. case 2:
  521. do_swap(word, uint16_t *);
  522. break;
  523. case 4:
  524. do_swap(dword, uint32_t *);
  525. break;
  526. default:
  527. DPRINTF("invalid ioctln");
  528. return -EINVAL;
  529. }
  530. } else
  531. return -EINVAL;
  532. return 0;
  533. }
  534. #ifdef DEBUG_PCIBA
  535. static void
  536. dump_allocations(struct list_head * dalp)
  537. {
  538. struct dma_allocation * dap;
  539. struct list_head * p;
  540. printk("{n");
  541. list_for_each(p, dalp) {
  542. dap = list_entry(p, struct dma_allocation, 
  543.  list);
  544. printk("  handle = %lx, va = %pn",
  545.        dap->handle, dap->va);
  546. }
  547. printk("}n");
  548. }
  549. static void
  550. dump_nodes(struct list_head * nodes)
  551. {
  552. struct node_data * ndp;
  553. struct list_head * p;
  554. printk("{n");
  555. list_for_each(p, nodes) {
  556. ndp = list_entry(p, struct node_data, 
  557.  global_node_list);
  558. printk("  %pn", (void *)ndp);
  559. }
  560. printk("}n");
  561. }
  562. #if 0
  563. #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
  564. static void
  565. test_list(void)
  566. {
  567. u64 i;
  568. LIST_HEAD(the_list);
  569. for (i = 0; i < 5; i++) {
  570. struct dma_allocation * new_alloc;
  571. NEW(new_alloc);
  572. new_alloc->va = (void *)i;
  573. new_alloc->handle = 5*i;
  574. printk("%d - the_list->next = %lxn", i, the_list.next);
  575. list_add(&new_alloc->list, &the_list);
  576. }
  577. dump_allocations(&the_list);
  578. }
  579. #endif
  580. #endif
  581. static LIST_HEAD(dma_buffer_list);
  582. static int
  583. dma_ioctl(struct inode * inode, struct file * file, 
  584.   unsigned int cmd, 
  585.   unsigned long arg)
  586. {
  587. struct node_data * nd;
  588. uint64_t argv;
  589. int result;
  590. struct dma_allocation * dma_alloc;
  591. struct list_head * iterp;
  592. TRACE();
  593. DPRINTF("cmd = %xn", cmd);
  594. DPRINTF("arg = %lxn", arg);
  595. nd = (struct node_data *)file->private_data;
  596. #ifdef DEBUG_PCIBA
  597. DPRINTF("at dma_ioctl entryn");
  598. dump_allocations(&nd->u.dma.dma_allocs);
  599. #endif
  600. switch (cmd) {
  601. case PCIIOCDMAALLOC:
  602. /* PCIIOCDMAALLOC: allocate a chunk of physical memory
  603.    and set it up for DMA. Return the PCI address that
  604.    gets to it.  */
  605. DPRINTF("case PCIIOCDMAALLOC (%lx)n", PCIIOCDMAALLOC);
  606. if ( (result = get_user(argv, (uint64_t *)arg)) )
  607. return result;
  608. DPRINTF("argv (size of buffer) = %lxn", argv);
  609. dma_alloc = (struct dma_allocation *)
  610. kmalloc(sizeof(struct dma_allocation), GFP_KERNEL);
  611. if (dma_alloc == NULL)
  612. return -ENOMEM;
  613. dma_alloc->size = (size_t)argv;
  614. dma_alloc->va = pci_alloc_consistent(nd->u.dma.dev,
  615.      dma_alloc->size,
  616.      &dma_alloc->handle);
  617. DPRINTF("dma_alloc->va = %p, dma_alloc->handle = %lxn",
  618. dma_alloc->va, dma_alloc->handle);
  619. if (dma_alloc->va == NULL) {
  620. kfree(dma_alloc);
  621. return -ENOMEM;
  622. }
  623. list_add(&dma_alloc->list, &nd->u.dma.dma_allocs);
  624. if ( (result = put_user((uint64_t)dma_alloc->handle, 
  625.       (uint64_t *)arg)) ) {
  626. DPRINTF("put_user failedn");
  627. pci_free_consistent(nd->u.dma.dev, (size_t)argv,
  628.     dma_alloc->va, dma_alloc->handle);
  629. kfree(dma_alloc);
  630. return result;
  631. }
  632. #ifdef DEBUG_PCIBA
  633. DPRINTF("after insertionn");
  634. dump_allocations(&nd->u.dma.dma_allocs);
  635. #endif
  636. break;
  637. case PCIIOCDMAFREE:
  638. DPRINTF("case PCIIOCDMAFREE (%lx)n", PCIIOCDMAFREE);
  639. if ( (result = get_user(argv, (uint64_t *)arg)) ) {
  640. DPRINTF("get_user failedn");
  641. return result;
  642. }
  643. DPRINTF("argv (physical address of DMA buffer) = %lxn", argv);
  644. list_for_each(iterp, &nd->u.dma.dma_allocs) {
  645. struct dma_allocation * da =
  646. list_entry(iterp, struct dma_allocation, list);
  647. if (da->handle == argv) {
  648. pci_free_consistent(nd->u.dma.dev, da->size,
  649.     da->va, da->handle);
  650. list_del(&da->list);
  651. kfree(da);
  652. #ifdef DEBUG_PCIBA
  653. DPRINTF("after deletionn");
  654. dump_allocations(&nd->u.dma.dma_allocs);
  655. #endif
  656. return 0; /* success */
  657. }
  658. }
  659. /* previously allocated dma buffer wasn't found */
  660. DPRINTF("attempt to free invalid dma handlen");
  661. return -EINVAL;
  662. default:
  663. DPRINTF("undefined ioctln");
  664. return -EINVAL;
  665. }
  666. DPRINTF("successn");
  667. return 0;
  668. }
  669. static int
  670. dma_mmap(struct file * file, struct vm_area_struct * vma)
  671. {
  672. struct node_data * nd;
  673. struct list_head * iterp;
  674. int result;
  675. TRACE();
  676. nd = (struct node_data *)file->private_data;
  677. DPRINTF("vma->vm_start is %lxn", vma->vm_start);
  678. DPRINTF("vma->vm_end is %lxn", vma->vm_end);
  679. DPRINTF("offset = %lxn", vma->vm_pgoff);
  680. /* get kernel virtual address for the dma buffer (necessary
  681.  * for the mmap). */
  682. list_for_each(iterp, &nd->u.dma.dma_allocs) {
  683. struct dma_allocation * da =
  684. list_entry(iterp, struct dma_allocation, list);
  685. /* why does mmap shift its offset argument? */
  686. if (da->handle == vma->vm_pgoff << PAGE_SHIFT) {
  687. DPRINTF("found dma handlen");
  688. if ( (result = mmap_kernel_address(vma,
  689.    da->va)) ) {
  690. return result; /* failure */
  691. } else {
  692. /* it seems like at least one of these
  693.    should show up in user land....
  694.    I'm missing something */
  695. *(char *)da->va = 0xaa;
  696. strncpy(da->va, "        Toastie!", da->size);
  697. if (put_user(0x18badbeeful,
  698.      (u64 *)vma->vm_start))
  699. DPRINTF("put_user failed?!n");
  700. return 0; /* success */
  701. }
  702. }
  703. }
  704. DPRINTF("attempt to mmap an invalid dma handlen");
  705. return -EINVAL;
  706. }
  707. static int
  708. mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va)
  709. {
  710. unsigned long pci_pa;
  711. TRACE();
  712. DPRINTF("vma->vm_start is %lxn", vma->vm_start);
  713. DPRINTF("vma->vm_end is %lxn", vma->vm_end);
  714. /* the size of the vma doesn't necessarily correspond to the
  715.            size specified in the mmap call.  So we can't really do any
  716.            kind of sanity check here.  This is a dangerous driver, and
  717.            it's very easy for a user process to kill the machine.  */
  718. DPRINTF("PCI base at virtual address %lxn", pci_va);
  719. /* the __pa macro is intended for region 7 on IA64, so it
  720.    doesn't work for region 6 */
  721.    /* pci_pa = __pa(pci_va); */
  722. /* should be replaced by __tpa or equivalent (preferably a
  723.    generic equivalent) */
  724. pci_pa = pci_va & ~0xe000000000000000ul;
  725. DPRINTF("PCI base at physical address %lxn", pci_pa);
  726. /* there are various arch-specific versions of this function
  727.            defined in linux/drivers/char/mem.c, but it would be nice
  728.            if all architectures put it in pgtable.h.  it's defined
  729.            there for ia64.... */
  730. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  731. vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO;
  732. return io_remap_page_range(vma->vm_start, pci_pa, 
  733.    vma->vm_end-vma->vm_start,
  734.    vma->vm_page_prot);
  735. }
  736. static int
  737. mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va)
  738. {
  739. unsigned long kernel_pa;
  740. TRACE();
  741. DPRINTF("vma->vm_start is %lxn", vma->vm_start);
  742. DPRINTF("vma->vm_end is %lxn", vma->vm_end);
  743. /* the size of the vma doesn't necessarily correspond to the
  744.            size specified in the mmap call.  So we can't really do any
  745.            kind of sanity check here.  This is a dangerous driver, and
  746.            it's very easy for a user process to kill the machine.  */
  747. DPRINTF("mapping virtual address %pn", kernel_va);
  748. kernel_pa = __pa(kernel_va);
  749. DPRINTF("mapping physical address %lxn", kernel_pa);
  750. vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO;
  751. return remap_page_range(vma->vm_start, kernel_pa, 
  752. vma->vm_end-vma->vm_start,
  753. vma->vm_page_prot);
  754. }