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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: proc.c,v 1.13 1998/05/12 07:36:07 mj Exp $
  3.  *
  4.  * Procfs interface for the PCI bus.
  5.  *
  6.  * Copyright (c) 1997--1999 Martin Mares <mj@ucw.cz>
  7.  */
  8. #include <linux/types.h>
  9. #include <linux/kernel.h>
  10. #include <linux/pci.h>
  11. #include <linux/proc_fs.h>
  12. #include <linux/init.h>
  13. #include <linux/seq_file.h>
  14. #include <asm/uaccess.h>
  15. #include <asm/byteorder.h>
  16. #define PCI_CFG_SPACE_SIZE 256
  17. static loff_t
  18. proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
  19. {
  20. loff_t new;
  21. switch (whence) {
  22. case 0:
  23. new = off;
  24. break;
  25. case 1:
  26. new = file->f_pos + off;
  27. break;
  28. case 2:
  29. new = PCI_CFG_SPACE_SIZE + off;
  30. break;
  31. default:
  32. return -EINVAL;
  33. }
  34. if (new < 0 || new > PCI_CFG_SPACE_SIZE)
  35. return -EINVAL;
  36. return (file->f_pos = new);
  37. }
  38. static ssize_t
  39. proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
  40. {
  41. const struct inode *ino = file->f_dentry->d_inode;
  42. const struct proc_dir_entry *dp = ino->u.generic_ip;
  43. struct pci_dev *dev = dp->data;
  44. unsigned int pos = *ppos;
  45. unsigned int cnt, size;
  46. /*
  47.  * Normal users can read only the standardized portion of the
  48.  * configuration space as several chips lock up when trying to read
  49.  * undefined locations (think of Intel PIIX4 as a typical example).
  50.  */
  51. if (capable(CAP_SYS_ADMIN))
  52. size = PCI_CFG_SPACE_SIZE;
  53. else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
  54. size = 128;
  55. else
  56. size = 64;
  57. if (pos >= size)
  58. return 0;
  59. if (nbytes >= size)
  60. nbytes = size;
  61. if (pos + nbytes > size)
  62. nbytes = size - pos;
  63. cnt = nbytes;
  64. if (!access_ok(VERIFY_WRITE, buf, cnt))
  65. return -EINVAL;
  66. if ((pos & 1) && cnt) {
  67. unsigned char val;
  68. pci_read_config_byte(dev, pos, &val);
  69. __put_user(val, buf);
  70. buf++;
  71. pos++;
  72. cnt--;
  73. }
  74. if ((pos & 3) && cnt > 2) {
  75. unsigned short val;
  76. pci_read_config_word(dev, pos, &val);
  77. __put_user(cpu_to_le16(val), (unsigned short *) buf);
  78. buf += 2;
  79. pos += 2;
  80. cnt -= 2;
  81. }
  82. while (cnt >= 4) {
  83. unsigned int val;
  84. pci_read_config_dword(dev, pos, &val);
  85. __put_user(cpu_to_le32(val), (unsigned int *) buf);
  86. buf += 4;
  87. pos += 4;
  88. cnt -= 4;
  89. }
  90. if (cnt >= 2) {
  91. unsigned short val;
  92. pci_read_config_word(dev, pos, &val);
  93. __put_user(cpu_to_le16(val), (unsigned short *) buf);
  94. buf += 2;
  95. pos += 2;
  96. cnt -= 2;
  97. }
  98. if (cnt) {
  99. unsigned char val;
  100. pci_read_config_byte(dev, pos, &val);
  101. __put_user(val, buf);
  102. buf++;
  103. pos++;
  104. cnt--;
  105. }
  106. *ppos = pos;
  107. return nbytes;
  108. }
  109. static ssize_t
  110. proc_bus_pci_write(struct file *file, const char *buf, size_t nbytes, loff_t *ppos)
  111. {
  112. const struct inode *ino = file->f_dentry->d_inode;
  113. const struct proc_dir_entry *dp = ino->u.generic_ip;
  114. struct pci_dev *dev = dp->data;
  115. int pos = *ppos;
  116. int cnt;
  117. if (pos >= PCI_CFG_SPACE_SIZE)
  118. return 0;
  119. if (nbytes >= PCI_CFG_SPACE_SIZE)
  120. nbytes = PCI_CFG_SPACE_SIZE;
  121. if (pos + nbytes > PCI_CFG_SPACE_SIZE)
  122. nbytes = PCI_CFG_SPACE_SIZE - pos;
  123. cnt = nbytes;
  124. if (!access_ok(VERIFY_READ, buf, cnt))
  125. return -EINVAL;
  126. if ((pos & 1) && cnt) {
  127. unsigned char val;
  128. __get_user(val, buf);
  129. pci_write_config_byte(dev, pos, val);
  130. buf++;
  131. pos++;
  132. cnt--;
  133. }
  134. if ((pos & 3) && cnt > 2) {
  135. unsigned short val;
  136. __get_user(val, (unsigned short *) buf);
  137. pci_write_config_word(dev, pos, le16_to_cpu(val));
  138. buf += 2;
  139. pos += 2;
  140. cnt -= 2;
  141. }
  142. while (cnt >= 4) {
  143. unsigned int val;
  144. __get_user(val, (unsigned int *) buf);
  145. pci_write_config_dword(dev, pos, le32_to_cpu(val));
  146. buf += 4;
  147. pos += 4;
  148. cnt -= 4;
  149. }
  150. if (cnt >= 2) {
  151. unsigned short val;
  152. __get_user(val, (unsigned short *) buf);
  153. pci_write_config_word(dev, pos, le16_to_cpu(val));
  154. buf += 2;
  155. pos += 2;
  156. cnt -= 2;
  157. }
  158. if (cnt) {
  159. unsigned char val;
  160. __get_user(val, buf);
  161. pci_write_config_byte(dev, pos, val);
  162. buf++;
  163. pos++;
  164. cnt--;
  165. }
  166. *ppos = pos;
  167. return nbytes;
  168. }
  169. struct pci_filp_private {
  170. enum pci_mmap_state mmap_state;
  171. int write_combine;
  172. };
  173. static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  174. {
  175. const struct proc_dir_entry *dp = inode->u.generic_ip;
  176. struct pci_dev *dev = dp->data;
  177. #ifdef HAVE_PCI_MMAP
  178. struct pci_filp_private *fpriv = file->private_data;
  179. #endif /* HAVE_PCI_MMAP */
  180. int ret = 0;
  181. switch (cmd) {
  182. case PCIIOC_CONTROLLER:
  183. ret = pci_controller_num(dev);
  184. break;
  185. #ifdef HAVE_PCI_MMAP
  186. case PCIIOC_MMAP_IS_IO:
  187. fpriv->mmap_state = pci_mmap_io;
  188. break;
  189. case PCIIOC_MMAP_IS_MEM:
  190. fpriv->mmap_state = pci_mmap_mem;
  191. break;
  192. case PCIIOC_WRITE_COMBINE:
  193. if (arg)
  194. fpriv->write_combine = 1;
  195. else
  196. fpriv->write_combine = 0;
  197. break;
  198. #endif /* HAVE_PCI_MMAP */
  199. default:
  200. ret = -EINVAL;
  201. break;
  202. };
  203. return ret;
  204. }
  205. #ifdef HAVE_PCI_MMAP
  206. static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
  207. {
  208. struct inode *inode = file->f_dentry->d_inode;
  209. const struct proc_dir_entry *dp = inode->u.generic_ip;
  210. struct pci_dev *dev = dp->data;
  211. struct pci_filp_private *fpriv = file->private_data;
  212. int ret;
  213. if (!capable(CAP_SYS_RAWIO))
  214. return -EPERM;
  215. ret = pci_mmap_page_range(dev, vma,
  216.   fpriv->mmap_state,
  217.   fpriv->write_combine);
  218. if (ret < 0)
  219. return ret;
  220. return 0;
  221. }
  222. static int proc_bus_pci_open(struct inode *inode, struct file *file)
  223. {
  224. struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
  225. if (!fpriv)
  226. return -ENOMEM;
  227. fpriv->mmap_state = pci_mmap_io;
  228. fpriv->write_combine = 0;
  229. file->private_data = fpriv;
  230. return 0;
  231. }
  232. static int proc_bus_pci_release(struct inode *inode, struct file *file)
  233. {
  234. kfree(file->private_data);
  235. file->private_data = NULL;
  236. return 0;
  237. }
  238. #endif /* HAVE_PCI_MMAP */
  239. static struct file_operations proc_bus_pci_operations = {
  240. llseek: proc_bus_pci_lseek,
  241. read: proc_bus_pci_read,
  242. write: proc_bus_pci_write,
  243. ioctl: proc_bus_pci_ioctl,
  244. #ifdef HAVE_PCI_MMAP
  245. open: proc_bus_pci_open,
  246. release: proc_bus_pci_release,
  247. mmap: proc_bus_pci_mmap,
  248. #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
  249. get_unmapped_area: get_pci_unmapped_area,
  250. #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
  251. #endif /* HAVE_PCI_MMAP */
  252. };
  253. #if BITS_PER_LONG == 32
  254. #define LONG_FORMAT "t%08lx"
  255. #else
  256. #define LONG_FORMAT "t%16lx"
  257. #endif
  258. /* iterator */
  259. static void *pci_seq_start(struct seq_file *m, loff_t *pos)
  260. {
  261. struct list_head *p = &pci_devices;
  262. loff_t n = *pos;
  263. /* XXX: surely we need some locking for traversing the list? */
  264. while (n--) {
  265. p = p->next;
  266. if (p == &pci_devices)
  267. return NULL;
  268. }
  269. return p;
  270. }
  271. static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos)
  272. {
  273. struct list_head *p = v;
  274. (*pos)++;
  275. return p->next != &pci_devices ? p->next : NULL;
  276. }
  277. static void pci_seq_stop(struct seq_file *m, void *v)
  278. {
  279. /* release whatever locks we need */
  280. }
  281. static int show_device(struct seq_file *m, void *v)
  282. {
  283. struct list_head *p = v;
  284. const struct pci_dev *dev;
  285. const struct pci_driver *drv;
  286. int i;
  287. if (p == &pci_devices)
  288. return 0;
  289. dev = pci_dev_g(p);
  290. drv = pci_dev_driver(dev);
  291. seq_printf(m, "%02x%02xt%04x%04xt%x",
  292. dev->bus->number,
  293. dev->devfn,
  294. dev->vendor,
  295. dev->device,
  296. dev->irq);
  297. /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
  298. for(i=0; i<7; i++)
  299. seq_printf(m, LONG_FORMAT,
  300. dev->resource[i].start |
  301. (dev->resource[i].flags & PCI_REGION_FLAG_MASK));
  302. for(i=0; i<7; i++)
  303. seq_printf(m, LONG_FORMAT,
  304. dev->resource[i].start < dev->resource[i].end ?
  305. dev->resource[i].end - dev->resource[i].start + 1 : 0);
  306. seq_putc(m, 't');
  307. if (drv)
  308. seq_printf(m, "%s", drv->name);
  309. seq_putc(m, 'n');
  310. return 0;
  311. }
  312. static struct seq_operations proc_bus_pci_devices_op = {
  313. start: pci_seq_start,
  314. next: pci_seq_next,
  315. stop: pci_seq_stop,
  316. show: show_device
  317. };
  318. struct proc_dir_entry *proc_bus_pci_dir;
  319. int pci_proc_attach_device(struct pci_dev *dev)
  320. {
  321. struct pci_bus *bus = dev->bus;
  322. struct proc_dir_entry *de, *e;
  323. char name[16];
  324. if (!(de = bus->procdir)) {
  325. sprintf(name, "%02x", bus->number);
  326. de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
  327. if (!de)
  328. return -ENOMEM;
  329. }
  330. sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
  331. e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, de);
  332. if (!e)
  333. return -ENOMEM;
  334. e->proc_fops = &proc_bus_pci_operations;
  335. e->data = dev;
  336. e->size = PCI_CFG_SPACE_SIZE;
  337. return 0;
  338. }
  339. int pci_proc_detach_device(struct pci_dev *dev)
  340. {
  341. struct proc_dir_entry *e;
  342. if ((e = dev->procent)) {
  343. if (atomic_read(&e->count))
  344. return -EBUSY;
  345. remove_proc_entry(e->name, dev->bus->procdir);
  346. dev->procent = NULL;
  347. }
  348. return 0;
  349. }
  350. int pci_proc_attach_bus(struct pci_bus* bus)
  351. {
  352. struct proc_dir_entry *de = bus->procdir;
  353. if (!de) {
  354. char name[16];
  355. sprintf(name, "%02x", bus->number);
  356. de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
  357. if (!de)
  358. return -ENOMEM;
  359. }
  360. return 0;
  361. }
  362. int pci_proc_detach_bus(struct pci_bus* bus)
  363. {
  364. struct proc_dir_entry *de = bus->procdir;
  365. if (de)
  366. remove_proc_entry(de->name, proc_bus_pci_dir);
  367. return 0;
  368. }
  369. /*
  370.  *  Backward compatible /proc/pci interface.
  371.  */
  372. /*
  373.  * Convert some of the configuration space registers of the device at
  374.  * address (bus,devfn) into a string (possibly several lines each).
  375.  * The configuration string is stored starting at buf[len].  If the
  376.  * string would exceed the size of the buffer (SIZE), 0 is returned.
  377.  */
  378. static int show_dev_config(struct seq_file *m, void *v)
  379. {
  380. struct list_head *p = v;
  381. struct pci_dev *dev;
  382. struct pci_driver *drv;
  383. u32 class_rev;
  384. unsigned char latency, min_gnt, max_lat, *class;
  385. int reg;
  386. if (p == &pci_devices) {
  387. seq_puts(m, "PCI devices found:n");
  388. return 0;
  389. }
  390. dev = pci_dev_g(p);
  391. drv = pci_dev_driver(dev);
  392. pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
  393. pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
  394. pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
  395. pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
  396. seq_printf(m, "  Bus %2d, device %3d, function %2d:n",
  397.        dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
  398. class = pci_class_name(class_rev >> 16);
  399. if (class)
  400. seq_printf(m, "    %s", class);
  401. else
  402. seq_printf(m, "    Class %04x", class_rev >> 16);
  403. seq_printf(m, ": %s (rev %d).n", dev->name, class_rev & 0xff);
  404. if (dev->irq)
  405. seq_printf(m, "      IRQ %d.n", dev->irq);
  406. if (latency || min_gnt || max_lat) {
  407. seq_printf(m, "      Master Capable.  ");
  408. if (latency)
  409. seq_printf(m, "Latency=%d.  ", latency);
  410. else
  411. seq_puts(m, "No bursts.  ");
  412. if (min_gnt)
  413. seq_printf(m, "Min Gnt=%d.", min_gnt);
  414. if (max_lat)
  415. seq_printf(m, "Max Lat=%d.", max_lat);
  416. seq_putc(m, 'n');
  417. }
  418. for (reg = 0; reg < 6; reg++) {
  419. struct resource *res = dev->resource + reg;
  420. unsigned long base, end, flags;
  421. base = res->start;
  422. end = res->end;
  423. flags = res->flags;
  424. if (!end)
  425. continue;
  426. if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
  427. seq_printf(m, "      I/O at 0x%lx [0x%lx].n",
  428. base, end);
  429. } else {
  430. const char *pref, *type = "unknown";
  431. if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
  432. pref = "P";
  433. else
  434. pref = "Non-p";
  435. switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
  436.       case PCI_BASE_ADDRESS_MEM_TYPE_32:
  437. type = "32 bit"; break;
  438.       case PCI_BASE_ADDRESS_MEM_TYPE_1M:
  439. type = "20 bit"; break;
  440.       case PCI_BASE_ADDRESS_MEM_TYPE_64:
  441. type = "64 bit"; break;
  442. }
  443. seq_printf(m, "      %srefetchable %s memory at "
  444.        "0x%lx [0x%lx].n", pref, type,
  445.        base,
  446.        end);
  447. }
  448. }
  449. return 0;
  450. }
  451. static struct seq_operations proc_pci_op = {
  452. start: pci_seq_start,
  453. next: pci_seq_next,
  454. stop: pci_seq_stop,
  455. show: show_dev_config
  456. };
  457. static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
  458. {
  459. return seq_open(file, &proc_bus_pci_devices_op);
  460. }
  461. static struct file_operations proc_bus_pci_dev_operations = {
  462. open: proc_bus_pci_dev_open,
  463. read: seq_read,
  464. llseek: seq_lseek,
  465. release: seq_release,
  466. };
  467. static int proc_pci_open(struct inode *inode, struct file *file)
  468. {
  469. return seq_open(file, &proc_pci_op);
  470. }
  471. static struct file_operations proc_pci_operations = {
  472. open: proc_pci_open,
  473. read: seq_read,
  474. llseek: seq_lseek,
  475. release: seq_release,
  476. };
  477. static int __init pci_proc_init(void)
  478. {
  479. if (pci_present()) {
  480. struct proc_dir_entry *entry;
  481. struct pci_dev *dev;
  482. proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
  483. entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
  484. if (entry)
  485. entry->proc_fops = &proc_bus_pci_dev_operations;
  486. pci_for_each_dev(dev) {
  487. pci_proc_attach_device(dev);
  488. }
  489. entry = create_proc_entry("pci", 0, NULL);
  490. if (entry)
  491. entry->proc_fops = &proc_pci_operations;
  492. }
  493. return 0;
  494. }
  495. __initcall(pci_proc_init);