isapnp_proc.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:24k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  *  ISA Plug & Play support
  3.  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  4.  *
  5.  *  Modified by Ed Okerson <eokerson@quicknet.net> to work with the 2.2.x
  6.  *  series of Linux kernels. 11/17/99
  7.  *
  8.  *   This program is free software; you can redistribute it and/or modify
  9.  *   it under the terms of the GNU General Public License as published by
  10.  *   the Free Software Foundation; either version 2 of the License, or
  11.  *   (at your option) any later version.
  12.  *
  13.  *   This program is distributed in the hope that it will be useful,
  14.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *   GNU General Public License for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with this program; if not, write to the Free Software
  20.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  */
  23. static void *isapnp_alloc(long size);
  24. struct pnp_bus *isapnp_cards;
  25. struct pnp_dev *isapnp_devices;
  26. struct isapnp_info_buffer {
  27. char *buffer; /* pointer to begin of buffer */
  28. char *curr; /* current position in buffer */
  29. unsigned long size; /* current size */
  30. unsigned long len; /* total length of buffer */
  31. int stop; /* stop flag */
  32. int error; /* error code */
  33. };
  34. typedef struct isapnp_info_buffer isapnp_info_buffer_t;
  35. static struct proc_dir_entry *isapnp_proc_entry = NULL;
  36. static void isapnp_info_read(isapnp_info_buffer_t *buffer);
  37. static void isapnp_info_write(isapnp_info_buffer_t *buffer);
  38. int isapnp_printf(isapnp_info_buffer_t * buffer, char *fmt,...)
  39. {
  40. va_list args;
  41. int res;
  42. char sbuffer[512];
  43. if (buffer->stop || buffer->error)
  44. return 0;
  45. va_start(args, fmt);
  46. res = vsprintf(sbuffer, fmt, args);
  47. va_end(args);
  48. if (buffer->size + res >= buffer->len) {
  49. buffer->stop = 1;
  50. return 0;
  51. }
  52. strcpy(buffer->curr, sbuffer);
  53. buffer->curr += res;
  54. buffer->size += res;
  55. return res;
  56. }
  57. static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig)
  58. {
  59. switch (orig) {
  60. case 0: /* SEEK_SET */
  61. file->f_pos = offset;
  62. return file->f_pos;
  63. case 1: /* SEEK_CUR */
  64. file->f_pos += offset;
  65. return file->f_pos;
  66. case 2: /* SEEK_END */
  67. default:
  68. return -EINVAL;
  69. }
  70. return -ENXIO;
  71. }
  72. static ssize_t isapnp_info_entry_read(struct file *file, char *buffer,
  73.       size_t count, loff_t * offset)
  74. {
  75. isapnp_info_buffer_t *buf;
  76. long size = 0, size1;
  77. int mode;
  78. mode = file->f_flags & O_ACCMODE;
  79. if (mode != O_RDONLY)
  80. return -EINVAL;
  81. buf = (isapnp_info_buffer_t *) file->private_data;
  82. if (!buf)
  83. return -EIO;
  84. if (file->f_pos >= buf->size)
  85. return 0;
  86. size = buf->size < count ? buf->size : count;
  87. size1 = buf->size - file->f_pos;
  88. if (size1 < size)
  89. size = size1;
  90. if (copy_to_user(buffer, buf->buffer + file->f_pos, size))
  91. return -EFAULT;
  92. file->f_pos += size;
  93. return size;
  94. }
  95. static ssize_t isapnp_info_entry_write(struct file *file, const char *buffer,
  96.        size_t count, loff_t * offset)
  97. {
  98. isapnp_info_buffer_t *buf;
  99. long size = 0, size1;
  100. int mode;
  101. mode = file->f_flags & O_ACCMODE;
  102. if (mode != O_WRONLY)
  103. return -EINVAL;
  104. buf = (isapnp_info_buffer_t *) file->private_data;
  105. if (!buf)
  106. return -EIO;
  107. if (file->f_pos < 0)
  108. return -EINVAL;
  109. if (file->f_pos >= buf->len)
  110. return -ENOMEM;
  111. size = buf->len < count ? buf->len : count;
  112. size1 = buf->len - file->f_pos;
  113. if (size1 < size)
  114. size = size1;
  115. if (copy_from_user(buf->buffer + file->f_pos, buffer, size))
  116. return -EFAULT;
  117. if (buf->size < file->f_pos + size)
  118. buf->size = file->f_pos + size;
  119. file->f_pos += size;
  120. return size;
  121. }
  122. static int isapnp_info_entry_open(struct inode *inode, struct file *file)
  123. {
  124. isapnp_info_buffer_t *buffer;
  125. int mode;
  126. mode = file->f_flags & O_ACCMODE;
  127. if (mode != O_RDONLY && mode != O_WRONLY)
  128. return -EINVAL;
  129. buffer = (isapnp_info_buffer_t *)
  130. isapnp_alloc(sizeof(isapnp_info_buffer_t));
  131. if (!buffer)
  132. return -ENOMEM;
  133. buffer->len = 4 * PAGE_SIZE;
  134. buffer->buffer = vmalloc(buffer->len);
  135. if (!buffer->buffer) {
  136. kfree(buffer);
  137. return -ENOMEM;
  138. }
  139. buffer->curr = buffer->buffer;
  140. file->private_data = buffer;
  141. MOD_INC_USE_COUNT;
  142. if (mode == O_RDONLY)
  143. isapnp_info_read(buffer);
  144. return 0;
  145. }
  146. static int isapnp_info_entry_release(struct inode *inode, struct file *file)
  147. {
  148. isapnp_info_buffer_t *buffer;
  149. int mode;
  150. if ((buffer = (isapnp_info_buffer_t *) file->private_data) == NULL)
  151. return -EINVAL;
  152. mode = file->f_flags & O_ACCMODE;
  153. if (mode == O_WRONLY)
  154. isapnp_info_write(buffer);
  155. vfree(buffer->buffer);
  156. kfree(buffer);
  157. MOD_DEC_USE_COUNT;
  158. return 0;
  159. }
  160. static unsigned int isapnp_info_entry_poll(struct file *file, poll_table * wait)
  161. {
  162. if (!file->private_data)
  163. return 0;
  164. return POLLIN | POLLRDNORM;
  165. }
  166. static int isapnp_info_entry_ioctl(struct inode *inode, struct file *file,
  167.    unsigned int cmd, unsigned long arg)
  168. {
  169. return -EINVAL;
  170. }
  171. static int isapnp_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
  172. {
  173. return -ENXIO;
  174. }
  175. static struct file_operations isapnp_info_entry_operations =
  176. {
  177. isapnp_info_entry_lseek, /* lseek */
  178. isapnp_info_entry_read, /* read */
  179. isapnp_info_entry_write, /* write */
  180. NULL, /* readdir */
  181. isapnp_info_entry_poll, /* poll */
  182. isapnp_info_entry_ioctl, /* ioctl - default */
  183. isapnp_info_entry_mmap, /* mmap */
  184. isapnp_info_entry_open, /* open */
  185. NULL, /* flush */
  186. isapnp_info_entry_release, /* release */
  187. NULL, /* can't fsync */
  188. NULL, /* fasync */
  189. NULL, /* check_media_change */
  190. NULL, /* revalidate */
  191. NULL, /* lock */
  192. };
  193. static struct inode_operations isapnp_info_entry_inode_operations =
  194. {
  195. &isapnp_info_entry_operations, /* default sound info directory file-ops */
  196. NULL, /* create */
  197. NULL, /* lookup */
  198. NULL, /* link */
  199. NULL, /* unlink */
  200. NULL, /* symlink */
  201. NULL, /* mkdir */
  202. NULL, /* rmdir */
  203. NULL, /* mknod */
  204. NULL, /* rename */
  205. NULL, /* readlink */
  206. NULL, /* follow_link */
  207. NULL, /* readpage */
  208. NULL, /* writepage */
  209. NULL, /* bmap */
  210. NULL, /* truncate */
  211. NULL /* permission */
  212. };
  213. static int __init isapnp_proc_init(void)
  214. {
  215. struct proc_dir_entry *p;
  216. isapnp_proc_entry = NULL;
  217. p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root);
  218. if (!p)
  219. return -ENOMEM;
  220. p->ops = &isapnp_info_entry_inode_operations;
  221. isapnp_proc_entry = p;
  222. return 0;
  223. }
  224. #ifdef MODULE
  225. static int isapnp_proc_done(void)
  226. {
  227. if (isapnp_proc_entry)
  228. remove_proc_entry("isapnp",&proc_root);
  229. return 0;
  230. }
  231. #endif /* MODULE */
  232. /*
  233.  *
  234.  */
  235. static void isapnp_print_devid(isapnp_info_buffer_t *buffer, unsigned short vendor, unsigned short device)
  236. {
  237. char tmp[8];
  238. sprintf(tmp, "%c%c%c%x%x%x%x",
  239. 'A' + ((vendor >> 2) & 0x3f) - 1,
  240. 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
  241. 'A' + ((vendor >> 8) & 0x1f) - 1,
  242. (device >> 4) & 0x0f,
  243. device & 0x0f,
  244. (device >> 12) & 0x0f,
  245. (device >> 8) & 0x0f);
  246. isapnp_printf(buffer, tmp);
  247. }
  248. static void isapnp_print_compatible(isapnp_info_buffer_t *buffer, struct pnp_dev *dev)
  249. {
  250. int idx;
  251. for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++) {
  252. if (dev->vendor_compatible[idx] == 0)
  253. continue;
  254. isapnp_printf(buffer, "    Compatible device ");
  255. isapnp_print_devid(buffer,
  256.    dev->vendor_compatible[idx],
  257.    dev->device_compatible[idx]);
  258. isapnp_printf(buffer, "n");
  259. }
  260. }
  261. static void isapnp_print_port(isapnp_info_buffer_t *buffer, char *space, struct isapnp_port *port)
  262. {
  263. isapnp_printf(buffer, "%sPort 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decodingn",
  264. space, port->min, port->max, port->align ? (port->align-1) : 0, port->size,
  265. port->flags & ISAPNP_PORT_FLAG_16BITADDR ? 16 : 10);
  266. }
  267. static void isapnp_print_irq(isapnp_info_buffer_t *buffer, char *space, struct isapnp_irq *irq)
  268. {
  269. int first = 1, i;
  270. isapnp_printf(buffer, "%sIRQ ", space);
  271. for (i = 0; i < 16; i++)
  272. if (irq->map & (1<<i)) {
  273. if (!first) {
  274. isapnp_printf(buffer, ",");
  275. } else {
  276. first = 0;
  277. }
  278. if (i == 2 || i == 9)
  279. isapnp_printf(buffer, "2/9");
  280. else
  281. isapnp_printf(buffer, "%i", i);
  282. }
  283. if (!irq->map)
  284. isapnp_printf(buffer, "<none>");
  285. if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
  286. isapnp_printf(buffer, " High-Edge");
  287. if (irq->flags & IORESOURCE_IRQ_LOWEDGE)
  288. isapnp_printf(buffer, " Low-Edge");
  289. if (irq->flags & IORESOURCE_IRQ_HIGHLEVEL)
  290. isapnp_printf(buffer, " High-Level");
  291. if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
  292. isapnp_printf(buffer, " Low-Level");
  293. isapnp_printf(buffer, "n");
  294. }
  295. static void isapnp_print_dma(isapnp_info_buffer_t *buffer, char *space, struct isapnp_dma *dma)
  296. {
  297. int first = 1, i;
  298. char *s;
  299. isapnp_printf(buffer, "%sDMA ", space);
  300. for (i = 0; i < 8; i++)
  301. if (dma->map & (1<<i)) {
  302. if (!first) {
  303. isapnp_printf(buffer, ",");
  304. } else {
  305. first = 0;
  306. }
  307. isapnp_printf(buffer, "%i", i);
  308. }
  309. if (!dma->map)
  310. isapnp_printf(buffer, "<none>");
  311. switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) {
  312. case IORESOURCE_DMA_8BIT:
  313. s = "8-bit";
  314. break;
  315. case IORESOURCE_DMA_8AND16BIT:
  316. s = "8-bit&16-bit";
  317. break;
  318. default:
  319. s = "16-bit";
  320. }
  321. isapnp_printf(buffer, " %s", s);
  322. if (dma->flags & IORESOURCE_DMA_MASTER)
  323. isapnp_printf(buffer, " master");
  324. if (dma->flags & IORESOURCE_DMA_BYTE)
  325. isapnp_printf(buffer, " byte-count");
  326. if (dma->flags & IORESOURCE_DMA_WORD)
  327. isapnp_printf(buffer, " word-count");
  328. switch (dma->flags & IORESOURCE_DMA_SPEED_MASK) {
  329. case IORESOURCE_DMA_TYPEA:
  330. s = "type-A";
  331. break;
  332. case IORESOURCE_DMA_TYPEB:
  333. s = "type-B";
  334. break;
  335. case IORESOURCE_DMA_TYPEF:
  336. s = "type-F";
  337. break;
  338. default:
  339. s = "compatible";
  340. break;
  341. }
  342. isapnp_printf(buffer, " %sn", s);
  343. }
  344. static void isapnp_print_mem(isapnp_info_buffer_t *buffer, char *space, struct isapnp_mem *mem)
  345. {
  346. char *s;
  347. isapnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
  348. space, mem->min, mem->max, mem->align, mem->size);
  349. if (mem->flags & IORESOURCE_MEM_WRITEABLE)
  350. isapnp_printf(buffer, ", writeable");
  351. if (mem->flags & IORESOURCE_MEM_CACHEABLE)
  352. isapnp_printf(buffer, ", cacheable");
  353. if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
  354. isapnp_printf(buffer, ", range-length");
  355. if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
  356. isapnp_printf(buffer, ", shadowable");
  357. if (mem->flags & IORESOURCE_MEM_EXPANSIONROM)
  358. isapnp_printf(buffer, ", expansion ROM");
  359. switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
  360. case IORESOURCE_MEM_8BIT:
  361. s = "8-bit";
  362. break;
  363. case IORESOURCE_MEM_8AND16BIT:
  364. s = "8-bit&16-bit";
  365. break;
  366. default:
  367. s = "16-bit";
  368. }
  369. isapnp_printf(buffer, ", %sn", s);
  370. }
  371. static void isapnp_print_mem32(isapnp_info_buffer_t *buffer, char *space, struct isapnp_mem32 *mem32)
  372. {
  373. int first = 1, i;
  374. isapnp_printf(buffer, "%s32-bit memory ", space);
  375. for (i = 0; i < 17; i++) {
  376. if (first) {
  377. first = 0;
  378. } else {
  379. isapnp_printf(buffer, ":");
  380. }
  381. isapnp_printf(buffer, "%02x", mem32->data[i]);
  382. }
  383. }
  384. static void isapnp_print_resources(isapnp_info_buffer_t *buffer, char *space, struct isapnp_resources *res)
  385. {
  386. char *s;
  387. struct isapnp_port *port;
  388. struct isapnp_irq *irq;
  389. struct isapnp_dma *dma;
  390. struct isapnp_mem *mem;
  391. struct isapnp_mem32 *mem32;
  392. switch (res->priority) {
  393. case ISAPNP_RES_PRIORITY_PREFERRED:
  394. s = "preferred";
  395. break;
  396. case ISAPNP_RES_PRIORITY_ACCEPTABLE:
  397. s = "acceptable";
  398. break;
  399. case ISAPNP_RES_PRIORITY_FUNCTIONAL:
  400. s = "functional";
  401. break;
  402. default:
  403. s = "invalid";
  404. }
  405. isapnp_printf(buffer, "%sPriority %sn", space, s);
  406. for (port = res->port; port; port = port->next)
  407. isapnp_print_port(buffer, space, port);
  408. for (irq = res->irq; irq; irq = irq->next)
  409. isapnp_print_irq(buffer, space, irq);
  410. for (dma = res->dma; dma; dma = dma->next)
  411. isapnp_print_dma(buffer, space, dma);
  412. for (mem = res->mem; mem; mem = mem->next)
  413. isapnp_print_mem(buffer, space, mem);
  414. for (mem32 = res->mem32; mem32; mem32 = mem32->next)
  415. isapnp_print_mem32(buffer, space, mem32);
  416. }
  417. static void isapnp_print_configuration(isapnp_info_buffer_t *buffer, struct pnp_dev *dev)
  418. {
  419. int i, tmp, next;
  420. char *space = "    ";
  421. isapnp_cfg_begin(dev->bus->number, dev->devfn);
  422. isapnp_printf(buffer, "%sDevice is %sactiven",
  423. space, isapnp_read_byte(ISAPNP_CFG_ACTIVATE)?"":"not ");
  424. for (i = next = 0; i < 8; i++) {
  425. tmp = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1));
  426. if (!tmp)
  427. continue;
  428. if (!next) {
  429. isapnp_printf(buffer, "%sActive port ", space);
  430. next = 1;
  431. }
  432. isapnp_printf(buffer, "%s0x%x", i > 0 ? "," : "", tmp);
  433. }
  434. if (next)
  435. isapnp_printf(buffer, "n");
  436. for (i = next = 0; i < 2; i++) {
  437. tmp = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1));
  438. if (!(tmp >> 8))
  439. continue;
  440. if (!next) {
  441. isapnp_printf(buffer, "%sActive IRQ ", space);
  442. next = 1;
  443. }
  444. isapnp_printf(buffer, "%s%i", i > 0 ? "," : "", tmp >> 8);
  445. if (tmp & 0xff)
  446. isapnp_printf(buffer, " [0x%x]", tmp & 0xff);
  447. }
  448. if (next)
  449. isapnp_printf(buffer, "n");
  450. for (i = next = 0; i < 2; i++) {
  451. tmp = isapnp_read_byte(ISAPNP_CFG_DMA + i);
  452. if (tmp == 4)
  453. continue;
  454. if (!next) {
  455. isapnp_printf(buffer, "%sActive DMA ", space);
  456. next = 1;
  457. }
  458. isapnp_printf(buffer, "%s%i", i > 0 ? "," : "", tmp);
  459. }
  460. if (next)
  461. isapnp_printf(buffer, "n");
  462. for (i = next = 0; i < 4; i++) {
  463. tmp = isapnp_read_dword(ISAPNP_CFG_MEM + (i << 3));
  464. if (!tmp)
  465. continue;
  466. if (!next) {
  467. isapnp_printf(buffer, "%sActive memory ", space);
  468. next = 1;
  469. }
  470. isapnp_printf(buffer, "%s0x%x", i > 0 ? "," : "", tmp);
  471. }
  472. if (next)
  473. isapnp_printf(buffer, "n");
  474. isapnp_cfg_end();
  475. }
  476. static void isapnp_print_device(isapnp_info_buffer_t *buffer, struct pnp_dev *dev)
  477. {
  478. int block, block1;
  479. char *space = "    ";
  480. struct isapnp_resources *res, *resa;
  481. if (!dev)
  482. return;
  483. isapnp_printf(buffer, "  Logical device %i '", dev->devfn);
  484. isapnp_print_devid(buffer, dev->vendor, dev->device);
  485. isapnp_printf(buffer, ":%s'", dev->name[0]?dev->name:"Unknown");
  486. isapnp_printf(buffer, "n");
  487. #if 0
  488. isapnp_cfg_begin(dev->bus->number, dev->devfn);
  489. for (block = 0; block < 128; block++)
  490. if ((block % 16) == 15)
  491. isapnp_printf(buffer, "%02xn", isapnp_read_byte(block));
  492. else
  493. isapnp_printf(buffer, "%02x:", isapnp_read_byte(block));
  494. isapnp_cfg_end();
  495. #endif
  496. if (dev->regs)
  497. isapnp_printf(buffer, "%sSupported registers 0x%xn", space, dev->regs);
  498. isapnp_print_compatible(buffer, dev);
  499. isapnp_print_configuration(buffer, dev);
  500. for (res = (struct isapnp_resources *)dev->sysdata, block = 0; res; res = res->next, block++) {
  501. isapnp_printf(buffer, "%sResources %in", space, block);
  502. isapnp_print_resources(buffer, "      ", res);
  503. for (resa = res->alt, block1 = 1; resa; resa = resa->alt, block1++) {
  504. isapnp_printf(buffer, "%s  Alternate resources %i:%in", space, block, block1);
  505. isapnp_print_resources(buffer, "        ", resa);
  506. }
  507. }
  508. }
  509. /*
  510.  *  Main read routine
  511.  */
  512.  
  513. static void isapnp_info_read(isapnp_info_buffer_t *buffer)
  514. {
  515. struct pnp_bus *card;
  516. struct pnp_dev *dev;
  517. for (card = isapnp_cards; card; 
  518.              card = card->next) {
  519. isapnp_printf(buffer, "Card %i '", card->number);
  520. isapnp_print_devid(buffer, card->vendor, card->device);
  521. isapnp_printf(buffer, ":%s'", card->name[0]?card->name:"Unknown");
  522. if (card->pnpver)
  523. isapnp_printf(buffer, " PnP version %x.%x", card->pnpver >> 4, card->pnpver & 0x0f);
  524. if (card->productver)
  525. isapnp_printf(buffer, " Product version %x.%x", card->productver >> 4, card->productver & 0x0f);
  526. isapnp_printf(buffer,"n");
  527. for (dev = card->devices; dev; dev = dev->sibling)
  528. isapnp_print_device(buffer, dev);
  529. }
  530. }
  531. /*
  532.  *
  533.  */
  534. static struct pnp_bus *isapnp_info_card;
  535. static struct pnp_dev *isapnp_info_device;
  536. static char *isapnp_get_str(char *dest, char *src, int len)
  537. {
  538. int c;
  539. while (*src == ' ' || *src == 't')
  540. src++;
  541. if (*src == '"' || *src == ''') {
  542. c = *src++;
  543. while (--len > 0 && *src && *src != c) {
  544. *dest++ = *src++;
  545. }
  546. if (*src == c)
  547. src++;
  548. } else {
  549. while (--len > 0 && *src && *src != ' ' && *src != 't') {
  550. *dest++ = *src++;
  551. }
  552. }
  553. *dest = 0;
  554. while (*src == ' ' || *src == 't')
  555. src++;
  556. return src;
  557. }
  558. static unsigned char isapnp_get_hex(unsigned char c)
  559. {
  560. if (c >= '0' || c <= '9')
  561. return c - '0';
  562. if (c >= 'a' || c <= 'f')
  563. return (c - 'a') + 10;
  564. if (c >= 'A' || c <= 'F')
  565. return (c - 'A') + 10;
  566. return 0;
  567. }
  568. static unsigned int isapnp_parse_id(const char *id)
  569. {
  570. if (strlen(id) != 7) {
  571. printk("isapnp: wrong PnP IDn");
  572. return 0;
  573. }
  574. return (ISAPNP_VENDOR(id[0], id[1], id[2])<<16) |
  575. (isapnp_get_hex(id[3])<<4) |
  576. (isapnp_get_hex(id[4])<<0) |
  577. (isapnp_get_hex(id[5])<<12) |
  578. (isapnp_get_hex(id[6])<<8);
  579. }
  580. static int isapnp_set_card(char *line)
  581. {
  582. int idx, idx1;
  583. unsigned int id;
  584. char index[16], value[32];
  585. isapnp_info_card = NULL;
  586. line = isapnp_get_str(index, line, sizeof(index));
  587. isapnp_get_str(value, line, sizeof(value));
  588. idx = idx1 = simple_strtoul(index, NULL, 0);
  589. id = isapnp_parse_id(value);
  590. isapnp_info_card = isapnp_find_card(id >> 16, id & 0xffff, NULL);
  591. while (isapnp_info_card && idx1-- > 0)
  592. isapnp_info_card = isapnp_find_card(id >> 16, id & 0xffff, isapnp_info_card);
  593. if (isapnp_info_card == NULL) {
  594. printk("isapnp: card '%s' order %i not foundn", value, idx);
  595. return 1;
  596. }
  597. if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
  598. printk("isapnp: configuration start sequence for device '%s' failedn", value);
  599. isapnp_info_card = NULL;
  600. return 1;
  601. }
  602. return 0;
  603. }
  604. static int isapnp_select_csn(char *line)
  605. {
  606. int csn;
  607. char index[16], value[32];
  608. isapnp_info_device = NULL;
  609. isapnp_get_str(index, line, sizeof(index));
  610. csn = simple_strtoul(index, NULL, 0);
  611. for (isapnp_info_card = isapnp_cards; isapnp_info_card; isapnp_info_card = isapnp_info_card->next)
  612. if (isapnp_info_card->number == csn)
  613. break;
  614. if (isapnp_info_card == NULL) {
  615. printk("isapnp: cannot find CSN %in", csn);
  616. return 1;
  617. }
  618. if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
  619. printk("isapnp: configuration start sequence for device '%s' failedn", value);
  620. isapnp_info_card = NULL;
  621. return 1;
  622. }
  623. return 0;
  624. }
  625. static int isapnp_set_device(char *line)
  626. {
  627. int idx, idx1;
  628. unsigned int id;
  629. char index[16], value[32];
  630. line = isapnp_get_str(index, line, sizeof(index));
  631. isapnp_get_str(value, line, sizeof(value));
  632. idx = idx1 = simple_strtoul(index, NULL, 0);
  633. id = isapnp_parse_id(value);
  634. isapnp_info_device = isapnp_find_dev(isapnp_info_card, id >> 16, id & 0xffff, NULL);
  635. while (isapnp_info_device && idx-- > 0)
  636. isapnp_info_device = isapnp_find_dev(isapnp_info_card, id >> 16, id & 0xffff, isapnp_info_device);
  637. if (isapnp_info_device == NULL) {
  638. printk("isapnp: device '%s' order %i not foundn", value, idx);
  639. return 1;
  640. }
  641. isapnp_device(isapnp_info_device->devfn);
  642. return 0;
  643. }
  644. static int isapnp_autoconfigure(void)
  645. {
  646. if (isapnp_info_device == NULL) {
  647. printk("isapnp: device is not setn");
  648. return 0;
  649. }
  650. if (isapnp_info_device->active)
  651. isapnp_info_device->deactivate(isapnp_info_device);
  652. if (isapnp_info_device->prepare(isapnp_info_device) < 0) {
  653. printk("isapnp: cannot prepare device for the activation");
  654. return 0;
  655. }
  656. if (isapnp_info_device->activate(isapnp_info_device) < 0) {
  657. printk("isapnp: cannot activate device");
  658. return 0;
  659. }
  660. return 0;
  661. }
  662. static int isapnp_set_port(char *line)
  663. {
  664. int idx, port;
  665. char index[16], value[32];
  666. line = isapnp_get_str(index, line, sizeof(index));
  667. isapnp_get_str(value, line, sizeof(value));
  668. idx = simple_strtoul(index, NULL, 0);
  669. port = simple_strtoul(value, NULL, 0);
  670. if (idx < 0 || idx > 7) {
  671. printk("isapnp: wrong port index %in", idx);
  672. return 1;
  673. }
  674. if (port < 0 || port > 0xffff) {
  675. printk("isapnp: wrong port value 0x%xn", port);
  676. return 1;
  677. }
  678. isapnp_write_word(ISAPNP_CFG_PORT + (idx << 1), port);
  679. if (!isapnp_info_device->resource[idx].flags)
  680. return 0;
  681. if (isapnp_info_device->resource[idx].flags & IORESOURCE_AUTO) {
  682. isapnp_info_device->resource[idx].start = port;
  683. isapnp_info_device->resource[idx].end += port - 1;
  684. isapnp_info_device->resource[idx].flags &= ~IORESOURCE_AUTO;
  685. } else {
  686. isapnp_info_device->resource[idx].end -= isapnp_info_device->resource[idx].start;
  687. isapnp_info_device->resource[idx].start = port;
  688. isapnp_info_device->resource[idx].end += port;
  689. }
  690. return 0;
  691. }
  692. static void isapnp_set_irqresource(struct resource *res, int irq)
  693. {
  694. res->start = res->end = irq;
  695. res->flags = IORESOURCE_IRQ;
  696. }
  697.  
  698. static int isapnp_set_irq(char *line)
  699. {
  700. int idx, irq;
  701. char index[16], value[32];
  702. line = isapnp_get_str(index, line, sizeof(index));
  703. isapnp_get_str(value, line, sizeof(value));
  704. idx = simple_strtoul(index, NULL, 0);
  705. irq = simple_strtoul(value, NULL, 0);
  706. if (idx < 0 || idx > 1) {
  707. printk("isapnp: wrong IRQ index %in", idx);
  708. return 1;
  709. }
  710. if (irq == 2)
  711. irq = 9;
  712. if (irq < 0 || irq > 15) {
  713. printk("isapnp: wrong IRQ value %in", irq);
  714. return 1;
  715. }
  716. isapnp_write_byte(ISAPNP_CFG_IRQ + (idx << 1), irq);
  717. isapnp_set_irqresource(isapnp_info_device->irq_resource + idx, irq);
  718. return 0;
  719. }
  720.  
  721. static void isapnp_set_dmaresource(struct resource *res, int dma)
  722. {
  723. res->start = res->end = dma;
  724. res->flags = IORESOURCE_DMA;
  725. }
  726.  
  727. static int isapnp_set_dma(char *line)
  728. {
  729. int idx, dma;
  730. char index[16], value[32];
  731. line = isapnp_get_str(index, line, sizeof(index));
  732. isapnp_get_str(value, line, sizeof(value));
  733. idx = simple_strtoul(index, NULL, 0);
  734. dma = simple_strtoul(value, NULL, 0);
  735. if (idx < 0 || idx > 1) {
  736. printk("isapnp: wrong DMA index %in", idx);
  737. return 1;
  738. }
  739. if (dma < 0 || dma > 7) {
  740. printk("isapnp: wrong DMA value %in", dma);
  741. return 1;
  742. }
  743. isapnp_write_byte(ISAPNP_CFG_DMA + idx, dma);
  744. isapnp_set_dmaresource(isapnp_info_device->dma_resource + idx, dma);
  745. return 0;
  746. }
  747.  
  748. static int isapnp_set_mem(char *line)
  749. {
  750. int idx;
  751. unsigned int mem;
  752. char index[16], value[32];
  753. line = isapnp_get_str(index, line, sizeof(index));
  754. isapnp_get_str(value, line, sizeof(value));
  755. idx = simple_strtoul(index, NULL, 0);
  756. mem = simple_strtoul(value, NULL, 0);
  757. if (idx < 0 || idx > 3) {
  758. printk("isapnp: wrong memory index %in", idx);
  759. return 1;
  760. }
  761. mem >>= 8;
  762. isapnp_write_word(ISAPNP_CFG_MEM + (idx<<2), mem & 0xffff);
  763. if (!isapnp_info_device->resource[idx + 8].flags)
  764. return 0;
  765. if (isapnp_info_device->resource[idx + 8].flags & IORESOURCE_AUTO) {
  766. isapnp_info_device->resource[idx + 8].start = mem & ~0x00ffff00;
  767. isapnp_info_device->resource[idx + 8].end += (mem & ~0x00ffff00) - 1;
  768. isapnp_info_device->resource[idx + 8].flags &= ~IORESOURCE_AUTO;
  769. } else {
  770. isapnp_info_device->resource[idx + 8].end -= isapnp_info_device->resource[idx + 8].start;
  771. isapnp_info_device->resource[idx + 8].start = mem & ~0x00ffff00;
  772. isapnp_info_device->resource[idx + 8].end += mem & ~0x00ffff00;
  773. }
  774. return 0;
  775. }
  776.  
  777. static int isapnp_poke(char *line, int what)
  778. {
  779. int reg;
  780. unsigned int val;
  781. char index[16], value[32];
  782. line = isapnp_get_str(index, line, sizeof(index));
  783. isapnp_get_str(value, line, sizeof(value));
  784. reg = simple_strtoul(index, NULL, 0);
  785. val = simple_strtoul(value, NULL, 0);
  786. if (reg < 0 || reg > 127) {
  787. printk("isapnp: wrong register %in", reg);
  788. return 1;
  789. }
  790. switch (what) {
  791. case 1:
  792. isapnp_write_word(reg, val);
  793. break;
  794. case 2:
  795. isapnp_write_dword(reg, val);
  796. break;
  797. default:
  798. isapnp_write_byte(reg, val);
  799. break;
  800. }
  801. return 0;
  802. }
  803.  
  804. static int isapnp_decode_line(char *line)
  805. {
  806. char cmd[32];
  807. line = isapnp_get_str(cmd, line, sizeof(cmd));
  808. if (!strcmp(cmd, "card"))
  809. return isapnp_set_card(line);
  810. if (!strcmp(cmd, "csn"))
  811. return isapnp_select_csn(line);
  812. if (!isapnp_info_card) {
  813. printk("isapnp: card is not selectedn");
  814. return 1;
  815. }
  816. if (!strncmp(cmd, "dev", 3))
  817. return isapnp_set_device(line);
  818. if (!isapnp_info_device) {
  819. printk("isapnp: device is not selectedn");
  820. return 1;
  821. }
  822. if (!strncmp(cmd, "auto", 4))
  823. return isapnp_autoconfigure();
  824. if (!strncmp(cmd, "act", 3)) {
  825. isapnp_activate(isapnp_info_device->devfn);
  826. isapnp_info_device->active = 1;
  827. return 0;
  828. }
  829. if (!strncmp(cmd, "deact", 5)) {
  830. isapnp_deactivate(isapnp_info_device->devfn);
  831. isapnp_info_device->active = 0;
  832. return 0;
  833. }
  834. if (!strcmp(cmd, "port"))
  835. return isapnp_set_port(line);
  836. if (!strcmp(cmd, "irq"))
  837. return isapnp_set_irq(line);
  838. if (!strcmp(cmd, "dma"))
  839. return isapnp_set_dma(line);
  840. if (!strncmp(cmd, "mem", 3))
  841. return isapnp_set_mem(line);
  842. if (!strcmp(cmd, "poke"))
  843. return isapnp_poke(line, 0);
  844. if (!strcmp(cmd, "pokew"))
  845. return isapnp_poke(line, 1);
  846. if (!strcmp(cmd, "poked"))
  847. return isapnp_poke(line, 2);
  848. printk("isapnp: wrong command '%s'n", cmd);
  849. return 1;
  850. }
  851. /*
  852.  *  Main write routine
  853.  */
  854. static void isapnp_info_write(isapnp_info_buffer_t *buffer)
  855. {
  856. int c, idx, idx1 = 0;
  857. char line[128];
  858. if (buffer->size <= 0)
  859. return;
  860. isapnp_info_card = NULL;
  861. isapnp_info_device = NULL;
  862. for (idx = 0; idx < buffer->size; idx++) {
  863. c = buffer->buffer[idx];
  864. if (c == 'n') {
  865. line[idx1] = '';
  866. if (line[0] != '#') {
  867. if (isapnp_decode_line(line))
  868. goto __end;
  869. }
  870. idx1 = 0;
  871. continue;
  872. }
  873. if (idx1 >= sizeof(line)-1) {
  874. printk("isapnp: line too long, abortingn");
  875. return;
  876. }
  877. line[idx1++] = c;
  878. }
  879.       __end:
  880. if (isapnp_info_card)
  881. isapnp_cfg_end();
  882. }