daisy.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * IEEE 1284.3 Parallel port daisy chain and multiplexor code
  3.  * 
  4.  * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version
  9.  * 2 of the License, or (at your option) any later version.
  10.  *
  11.  * ??-12-1998: Initial implementation.
  12.  * 31-01-1999: Make port-cloning transparent.
  13.  * 13-02-1999: Move DeviceID technique from parport_probe.
  14.  * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
  15.  * 22-02-2000: Count devices that are actually detected.
  16.  *
  17.  * Any part of this program may be used in documents licensed under
  18.  * the GNU Free Documentation License, Version 1.1 or any later version
  19.  * published by the Free Software Foundation.
  20.  */
  21. #include <linux/parport.h>
  22. #include <linux/delay.h>
  23. #include <asm/uaccess.h>
  24. #undef DEBUG /* undef me for production */
  25. #ifdef DEBUG
  26. #define DPRINTK(stuff...) printk (stuff)
  27. #else
  28. #define DPRINTK(stuff...)
  29. #endif
  30. static struct daisydev {
  31. struct daisydev *next;
  32. struct parport *port;
  33. int daisy;
  34. int devnum;
  35. } *topology = NULL;
  36. static int numdevs = 0;
  37. /* Forward-declaration of lower-level functions. */
  38. static int mux_present (struct parport *port);
  39. static int num_mux_ports (struct parport *port);
  40. static int select_port (struct parport *port);
  41. static int assign_addrs (struct parport *port);
  42. /* Add a device to the discovered topology. */
  43. static void add_dev (int devnum, struct parport *port, int daisy)
  44. {
  45. struct daisydev *newdev;
  46. newdev = kmalloc (sizeof (struct daisydev), GFP_KERNEL);
  47. if (newdev) {
  48. newdev->port = port;
  49. newdev->daisy = daisy;
  50. newdev->devnum = devnum;
  51. newdev->next = topology;
  52. if (!topology || topology->devnum >= devnum)
  53. topology = newdev;
  54. else {
  55. struct daisydev *prev = topology;
  56. while (prev->next && prev->next->devnum < devnum)
  57. prev = prev->next;
  58. newdev->next = prev->next;
  59. prev->next = newdev;
  60. }
  61. }
  62. }
  63. /* Clone a parport (actually, make an alias). */
  64. static struct parport *clone_parport (struct parport *real, int muxport)
  65. {
  66. struct parport *extra = parport_register_port (real->base,
  67.        real->irq,
  68.        real->dma,
  69.        real->ops);
  70. if (extra) {
  71. extra->portnum = real->portnum;
  72. extra->physport = real;
  73. extra->muxport = muxport;
  74. }
  75. return extra;
  76. }
  77. /* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains.
  78.  * Return value is number of devices actually detected. */
  79. int parport_daisy_init (struct parport *port)
  80. {
  81. int detected = 0;
  82. char *deviceid;
  83. static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
  84. int num_ports;
  85. int i;
  86. /* Because this is called before any other devices exist,
  87.  * we don't have to claim exclusive access.  */
  88. /* If mux present on normal port, need to create new
  89.  * parports for each extra port. */
  90. if (port->muxport < 0 && mux_present (port) &&
  91.     /* don't be fooled: a mux must have 2 or 4 ports. */
  92.     ((num_ports = num_mux_ports (port)) == 2 || num_ports == 4)) {
  93. /* Leave original as port zero. */
  94. port->muxport = 0;
  95. printk (KERN_INFO
  96. "%s: 1st (default) port of %d-way multiplexorn",
  97. port->name, num_ports);
  98. for (i = 1; i < num_ports; i++) {
  99. /* Clone the port. */
  100. struct parport *extra = clone_parport (port, i);
  101. if (!extra) {
  102. if (signal_pending (current))
  103. break;
  104. schedule ();
  105. continue;
  106. }
  107. printk (KERN_INFO
  108. "%s: %d%s port of %d-way multiplexor on %sn",
  109. extra->name, i + 1, th[i + 1], num_ports,
  110. port->name);
  111. /* Analyse that port too.  We won't recurse
  112.    forever because of the 'port->muxport < 0'
  113.    test above. */
  114. parport_announce_port (extra);
  115. }
  116. }
  117. if (port->muxport >= 0)
  118. select_port (port);
  119. parport_daisy_deselect_all (port);
  120. detected += assign_addrs (port);
  121. /* Count the potential legacy device at the end. */
  122. add_dev (numdevs++, port, -1);
  123. /* Find out the legacy device's IEEE 1284 device ID. */
  124. deviceid = kmalloc (1000, GFP_KERNEL);
  125. if (deviceid) {
  126. if (parport_device_id (numdevs - 1, deviceid, 1000) > 2)
  127. detected++;
  128. kfree (deviceid);
  129. }
  130. return detected;
  131. }
  132. /* Forget about devices on a physical port. */
  133. void parport_daisy_fini (struct parport *port)
  134. {
  135. struct daisydev *dev, *prev = topology;
  136. while (prev && prev->port == port) {
  137. topology = topology->next;
  138. kfree (prev);
  139. prev = topology;
  140. }
  141. while (prev) {
  142. dev = prev->next;
  143. if (dev && dev->port == port) {
  144. prev->next = dev->next;
  145. kfree (dev);
  146. }
  147. prev = prev->next;
  148. }
  149. /* Gaps in the numbering could be handled better.  How should
  150.            someone enumerate through all IEEE1284.3 devices in the
  151.            topology?. */
  152. if (!topology) numdevs = 0;
  153. return;
  154. }
  155. /**
  156.  * parport_open - find a device by canonical device number
  157.  * @devnum: canonical device number
  158.  * @name: name to associate with the device
  159.  * @pf: preemption callback
  160.  * @kf: kick callback
  161.  * @irqf: interrupt handler
  162.  * @flags: registration flags
  163.  * @handle: driver data
  164.  *
  165.  * This function is similar to parport_register_device(), except
  166.  * that it locates a device by its number rather than by the port
  167.  * it is attached to.  See parport_find_device() and
  168.  * parport_find_class().
  169.  *
  170.  * All parameters except for @devnum are the same as for
  171.  * parport_register_device().  The return value is the same as
  172.  * for parport_register_device().
  173.  **/
  174. struct pardevice *parport_open (int devnum, const char *name,
  175. int (*pf) (void *), void (*kf) (void *),
  176. void (*irqf) (int, void *, struct pt_regs *),
  177. int flags, void *handle)
  178. {
  179. struct parport *port = parport_enumerate ();
  180. struct pardevice *dev;
  181. int portnum;
  182. int muxnum;
  183. int daisynum;
  184. if (parport_device_coords (devnum,  &portnum, &muxnum, &daisynum))
  185. return NULL;
  186. while (port && ((port->portnum != portnum) ||
  187. (port->muxport != muxnum)))
  188. port = port->next;
  189. if (!port)
  190. /* No corresponding parport. */
  191. return NULL;
  192. dev = parport_register_device (port, name, pf, kf,
  193.        irqf, flags, handle);
  194. if (dev)
  195. dev->daisy = daisynum;
  196. /* Check that there really is a device to select. */
  197. if (daisynum >= 0) {
  198. int selected;
  199. parport_claim_or_block (dev);
  200. selected = port->daisy;
  201. parport_release (dev);
  202. if (selected != port->daisy) {
  203. /* No corresponding device. */
  204. parport_unregister_device (dev);
  205. return NULL;
  206. }
  207. }
  208. return dev;
  209. }
  210. /**
  211.  * parport_close - close a device opened with parport_open()
  212.  * @dev: device to close
  213.  *
  214.  * This is to parport_open() as parport_unregister_device() is to
  215.  * parport_register_device().
  216.  **/
  217. void parport_close (struct pardevice *dev)
  218. {
  219. parport_unregister_device (dev);
  220. }
  221. /**
  222.  * parport_device_num - convert device coordinates
  223.  * @parport: parallel port number
  224.  * @mux: multiplexor port number (-1 for no multiplexor)
  225.  * @daisy: daisy chain address (-1 for no daisy chain address)
  226.  *
  227.  * This tries to locate a device on the given parallel port,
  228.  * multiplexor port and daisy chain address, and returns its
  229.  * device number or -NXIO if no device with those coordinates
  230.  * exists.
  231.  **/
  232. int parport_device_num (int parport, int mux, int daisy)
  233. {
  234. struct daisydev *dev = topology;
  235. while (dev && dev->port->portnum != parport &&
  236.        dev->port->muxport != mux && dev->daisy != daisy)
  237. dev = dev->next;
  238. if (!dev)
  239. return -ENXIO;
  240. return dev->devnum;
  241. }
  242. /**
  243.  * parport_device_coords - convert canonical device number
  244.  * @devnum: device number
  245.  * @parport: pointer to storage for parallel port number
  246.  * @mux: pointer to storage for multiplexor port number
  247.  * @daisy: pointer to storage for daisy chain address
  248.  *
  249.  * This function converts a device number into its coordinates in
  250.  * terms of which parallel port in the system it is attached to,
  251.  * which multiplexor port it is attached to if there is a
  252.  * multiplexor on that port, and which daisy chain address it has
  253.  * if it is in a daisy chain.
  254.  *
  255.  * The caller must allocate storage for @parport, @mux, and
  256.  * @daisy.
  257.  *
  258.  * If there is no device with the specified device number, -ENXIO
  259.  * is returned.  Otherwise, the values pointed to by @parport,
  260.  * @mux, and @daisy are set to the coordinates of the device,
  261.  * with -1 for coordinates with no value.
  262.  *
  263.  * This function is not actually very useful, but this interface
  264.  * was suggested by IEEE 1284.3.
  265.  **/
  266. int parport_device_coords (int devnum, int *parport, int *mux, int *daisy)
  267. {
  268. struct daisydev *dev = topology;
  269. while (dev && dev->devnum != devnum)
  270. dev = dev->next;
  271. if (!dev)
  272. return -ENXIO;
  273. if (parport) *parport = dev->port->portnum;
  274. if (mux) *mux = dev->port->muxport;
  275. if (daisy) *daisy = dev->daisy;
  276. return 0;
  277. }
  278. /* Send a daisy-chain-style CPP command packet. */
  279. static int cpp_daisy (struct parport *port, int cmd)
  280. {
  281. unsigned char s;
  282. parport_data_forward (port);
  283. parport_write_data (port, 0xaa); udelay (2);
  284. parport_write_data (port, 0x55); udelay (2);
  285. parport_write_data (port, 0x00); udelay (2);
  286. parport_write_data (port, 0xff); udelay (2);
  287. s = parport_read_status (port) & (PARPORT_STATUS_BUSY
  288.   | PARPORT_STATUS_PAPEROUT
  289.   | PARPORT_STATUS_SELECT
  290.   | PARPORT_STATUS_ERROR);
  291. if (s != (PARPORT_STATUS_BUSY
  292.   | PARPORT_STATUS_PAPEROUT
  293.   | PARPORT_STATUS_SELECT
  294.   | PARPORT_STATUS_ERROR)) {
  295. DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)n",
  296.  port->name, s);
  297. return -ENXIO;
  298. }
  299. parport_write_data (port, 0x87); udelay (2);
  300. s = parport_read_status (port) & (PARPORT_STATUS_BUSY
  301.   | PARPORT_STATUS_PAPEROUT
  302.   | PARPORT_STATUS_SELECT
  303.   | PARPORT_STATUS_ERROR);
  304. if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
  305. DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)n",
  306.  port->name, s);
  307. return -ENXIO;
  308. }
  309. parport_write_data (port, 0x78); udelay (2);
  310. parport_write_data (port, cmd); udelay (2);
  311. parport_frob_control (port,
  312.       PARPORT_CONTROL_STROBE,
  313.       PARPORT_CONTROL_STROBE);
  314. udelay (1);
  315. parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
  316. udelay (1);
  317. s = parport_read_status (port);
  318. parport_write_data (port, 0xff); udelay (2);
  319. return s;
  320. }
  321. /* Send a mux-style CPP command packet. */
  322. static int cpp_mux (struct parport *port, int cmd)
  323. {
  324. unsigned char s;
  325. int rc;
  326. parport_data_forward (port);
  327. parport_write_data (port, 0xaa); udelay (2);
  328. parport_write_data (port, 0x55); udelay (2);
  329. parport_write_data (port, 0xf0); udelay (2);
  330. parport_write_data (port, 0x0f); udelay (2);
  331. parport_write_data (port, 0x52); udelay (2);
  332. parport_write_data (port, 0xad); udelay (2);
  333. parport_write_data (port, cmd); udelay (2);
  334. s = parport_read_status (port);
  335. if (!(s & PARPORT_STATUS_ACK)) {
  336. DPRINTK (KERN_DEBUG "%s: cpp_mux: aa55f00f52ad%02x(%02x)n",
  337.  port->name, cmd, s);
  338. return -EIO;
  339. }
  340. rc = (((s & PARPORT_STATUS_SELECT   ? 1 : 0) << 0) |
  341.       ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) |
  342.       ((s & PARPORT_STATUS_BUSY     ? 0 : 1) << 2) |
  343.       ((s & PARPORT_STATUS_ERROR    ? 0 : 1) << 3));
  344. return rc;
  345. }
  346. void parport_daisy_deselect_all (struct parport *port)
  347. {
  348. cpp_daisy (port, 0x30);
  349. }
  350. int parport_daisy_select (struct parport *port, int daisy, int mode)
  351. {
  352. /* mode is currently ignored. FIXME? */
  353. return cpp_daisy (port, 0xe0 + daisy) & PARPORT_STATUS_ERROR;
  354. }
  355. static int mux_present (struct parport *port)
  356. {
  357. return cpp_mux (port, 0x51) == 3;
  358. }
  359. static int num_mux_ports (struct parport *port)
  360. {
  361. return cpp_mux (port, 0x58);
  362. }
  363. static int select_port (struct parport *port)
  364. {
  365. int muxport = port->muxport;
  366. return cpp_mux (port, 0x60 + muxport) == muxport;
  367. }
  368. static int assign_addrs (struct parport *port)
  369. {
  370. unsigned char s, last_dev;
  371. unsigned char daisy;
  372. int thisdev = numdevs;
  373. int detected;
  374. char *deviceid;
  375. parport_data_forward (port);
  376. parport_write_data (port, 0xaa); udelay (2);
  377. parport_write_data (port, 0x55); udelay (2);
  378. parport_write_data (port, 0x00); udelay (2);
  379. parport_write_data (port, 0xff); udelay (2);
  380. s = parport_read_status (port) & (PARPORT_STATUS_BUSY
  381.   | PARPORT_STATUS_PAPEROUT
  382.   | PARPORT_STATUS_SELECT
  383.   | PARPORT_STATUS_ERROR);
  384. if (s != (PARPORT_STATUS_BUSY
  385.   | PARPORT_STATUS_PAPEROUT
  386.   | PARPORT_STATUS_SELECT
  387.   | PARPORT_STATUS_ERROR)) {
  388. DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)n",
  389.  port->name, s);
  390. return 0;
  391. }
  392. parport_write_data (port, 0x87); udelay (2);
  393. s = parport_read_status (port) & (PARPORT_STATUS_BUSY
  394.   | PARPORT_STATUS_PAPEROUT
  395.   | PARPORT_STATUS_SELECT
  396.   | PARPORT_STATUS_ERROR);
  397. if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
  398. DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)n",
  399.  port->name, s);
  400. return 0;
  401. }
  402. parport_write_data (port, 0x78); udelay (2);
  403. last_dev = 0; /* We've just been speaking to a device, so we
  404.  know there must be at least _one_ out there. */
  405. for (daisy = 0; daisy < 4; daisy++) {
  406. parport_write_data (port, daisy);
  407. udelay (2);
  408. parport_frob_control (port,
  409.       PARPORT_CONTROL_STROBE,
  410.       PARPORT_CONTROL_STROBE);
  411. udelay (1);
  412. parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
  413. udelay (1);
  414. if (last_dev)
  415. /* No more devices. */
  416. break;
  417. last_dev = !(parport_read_status (port)
  418.      & PARPORT_STATUS_BUSY);
  419. add_dev (numdevs++, port, daisy);
  420. }
  421. parport_write_data (port, 0xff); udelay (2);
  422. detected = numdevs - thisdev;
  423. DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devicesn", port->name,
  424.  detected);
  425. /* Ask the new devices to introduce themselves. */
  426. deviceid = kmalloc (1000, GFP_KERNEL);
  427. if (!deviceid) return 0;
  428. for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
  429. parport_device_id (thisdev, deviceid, 1000);
  430. kfree (deviceid);
  431. return detected;
  432. }
  433. /* Find a device with a particular manufacturer and model string,
  434.    starting from a given device number.  Like the PCI equivalent,
  435.    'from' itself is skipped. */
  436. /**
  437.  * parport_find_device - find a specific device
  438.  * @mfg: required manufacturer string
  439.  * @mdl: required model string
  440.  * @from: previous device number found in search, or %NULL for
  441.  *        new search
  442.  *
  443.  * This walks through the list of parallel port devices looking
  444.  * for a device whose 'MFG' string matches @mfg and whose 'MDL'
  445.  * string matches @mdl in their IEEE 1284 Device ID.
  446.  *
  447.  * When a device is found matching those requirements, its device
  448.  * number is returned; if there is no matching device, a negative
  449.  * value is returned.
  450.  *
  451.  * A new search it initiated by passing %NULL as the @from
  452.  * argument.  If @from is not %NULL, the search continues from
  453.  * that device.
  454.  **/
  455. int parport_find_device (const char *mfg, const char *mdl, int from)
  456. {
  457. struct daisydev *d = topology; /* sorted by devnum */
  458. /* Find where to start. */
  459. while (d && d->devnum <= from)
  460. d = d->next;
  461. /* Search. */
  462. while (d) {
  463. struct parport_device_info *info;
  464. info = &d->port->probe_info[1 + d->daisy];
  465. if ((!mfg || !strcmp (mfg, info->mfr)) &&
  466.     (!mdl || !strcmp (mdl, info->model)))
  467. break;
  468. d = d->next;
  469. }
  470. if (d)
  471. return d->devnum;
  472. return -1;
  473. }
  474. /**
  475.  * parport_find_class - find a device in a specified class
  476.  * @cls: required class
  477.  * @from: previous device number found in search, or %NULL for
  478.  *        new search
  479.  *
  480.  * This walks through the list of parallel port devices looking
  481.  * for a device whose 'CLS' string matches @cls in their IEEE
  482.  * 1284 Device ID.
  483.  *
  484.  * When a device is found matching those requirements, its device
  485.  * number is returned; if there is no matching device, a negative
  486.  * value is returned.
  487.  *
  488.  * A new search it initiated by passing %NULL as the @from
  489.  * argument.  If @from is not %NULL, the search continues from
  490.  * that device.
  491.  **/
  492. int parport_find_class (parport_device_class cls, int from)
  493. {
  494. struct daisydev *d = topology; /* sorted by devnum */
  495. /* Find where to start. */
  496. while (d && d->devnum <= from)
  497. d = d->next;
  498. /* Search. */
  499. while (d && d->port->probe_info[1 + d->daisy].class != cls)
  500. d = d->next;
  501. if (d)
  502. return d->devnum;
  503. return -1;
  504. }