root/lm-sensors/trunk/i2c/old-code/pcf-lp.c @ 3

Revision 3, 6.6 KB (checked in by frodo, 15 years ago)

The basic directory structure for lmsensors2.

README.directories contains a description of the directories I created;

read it if you have questions about them.

doc/design is the design document I sent before through email.
doc/useful_addresses.html contains links to I2C, SMBus and sensors

information.

Note that we may have to change minor i2c things, like Makefiles; this
is why I put it in the archive too (we should, of course, send important
changes to Simon Vogl).

  • Property svn:eol-style set to native
Line 
1/* ------------------------------------------------------------------------- */
2/* pcf-lp.c i2c-hw access for PCF 8584 on bidir. parallel ports              */
3/* ------------------------------------------------------------------------- */
4/*
5-----.-.---....------..-.-.---.... Oh bugger! Hope it works this time......
6
7    Copyright (C) 1995-97 Simon G. Vogl
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
22/* ------------------------------------------------------------------------- */
23static char rcsid[] = "$Id: pcf-lp.c,v 1.1 1998/09/05 18:20:09 i2c Exp $";
24/*
25 * $Log: pcf-lp.c,v $
26 * Revision 1.1  1998/09/05 18:20:09  i2c
27 * Initial revision
28 *
29 * Revision 1.4  1998/01/20 10:01:29  i2c
30 * *** empty log message ***
31 *
32 * Revision 1.3  1997/06/15 14:21:37  i2c
33 * removed debugging messages
34 *
35 * Revision 1.2  1997/06/03 06:00:10  i2c
36 * first version that works
37 *
38 * Revision 1.2  1996/11/20 20:20:46  i2c
39 * first version for ISA bus.
40 *
41 * Revision 1.1  1996/11/17 11:00:03  i2c
42 * Initial revision
43 *
44 *
45 */
46
47#include <linux/kernel.h>
48#include <linux/delay.h>
49#include <linux/ioport.h>
50#include <asm/io.h>
51#include <linux/errno.h>
52
53#include "i2c.h"
54#include "i2c-priv.h"
55
56/* ----- global defines ----------------------------------------------- */
57#define DEB(x)          /* should be reasonable open, close &c.         */
58#define DEB2(x)         /* low level debugging - very slow              */
59#define DEBE(x) x       /* error messages                               */
60
61#define DEBHW(x) x      /* lowest level hardware debug -- log changes of*/
62                        /* the bit lines...                             */
63                       
64#define lpPort(port)    (i2c_table[minor].base+(port))
65
66
67/* ----- local variables ---------------------------------------------- */
68
69static unsigned char ctrl;                      /* remember line states */ 
70
71                                                /* (re)set line states  */
72#define Strobe(arg) if (!arg) ctrl|= 0x01; else ctrl &=!0x01;\
73                        outb_p(ctrl,lpPort(2))  /* Strobe -- pin 1      */
74#define AutoLF(arg) if (!arg) ctrl|= 0x02; else ctrl &=!0x02;\
75                        outb_p(ctrl,lpPort(2))  /* AutoLF -- pin 14     */
76#define Init(arg)   if ( arg) ctrl|= 0x04; else ctrl &=!0x04;\
77                        outb(ctrl,lpPort(2))    /* Init   -- pin 16     */
78#define Select(arg) if (!arg) ctrl|= 0x08; else ctrl &=!0x08;\
79                        outb_p(ctrl,lpPort(2))  /* Sel. in - pin 17     */
80                                                /* 0x10 -- Int Enable   */
81#define ReadBit(arg) if(arg) ctrl|= 0x20; else ctrl &=!0x20;\
82                        outb_p(ctrl,lpPort(2))  /* direction bit        */
83
84#define inStr() (! (0x01 & inb(lpPort(2)) ) )   /* Strobe -- pin 1      */
85#define inALF() (! (0x02 & inb(lpPort(2)) ) )   /* AutoLF -- pin 14     */
86#define inIni() (  (0x04 & inb(lpPort(2)) ) )   /* Init   -- pin 16     */
87#define inSel() (! (0x08 & inb(lpPort(2)) ) )   /* Sel. in - pin 17     */
88                                                /* 0x10 -- Int Enable   */
89/*                                             
90#define Argl() printk("(wr-%d cs-%d a0-%d  (%#2x, %#2x))\n", \
91                inStr(),inALF(),inIni(),inb(lpPort(0)),inb(lpPort(1)) )
92*/
93#define Argl() /**/
94
95#define wr(arg) Strobe(arg); Argl()             /* write line           */
96#define cs(arg) AutoLF(arg); Argl()             /* chip select          */
97#define a0(arg) Init  (arg); Argl()             /* address line         */
98       
99/* ----- local functions ---------------------------------------------- */
100/*
101#if (PCFADAPS) > 1
102#  define Local static
103#else
104#  define Local inline
105#endif
106*/
107#define Local /**/
108
109/* --------- okay, I borrowed it. Stays here for debugging.
110 * check the epp status. After a EPP transfer, it should be true that
111 * 1) the TIMEOUT bit (SPP_STR.0) is clear
112 * 2) the READY bit (SPP_STR.7) is set
113 * returns 1 if okay
114 */
115static int ex_ppa_check_epp_status(int minor)
116{
117        char r;
118        inb(STAT);
119        r = inb(STAT);
120
121        if (r & 1) {
122                outb(r, STAT);
123                outb(r&0xfe, STAT);
124                printk("timed out on port 0x%04x\n", BASE);
125                return 0;
126        }
127        if (!(r & 0x80)) {
128                return 0;
129        }
130        return 1;
131}
132
133
134Local   int  pcf_read (int minor, int adr)
135{
136        int ret;
137        a0(adr);
138        ex_ppa_check_epp_status(minor);
139        ret = inb(lpPort(4));
140        return ret;
141}
142
143
144Local   void pcf_write (int minor, int adr,char data)
145{
146        a0(adr);
147        ex_ppa_check_epp_status(minor);
148        outb(data,lpPort(4));
149}
150
151
152Local   int  pcf_init (int minor)
153{
154        char ctrl,ecr;                  /* parallel port registers      */
155
156        if (check_region(i2c_table[minor].base, 8) < 0 ) {
157                return -ENODEV; 
158        } else {
159                request_region(i2c_table[minor].base,  8, "i2c (pcf-lp)");
160        }
161
162        /* This is the standard detection algorithm for ECP ports       */
163        /* now detect, what kind of parallel port we have:              */
164        ecr = inb(i2c_table[minor].base+0x402);
165        ctrl= inb(i2c_table[minor].base+0x002);
166        if (ecr!=ctrl) {                /* Okay, we seem to have an extended port :)    */
167                if (check_region(i2c_table[minor].base + 0x400, 8) < 0 ) {
168                        DEBE(printk(    "i2c_init, port %#x: ext. ports already in use "
169                                "using only standard driver.\n",
170                                i2c_table[minor].base));
171                        return -ENODEV;
172                } else {
173                        if ( (ecr & 0x03) != 0x01 ) {   /* FIFO empty?  */
174                                printk("FIFO not empty\n");
175                                return -ENODEV; 
176                        }
177
178                        outb(0x34,i2c_table[minor].base+0x402);
179                        if (inb(i2c_table[minor].base+0x402) != 0x35 ){ /* bits 0,1 readonly    */
180                                printk("bits 0,1 not rd/only");
181                                return -ENODEV;
182                        }
183                        /* Okay, now we should have an ECP-capable printer port */
184                        printk("i2c%d: ECP parallel port.\n",minor);
185                        request_region(i2c_table[minor].base+0x0400, 3 , 
186                                "i2c (Extended Parallel port adapter)");
187                        outb(0x94 ,lpPort(0x402));      /* EPP mode     */
188                        ctrl = inb(CTRL);
189
190                        if (i2c_table[minor].irq > 0){  /* enable int.  */
191                                outb(inb(lpPort(0x402)|0x10), lpPort(0x402));
192                                outb(ctrl|0x10,CTRL);
193                        }
194                       
195                        ex_ppa_check_epp_status(minor);
196                        printk("status reads %2x\n",pcf_read(minor,1));
197                        ex_ppa_check_epp_status(minor);
198                        printk("data   reads %2x\n",pcf_read(minor,0));
199                }
200        } else {
201                printk("i2c%d: Need EPP port. Sorry.\n",minor);
202                return -ENODEV;
203        }
204        /* Okay, now it's time to init my data structures */
205       
206        return 0;
207}
208
209
210Local   void pcf_exit   (int minor)
211{
212        release_region( i2c_table[minor].base,  8 );
213        release_region( i2c_table[minor].base + 0x0400,  3 );
214}
215
216
217/* ------------------------------------------------------------------------
218 * Encapsulate the above functions in the correct operations structure.
219 * This is only done when more than one hardware adapter is supported.
220 */
221#if (PCFADAPS) > 1
222struct i2c_pcf_ops pcf_lp_ops = {
223        pcf_read,
224        pcf_write,
225        pcf_init,
226        pcf_exit
227};
228#endif
Note: See TracBrowser for help on using the browser.