interface.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /*
  2. * interface.c - contains everything related to the user interface
  3. *
  4. * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz>
  5. * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
  6. *
  7. */
  8. #include <linux/pnp.h>
  9. #include <linux/string.h>
  10. #include <linux/errno.h>
  11. #include <linux/list.h>
  12. #include <linux/types.h>
  13. #include <linux/stat.h>
  14. #include <linux/ctype.h>
  15. #include <linux/slab.h>
  16. #include <asm/uaccess.h>
  17. #include "base.h"
  18. struct pnp_info_buffer {
  19. char *buffer; /* pointer to begin of buffer */
  20. char *curr; /* current position in buffer */
  21. unsigned long size; /* current size */
  22. unsigned long len; /* total length of buffer */
  23. int stop; /* stop flag */
  24. int error; /* error code */
  25. };
  26. typedef struct pnp_info_buffer pnp_info_buffer_t;
  27. static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt,...)
  28. {
  29. va_list args;
  30. int res;
  31. if (buffer->stop || buffer->error)
  32. return 0;
  33. va_start(args, fmt);
  34. res = vsnprintf(buffer->curr, buffer->len - buffer->size, fmt, args);
  35. va_end(args);
  36. if (buffer->size + res >= buffer->len) {
  37. buffer->stop = 1;
  38. return 0;
  39. }
  40. buffer->curr += res;
  41. buffer->size += res;
  42. return res;
  43. }
  44. static void pnp_print_port(pnp_info_buffer_t *buffer, char *space, struct pnp_port *port)
  45. {
  46. pnp_printf(buffer, "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
  47. space, port->min, port->max, port->align ? (port->align-1) : 0, port->size,
  48. port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10);
  49. }
  50. static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq *irq)
  51. {
  52. int first = 1, i;
  53. pnp_printf(buffer, "%sirq ", space);
  54. for (i = 0; i < PNP_IRQ_NR; i++)
  55. if (test_bit(i, irq->map)) {
  56. if (!first) {
  57. pnp_printf(buffer, ",");
  58. } else {
  59. first = 0;
  60. }
  61. if (i == 2 || i == 9)
  62. pnp_printf(buffer, "2/9");
  63. else
  64. pnp_printf(buffer, "%i", i);
  65. }
  66. if (bitmap_empty(irq->map, PNP_IRQ_NR))
  67. pnp_printf(buffer, "<none>");
  68. if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
  69. pnp_printf(buffer, " High-Edge");
  70. if (irq->flags & IORESOURCE_IRQ_LOWEDGE)
  71. pnp_printf(buffer, " Low-Edge");
  72. if (irq->flags & IORESOURCE_IRQ_HIGHLEVEL)
  73. pnp_printf(buffer, " High-Level");
  74. if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
  75. pnp_printf(buffer, " Low-Level");
  76. pnp_printf(buffer, "\n");
  77. }
  78. static void pnp_print_dma(pnp_info_buffer_t *buffer, char *space, struct pnp_dma *dma)
  79. {
  80. int first = 1, i;
  81. char *s;
  82. pnp_printf(buffer, "%sdma ", space);
  83. for (i = 0; i < 8; i++)
  84. if (dma->map & (1<<i)) {
  85. if (!first) {
  86. pnp_printf(buffer, ",");
  87. } else {
  88. first = 0;
  89. }
  90. pnp_printf(buffer, "%i", i);
  91. }
  92. if (!dma->map)
  93. pnp_printf(buffer, "<none>");
  94. switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) {
  95. case IORESOURCE_DMA_8BIT:
  96. s = "8-bit";
  97. break;
  98. case IORESOURCE_DMA_8AND16BIT:
  99. s = "8-bit&16-bit";
  100. break;
  101. default:
  102. s = "16-bit";
  103. }
  104. pnp_printf(buffer, " %s", s);
  105. if (dma->flags & IORESOURCE_DMA_MASTER)
  106. pnp_printf(buffer, " master");
  107. if (dma->flags & IORESOURCE_DMA_BYTE)
  108. pnp_printf(buffer, " byte-count");
  109. if (dma->flags & IORESOURCE_DMA_WORD)
  110. pnp_printf(buffer, " word-count");
  111. switch (dma->flags & IORESOURCE_DMA_SPEED_MASK) {
  112. case IORESOURCE_DMA_TYPEA:
  113. s = "type-A";
  114. break;
  115. case IORESOURCE_DMA_TYPEB:
  116. s = "type-B";
  117. break;
  118. case IORESOURCE_DMA_TYPEF:
  119. s = "type-F";
  120. break;
  121. default:
  122. s = "compatible";
  123. break;
  124. }
  125. pnp_printf(buffer, " %s\n", s);
  126. }
  127. static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem *mem)
  128. {
  129. char *s;
  130. pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
  131. space, mem->min, mem->max, mem->align, mem->size);
  132. if (mem->flags & IORESOURCE_MEM_WRITEABLE)
  133. pnp_printf(buffer, ", writeable");
  134. if (mem->flags & IORESOURCE_MEM_CACHEABLE)
  135. pnp_printf(buffer, ", cacheable");
  136. if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
  137. pnp_printf(buffer, ", range-length");
  138. if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
  139. pnp_printf(buffer, ", shadowable");
  140. if (mem->flags & IORESOURCE_MEM_EXPANSIONROM)
  141. pnp_printf(buffer, ", expansion ROM");
  142. switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
  143. case IORESOURCE_MEM_8BIT:
  144. s = "8-bit";
  145. break;
  146. case IORESOURCE_MEM_8AND16BIT:
  147. s = "8-bit&16-bit";
  148. break;
  149. case IORESOURCE_MEM_32BIT:
  150. s = "32-bit";
  151. break;
  152. default:
  153. s = "16-bit";
  154. }
  155. pnp_printf(buffer, ", %s\n", s);
  156. }
  157. static void pnp_print_option(pnp_info_buffer_t *buffer, char *space,
  158. struct pnp_option *option, int dep)
  159. {
  160. char *s;
  161. struct pnp_port *port;
  162. struct pnp_irq *irq;
  163. struct pnp_dma *dma;
  164. struct pnp_mem *mem;
  165. if (dep) {
  166. switch (option->priority) {
  167. case PNP_RES_PRIORITY_PREFERRED:
  168. s = "preferred";
  169. break;
  170. case PNP_RES_PRIORITY_ACCEPTABLE:
  171. s = "acceptable";
  172. break;
  173. case PNP_RES_PRIORITY_FUNCTIONAL:
  174. s = "functional";
  175. break;
  176. default:
  177. s = "invalid";
  178. }
  179. pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s);
  180. }
  181. for (port = option->port; port; port = port->next)
  182. pnp_print_port(buffer, space, port);
  183. for (irq = option->irq; irq; irq = irq->next)
  184. pnp_print_irq(buffer, space, irq);
  185. for (dma = option->dma; dma; dma = dma->next)
  186. pnp_print_dma(buffer, space, dma);
  187. for (mem = option->mem; mem; mem = mem->next)
  188. pnp_print_mem(buffer, space, mem);
  189. }
  190. static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *attr, char *buf)
  191. {
  192. struct pnp_dev *dev = to_pnp_dev(dmdev);
  193. struct pnp_option * independent = dev->independent;
  194. struct pnp_option * dependent = dev->dependent;
  195. int ret, dep = 1;
  196. pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
  197. pnp_alloc(sizeof(pnp_info_buffer_t));
  198. if (!buffer)
  199. return -ENOMEM;
  200. buffer->len = PAGE_SIZE;
  201. buffer->buffer = buf;
  202. buffer->curr = buffer->buffer;
  203. if (independent)
  204. pnp_print_option(buffer, "", independent, 0);
  205. while (dependent){
  206. pnp_print_option(buffer, " ", dependent, dep);
  207. dependent = dependent->next;
  208. dep++;
  209. }
  210. ret = (buffer->curr - buf);
  211. kfree(buffer);
  212. return ret;
  213. }
  214. static DEVICE_ATTR(options,S_IRUGO,pnp_show_options,NULL);
  215. static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_attribute *attr, char *buf)
  216. {
  217. struct pnp_dev *dev = to_pnp_dev(dmdev);
  218. int i, ret;
  219. pnp_info_buffer_t *buffer;
  220. if (!dev)
  221. return -EINVAL;
  222. buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
  223. if (!buffer)
  224. return -ENOMEM;
  225. buffer->len = PAGE_SIZE;
  226. buffer->buffer = buf;
  227. buffer->curr = buffer->buffer;
  228. pnp_printf(buffer,"state = ");
  229. if (dev->active)
  230. pnp_printf(buffer,"active\n");
  231. else
  232. pnp_printf(buffer,"disabled\n");
  233. for (i = 0; i < PNP_MAX_PORT; i++) {
  234. if (pnp_port_valid(dev, i)) {
  235. pnp_printf(buffer,"io");
  236. if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
  237. pnp_printf(buffer," disabled\n");
  238. else
  239. pnp_printf(buffer," 0x%lx-0x%lx\n",
  240. pnp_port_start(dev, i),
  241. pnp_port_end(dev, i));
  242. }
  243. }
  244. for (i = 0; i < PNP_MAX_MEM; i++) {
  245. if (pnp_mem_valid(dev, i)) {
  246. pnp_printf(buffer,"mem");
  247. if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
  248. pnp_printf(buffer," disabled\n");
  249. else
  250. pnp_printf(buffer," 0x%lx-0x%lx\n",
  251. pnp_mem_start(dev, i),
  252. pnp_mem_end(dev, i));
  253. }
  254. }
  255. for (i = 0; i < PNP_MAX_IRQ; i++) {
  256. if (pnp_irq_valid(dev, i)) {
  257. pnp_printf(buffer,"irq");
  258. if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
  259. pnp_printf(buffer," disabled\n");
  260. else
  261. pnp_printf(buffer," %ld\n",
  262. pnp_irq(dev, i));
  263. }
  264. }
  265. for (i = 0; i < PNP_MAX_DMA; i++) {
  266. if (pnp_dma_valid(dev, i)) {
  267. pnp_printf(buffer,"dma");
  268. if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
  269. pnp_printf(buffer," disabled\n");
  270. else
  271. pnp_printf(buffer," %ld\n",
  272. pnp_dma(dev, i));
  273. }
  274. }
  275. ret = (buffer->curr - buf);
  276. kfree(buffer);
  277. return ret;
  278. }
  279. extern struct semaphore pnp_res_mutex;
  280. static ssize_t
  281. pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, const char * ubuf, size_t count)
  282. {
  283. struct pnp_dev *dev = to_pnp_dev(dmdev);
  284. char *buf = (void *)ubuf;
  285. int retval = 0;
  286. if (dev->status & PNP_ATTACHED) {
  287. retval = -EBUSY;
  288. pnp_info("Device %s cannot be configured because it is in use.", dev->dev.bus_id);
  289. goto done;
  290. }
  291. while (isspace(*buf))
  292. ++buf;
  293. if (!strnicmp(buf,"disable",7)) {
  294. retval = pnp_disable_dev(dev);
  295. goto done;
  296. }
  297. if (!strnicmp(buf,"activate",8)) {
  298. retval = pnp_activate_dev(dev);
  299. goto done;
  300. }
  301. if (!strnicmp(buf,"fill",4)) {
  302. if (dev->active)
  303. goto done;
  304. retval = pnp_auto_config_dev(dev);
  305. goto done;
  306. }
  307. if (!strnicmp(buf,"auto",4)) {
  308. if (dev->active)
  309. goto done;
  310. pnp_init_resource_table(&dev->res);
  311. retval = pnp_auto_config_dev(dev);
  312. goto done;
  313. }
  314. if (!strnicmp(buf,"clear",5)) {
  315. if (dev->active)
  316. goto done;
  317. pnp_init_resource_table(&dev->res);
  318. goto done;
  319. }
  320. if (!strnicmp(buf,"get",3)) {
  321. down(&pnp_res_mutex);
  322. if (pnp_can_read(dev))
  323. dev->protocol->get(dev, &dev->res);
  324. up(&pnp_res_mutex);
  325. goto done;
  326. }
  327. if (!strnicmp(buf,"set",3)) {
  328. int nport = 0, nmem = 0, nirq = 0, ndma = 0;
  329. if (dev->active)
  330. goto done;
  331. buf += 3;
  332. pnp_init_resource_table(&dev->res);
  333. down(&pnp_res_mutex);
  334. while (1) {
  335. while (isspace(*buf))
  336. ++buf;
  337. if (!strnicmp(buf,"io",2)) {
  338. buf += 2;
  339. while (isspace(*buf))
  340. ++buf;
  341. dev->res.port_resource[nport].start = simple_strtoul(buf,&buf,0);
  342. while (isspace(*buf))
  343. ++buf;
  344. if(*buf == '-') {
  345. buf += 1;
  346. while (isspace(*buf))
  347. ++buf;
  348. dev->res.port_resource[nport].end = simple_strtoul(buf,&buf,0);
  349. } else
  350. dev->res.port_resource[nport].end = dev->res.port_resource[nport].start;
  351. dev->res.port_resource[nport].flags = IORESOURCE_IO;
  352. nport++;
  353. if (nport >= PNP_MAX_PORT)
  354. break;
  355. continue;
  356. }
  357. if (!strnicmp(buf,"mem",3)) {
  358. buf += 3;
  359. while (isspace(*buf))
  360. ++buf;
  361. dev->res.mem_resource[nmem].start = simple_strtoul(buf,&buf,0);
  362. while (isspace(*buf))
  363. ++buf;
  364. if(*buf == '-') {
  365. buf += 1;
  366. while (isspace(*buf))
  367. ++buf;
  368. dev->res.mem_resource[nmem].end = simple_strtoul(buf,&buf,0);
  369. } else
  370. dev->res.mem_resource[nmem].end = dev->res.mem_resource[nmem].start;
  371. dev->res.mem_resource[nmem].flags = IORESOURCE_MEM;
  372. nmem++;
  373. if (nmem >= PNP_MAX_MEM)
  374. break;
  375. continue;
  376. }
  377. if (!strnicmp(buf,"irq",3)) {
  378. buf += 3;
  379. while (isspace(*buf))
  380. ++buf;
  381. dev->res.irq_resource[nirq].start =
  382. dev->res.irq_resource[nirq].end = simple_strtoul(buf,&buf,0);
  383. dev->res.irq_resource[nirq].flags = IORESOURCE_IRQ;
  384. nirq++;
  385. if (nirq >= PNP_MAX_IRQ)
  386. break;
  387. continue;
  388. }
  389. if (!strnicmp(buf,"dma",3)) {
  390. buf += 3;
  391. while (isspace(*buf))
  392. ++buf;
  393. dev->res.dma_resource[ndma].start =
  394. dev->res.dma_resource[ndma].end = simple_strtoul(buf,&buf,0);
  395. dev->res.dma_resource[ndma].flags = IORESOURCE_DMA;
  396. ndma++;
  397. if (ndma >= PNP_MAX_DMA)
  398. break;
  399. continue;
  400. }
  401. break;
  402. }
  403. up(&pnp_res_mutex);
  404. goto done;
  405. }
  406. done:
  407. if (retval < 0)
  408. return retval;
  409. return count;
  410. }
  411. static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR,
  412. pnp_show_current_resources,pnp_set_current_resources);
  413. static ssize_t pnp_show_current_ids(struct device *dmdev, struct device_attribute *attr, char *buf)
  414. {
  415. char *str = buf;
  416. struct pnp_dev *dev = to_pnp_dev(dmdev);
  417. struct pnp_id * pos = dev->id;
  418. while (pos) {
  419. str += sprintf(str,"%s\n", pos->id);
  420. pos = pos->next;
  421. }
  422. return (str - buf);
  423. }
  424. static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL);
  425. int pnp_interface_attach_device(struct pnp_dev *dev)
  426. {
  427. device_create_file(&dev->dev,&dev_attr_options);
  428. device_create_file(&dev->dev,&dev_attr_resources);
  429. device_create_file(&dev->dev,&dev_attr_id);
  430. return 0;
  431. }