]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/ec.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / ec.c
1 /*
2  * embedded controller (usually at ports 0x66/0x62)
3  */
4 #include        "u.h"
5 #include        "../port/lib.h"
6 #include        "mem.h"
7 #include        "dat.h"
8 #include        "fns.h"
9 #include        "io.h"
10 #include        "../port/error.h"
11
12 enum {
13         /* registers */
14         EC_SC   = 0,
15         EC_DATA,
16
17         /* Embedded Controller Status, EC_SC (R) */
18         OBF     = 1<<0,
19         IBF     = 1<<1,
20         CMD     = 1<<3,
21         BURST   = 1<<4,
22         SCI_EVT = 1<<5,
23         SMI_EVT = 1<<6,
24
25         /* Embedded Controller Command Set */
26         RD_EC   = 0x80,
27         WR_EC   = 0x81,
28         BE_EC   = 0x82,
29         BD_EC   = 0x83,
30         QR_EC   = 0x84,
31 };
32
33 static struct {
34         Lock;
35         int     init;
36         int     port[2];        /* EC_SC and EC_DATA */
37 } ec;
38
39 static uchar
40 ecrr(int reg)
41 {
42         return inb(ec.port[reg]);
43 }
44 static void
45 ecwr(int reg, uchar val)
46 {
47         outb(ec.port[reg], val);
48 }
49
50 static int
51 ecwait(uchar mask, uchar val)
52 {
53         int i, s;
54
55         s = 0;
56         for(i=0; i<1000; i++){
57                 s = ecrr(EC_SC);
58                 if((s & mask) == val)
59                         return 0;
60                 delay(1);
61         }
62         print("ec: wait timeout status=%x pc=%#p\n", s, getcallerpc(&mask));
63         return -1;
64 }
65
66 int
67 ecread(uchar addr)
68 {
69         int r;
70
71         r = -1;
72         lock(&ec);
73         if(!ec.init)
74                 goto out;
75         if(ecwait(IBF, 0))
76                 goto out;
77         ecwr(EC_SC, RD_EC);
78         if(ecwait(IBF, 0))
79                 goto out;
80         ecwr(EC_DATA, addr);
81         if(ecwait(OBF, OBF))
82                 goto out;
83         r = ecrr(EC_DATA);
84         ecwait(OBF, 0);
85 out:
86         unlock(&ec);
87         return r;
88 }
89
90 int
91 ecwrite(uchar addr, uchar val)
92 {
93         int r;
94
95         r = -1;
96         lock(&ec);
97         if(!ec.init)
98                 goto out;
99         if(ecwait(IBF, 0))
100                 goto out;
101         ecwr(EC_SC, WR_EC);
102         if(ecwait(IBF, 0))
103                 goto out;
104         ecwr(EC_DATA, addr);
105         if(ecwait(IBF, 0))
106                 goto out;
107         ecwr(EC_DATA, val);
108         if(ecwait(IBF, 0))
109                 goto out;
110         r = 0;
111 out:
112         unlock(&ec);
113         return r;
114 }
115
116 static long
117 ecarchread(Chan*, void *a, long n, vlong off)
118 {
119         int port, v;
120         uchar *p;
121
122         if(off < 0 || off >= 256)
123                 return 0;
124         if(off+n > 256)
125                 n = 256 - off;
126         p = a;
127         for(port = off; port < off+n; port++){
128                 if((v = ecread(port)) < 0)
129                         error(Eio);
130                 *p++ = v;
131         }
132         return n;
133 }
134
135 static long
136 ecarchwrite(Chan*, void *a, long n, vlong off)
137 {
138         int port;
139         uchar *p;
140
141         if(off < 0 || off+n > 256)
142                 error(Ebadarg);
143         p = a;
144         for(port = off; port < off+n; port++)
145                 if(ecwrite(port, *p++) < 0)
146                         error(Eio);
147         return n;
148 }
149
150 int
151 ecinit(int cmdport, int dataport)
152 {
153         print("ec: cmd %X, data %X\n", cmdport, dataport);
154
155         if(ioalloc(cmdport, 1, 0, "ec.sc") < 0){
156                 print("ec: cant allocate cmd port %X\n", cmdport);
157                 return -1;
158         }
159         if(ioalloc(dataport, 1, 0, "ec.data") < 0){
160                 print("ec: cant allocate data port %X\n", dataport);
161                 iofree(cmdport);
162                 return -1;
163         }
164
165         lock(&ec);
166         ec.port[EC_SC] = cmdport;
167         ec.port[EC_DATA] = dataport;
168         ec.init = 1;
169         unlock(&ec);
170
171         addarchfile("ec", 0660, ecarchread, ecarchwrite);
172
173         return 0;
174 }