home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lxapi32.zip / Linux / I2C / i2c-philips-par.c < prev    next >
C/C++ Source or Header  |  2002-04-26  |  8KB  |  309 lines

  1. /* ------------------------------------------------------------------------- */
  2. /* i2c-philips-par.c i2c-hw access for philips style parallel port adapters  */
  3. /* ------------------------------------------------------------------------- */
  4. /*   Copyright (C) 1995-2000 Simon G. Vogl
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             */
  19. /* ------------------------------------------------------------------------- */ 
  20.  
  21. /* With some changes from Ky÷sti MΣlkki <kmalkki@cc.hut.fi> and even
  22.    Frodo Looijaard <frodol@dds.nl> */
  23.  
  24. /* $Id: i2c-philips-par.c,v 1.2 2002/04/26 23:09:28 smilcke Exp $ */
  25.  
  26. #include <linux/kernel.h>
  27. #include <linux/ioport.h>
  28. #include <linux/module.h>
  29. #include <linux/init.h>
  30. #include <linux/stddef.h>
  31. #include <linux/parport.h>
  32.  
  33. #include <linux/i2c.h>
  34. #include <linux/i2c-algo-bit.h>
  35.  
  36. #ifndef __exit
  37. #define __exit __init
  38. #endif
  39.  
  40. static int type;
  41.  
  42. struct i2c_par
  43. {
  44.     struct pardevice *pdev;
  45.     struct i2c_adapter adapter;
  46.     struct i2c_algo_bit_data bit_lp_data;
  47.     struct i2c_par *next;
  48. };
  49.  
  50. static struct i2c_par *adapter_list;
  51.  
  52.  
  53. /* ----- global defines -----------------------------------------------    */
  54. #define DEB(x)        /* should be reasonable open, close &c.     */
  55. #define DEB2(x)     /* low level debugging - very slow         */
  56. #define DEBE(x)    x    /* error messages                 */
  57.  
  58. /* ----- printer port defines ------------------------------------------*/
  59.                     /* Pin Port  Inverted    name    */
  60. #define I2C_ON        0x20        /* 12 status N    paper        */
  61.                     /* ... only for phil. not used  */
  62. #define I2C_SDA        0x80        /*  9 data   N    data7        */
  63. #define I2C_SCL        0x08        /* 17 ctrl   N    dsel        */
  64.  
  65. #define I2C_SDAIN    0x80        /* 11 stat   Y    busy        */
  66. #define I2C_SCLIN    0x08        /* 15 stat   Y    enable        */
  67.  
  68. #define I2C_DMASK    0x7f
  69. #define I2C_CMASK    0xf7
  70.  
  71. /* ----- local functions ----------------------------------------------    */
  72.  
  73. static void bit_lp_setscl(void *data, int state)
  74. {
  75.     /*be cautious about state of the control register - 
  76.         touch only the one bit needed*/
  77.     if (state) {
  78.         parport_write_control((struct parport *) data,
  79.               parport_read_control((struct parport *) data)|I2C_SCL);
  80.     } else {
  81.         parport_write_control((struct parport *) data,
  82.               parport_read_control((struct parport *) data)&I2C_CMASK);
  83.     }
  84. }
  85.  
  86. static void bit_lp_setsda(void *data, int state)
  87. {
  88.     if (state) {
  89.         parport_write_data((struct parport *) data, I2C_DMASK);
  90.     } else {
  91.         parport_write_data((struct parport *) data, I2C_SDA);
  92.     }
  93. }
  94.  
  95. static int bit_lp_getscl(void *data)
  96. {
  97.     return parport_read_status((struct parport *) data) & I2C_SCLIN;
  98. }
  99.  
  100. static int bit_lp_getsda(void *data)
  101. {
  102.     return parport_read_status((struct parport *) data) & I2C_SDAIN;
  103. }
  104.  
  105. static void bit_lp_setscl2(void *data, int state)
  106. {
  107.     if (state) {
  108.         parport_write_data((struct parport *) data,
  109.               parport_read_data((struct parport *) data)|0x1);
  110.     } else {
  111.         parport_write_data((struct parport *) data,
  112.               parport_read_data((struct parport *) data)&0xfe);
  113.     }
  114. }
  115.  
  116. static void bit_lp_setsda2(void *data, int state)
  117. {
  118.     if (state) {
  119.         parport_write_data((struct parport *) data,
  120.               parport_read_data((struct parport *) data)|0x2);
  121.     } else {
  122.         parport_write_data((struct parport *) data,
  123.               parport_read_data((struct parport *) data)&0xfd);
  124.     }
  125. }
  126.  
  127. static int bit_lp_getsda2(void *data)
  128. {
  129.     return (parport_read_status((struct parport *) data) & 
  130.                          PARPORT_STATUS_BUSY) ? 0 : 1;
  131. }
  132.  
  133. static int bit_lp_reg(struct i2c_client *client)
  134. {
  135.     return 0;
  136. }
  137.  
  138. static int bit_lp_unreg(struct i2c_client *client)
  139. {
  140.     return 0;
  141. }
  142.  
  143. static void bit_lp_inc_use(struct i2c_adapter *adap)
  144. {
  145.     MOD_INC_USE_COUNT;
  146. }
  147.  
  148. static void bit_lp_dec_use(struct i2c_adapter *adap)
  149. {
  150.     MOD_DEC_USE_COUNT;
  151. }
  152.  
  153. /* ------------------------------------------------------------------------
  154.  * Encapsulate the above functions in the correct operations structure.
  155.  * This is only done when more than one hardware adapter is supported.
  156.  */
  157.  
  158. static struct i2c_algo_bit_data bit_lp_data = {
  159.     NULL,
  160.     bit_lp_setsda,
  161.     bit_lp_setscl,
  162.     bit_lp_getsda,
  163.     bit_lp_getscl,
  164.     80, 80, 100,        /*    waits, timeout */
  165. }; 
  166.  
  167. static struct i2c_algo_bit_data bit_lp_data2 = {
  168.     NULL,
  169.     bit_lp_setsda2,
  170.     bit_lp_setscl2,
  171.     bit_lp_getsda2,
  172.     NULL,
  173.     80, 80, 100,        /*    waits, timeout */
  174. }; 
  175.  
  176. static struct i2c_adapter bit_lp_ops = {
  177.     "Philips Parallel port adapter",
  178.     I2C_HW_B_LP,
  179.     NULL,
  180.     NULL,
  181.     bit_lp_inc_use,
  182.     bit_lp_dec_use,
  183.     bit_lp_reg,
  184.  
  185.     bit_lp_unreg,
  186. };
  187.  
  188. static void i2c_parport_attach (struct parport *port)
  189. {
  190.     struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par),
  191.                       GFP_KERNEL);
  192.     if (!adapter) {
  193.         printk("i2c-philips-par: Unable to malloc.\n");
  194.         return;
  195.     }
  196.  
  197.     printk("i2c-philips-par.o: attaching to %s\n", port->name);
  198.  
  199.     adapter->pdev = parport_register_device(port, "i2c-philips-par",
  200.                         NULL, NULL, NULL, 
  201.                         PARPORT_FLAG_EXCL,
  202.                         NULL);
  203.     if (!adapter->pdev) {
  204.         printk("i2c-philips-par: Unable to register with parport.\n");
  205.         return;
  206.     }
  207.  
  208.     adapter->adapter = bit_lp_ops;
  209.     adapter->adapter.algo_data = &adapter->bit_lp_data;
  210.     adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data;
  211.     adapter->bit_lp_data.data = port;
  212.  
  213.     /* reset hardware to sane state */
  214.     parport_claim_or_block(adapter->pdev);
  215.     bit_lp_setsda(port, 1);
  216.     bit_lp_setscl(port, 1);
  217.     parport_release(adapter->pdev);
  218.  
  219.     if (i2c_bit_add_bus(&adapter->adapter) < 0)
  220.     {
  221.         printk("i2c-philips-par: Unable to register with I2C.\n");
  222.         parport_unregister_device(adapter->pdev);
  223.         kfree(adapter);
  224.         return;        /* No good */
  225.     }
  226.  
  227.     adapter->next = adapter_list;
  228.     adapter_list = adapter;
  229. }
  230.  
  231. static void i2c_parport_detach (struct parport *port)
  232. {
  233.     struct i2c_par *adapter, *prev = NULL;
  234.  
  235.     for (adapter = adapter_list; adapter; adapter = adapter->next)
  236.     {
  237.         if (adapter->pdev->port == port)
  238.         {
  239.             parport_unregister_device(adapter->pdev);
  240.             i2c_bit_del_bus(&adapter->adapter);
  241.             if (prev)
  242.                 prev->next = adapter->next;
  243.             else
  244.                 adapter_list = adapter->next;
  245.             kfree(adapter);
  246.             return;
  247.         }
  248.         prev = adapter;
  249.     }
  250. }
  251.  
  252.  
  253. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
  254. static struct parport_driver i2c_driver = {
  255.     "i2c-philips-par",
  256.     i2c_parport_attach,
  257.     i2c_parport_detach,
  258.     NULL
  259. };
  260. #endif
  261.  
  262. int __init i2c_bitlp_init(void)
  263. {
  264. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,4)
  265.     struct parport *port;
  266. #endif
  267.     printk("i2c-philips-par.o: i2c Philips parallel port adapter module\n");
  268.  
  269. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
  270.     parport_register_driver(&i2c_driver);
  271. #else
  272.     for (port = parport_enumerate(); port; port=port->next)
  273.         i2c_parport_attach(port);
  274. #endif
  275.     
  276.     return 0;
  277. }
  278.  
  279. void __exit i2c_bitlp_exit(void)
  280. {
  281. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
  282.     parport_unregister_driver(&i2c_driver);
  283. #else
  284.     struct parport *port;
  285.     for (port = parport_enumerate(); port; port=port->next)
  286.         i2c_parport_detach(port);
  287. #endif
  288. }
  289.  
  290. EXPORT_NO_SYMBOLS;
  291.  
  292. MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
  293. MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter");
  294. MODULE_LICENSE("GPL");
  295.  
  296. MODULE_PARM(type, "i");
  297.  
  298. #ifdef MODULE
  299. int init_module(void)
  300. {
  301.     return i2c_bitlp_init();
  302. }
  303.  
  304. void cleanup_module(void)
  305. {
  306.     i2c_bitlp_exit();
  307. }
  308. #endif
  309.