ppc64: Don't set Kp bit on SLB
[openbios/afaerber.git] / drivers / adb_bus.c
blobd67d1f1a4a6f74f7f833abc5718a0bdb788a78b5
1 /*
3 * Open Hack'Ware BIOS ADB bus support, ported to OpenBIOS
5 * Copyright (c) 2005 Jocelyn Mayer
6 * Copyright (c) 2005 Stefan Reinauer
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License V2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
22 #include "config.h"
23 #include "libopenbios/bindings.h"
24 #include "libc/vsprintf.h"
26 #include "adb_bus.h"
27 #include "adb_kbd.h"
28 #include "adb_mouse.h"
30 DECLARE_UNNAMED_NODE( adb, INSTALL_OPEN, sizeof(int));
32 static void
33 adb_initialize (int *idx)
35 phandle_t ph=get_cur_dev();
37 push_str("adb");
38 fword("device-type");
40 set_property(ph, "compatible", "adb", 4);
41 set_int_property(ph, "#address-cells", 1);
42 set_int_property(ph, "#size-cells", 0);
45 static void
46 adb_open(int *idx)
48 RET(-1);
51 static void
52 adb_close(int *idx)
56 NODE_METHODS( adb ) = {
57 { NULL, adb_initialize },
58 { "open", adb_open },
59 { "close", adb_close },
62 adb_bus_t *adb_bus_new (void *host,
63 int (*req)(void *host, const uint8_t *snd_buf,
64 int len, uint8_t *rcv_buf))
66 adb_bus_t *new;
68 new = malloc(sizeof(adb_bus_t));
69 if (new == NULL)
70 return NULL;
71 new->host = host;
72 new->req = req;
74 return new;
77 /* Check and relocate all ADB devices as suggested in
78 * ADB_manager Apple documentation
81 int adb_bus_init (char *path, adb_bus_t *bus)
83 char buf[64];
84 uint8_t buffer[ADB_BUF_SIZE];
85 uint8_t adb_addresses[16] =
86 { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, };
87 adb_dev_t tmp_device, **cur;
88 int address;
89 int reloc = 0, next_free = 7;
90 int keep;
92 snprintf(buf, sizeof(buf), "%s/adb", path);
93 REGISTER_NAMED_NODE( adb, buf);
94 /* Reset the bus */
95 // ADB_DPRINTF("\n");
96 adb_reset(bus);
97 cur = &bus->devices;
98 memset(&tmp_device, 0, sizeof(adb_dev_t));
99 tmp_device.bus = bus;
100 for (address = 1; address < 8 && adb_addresses[reloc] > 0;) {
101 if (address == ADB_RES) {
102 /* Reserved */
103 address++;
104 continue;
106 //ADB_DPRINTF("Check device on ADB address %d\n", address);
107 tmp_device.addr = address;
108 switch (adb_reg_get(&tmp_device, 3, buffer)) {
109 case 0:
110 //ADB_DPRINTF("No device on ADB address %d\n", address);
111 /* Register this address as free */
112 if (adb_addresses[next_free] != 0)
113 adb_addresses[next_free++] = address;
114 /* Check next ADB address */
115 address++;
116 break;
117 case 2:
118 /* One device answered :
119 * make it available and relocate it to a free address
121 if (buffer[0] == ADB_CHADDR) {
122 /* device self test failed */
123 ADB_DPRINTF("device on ADB address %d self-test failed "
124 "%02x %02x %02x\n", address,
125 buffer[0], buffer[1], buffer[2]);
126 keep = 0;
127 } else {
128 //ADB_DPRINTF("device on ADB address %d self-test OK\n",
129 // address);
130 keep = 1;
132 ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n",
133 address, adb_addresses[reloc], reloc);
134 buffer[0] = ((buffer[0] & 0x40) & ~0x90) | adb_addresses[reloc];
135 if (keep == 1)
136 buffer[0] |= 0x20;
137 buffer[1] = ADB_CHADDR_NOCOLL;
138 if (adb_reg_set(&tmp_device, 3, buffer, 2) < 0) {
139 ADB_DPRINTF("ADB device relocation failed\n");
140 return -1;
142 if (keep == 1) {
143 *cur = malloc(sizeof(adb_dev_t));
144 if (*cur == NULL) {
145 return -1;
147 (*cur)->type = address;
148 (*cur)->bus = bus;
149 (*cur)->addr = adb_addresses[reloc++];
150 /* Flush buffers */
151 adb_flush(*cur);
152 switch ((*cur)->type) {
153 case ADB_PROTECT:
154 ADB_DPRINTF("Found one protected device\n");
155 break;
156 case ADB_KEYBD:
157 ADB_DPRINTF("Found one keyboard on address %d\n", address);
158 adb_kbd_new(buf, *cur);
159 break;
160 case ADB_MOUSE:
161 ADB_DPRINTF("Found one mouse on address %d\n", address);
162 adb_mouse_new(buf, *cur);
163 break;
164 case ADB_ABS:
165 ADB_DPRINTF("Found one absolute positioning device\n");
166 break;
167 case ADB_MODEM:
168 ADB_DPRINTF("Found one modem\n");
169 break;
170 case ADB_RES:
171 ADB_DPRINTF("Found one ADB res device\n");
172 break;
173 case ADB_MISC:
174 ADB_DPRINTF("Found one ADB misc device\n");
175 break;
177 cur = &((*cur)->next);
179 break;
180 case 1:
181 case 3 ... 7:
182 /* SHOULD NOT HAPPEN : register 3 is always two bytes long */
183 ADB_DPRINTF("Invalid returned len for ADB register 3\n");
184 return -1;
185 case -1:
186 /* ADB ERROR */
187 ADB_DPRINTF("error gettting ADB register 3\n");
188 return -1;
192 return 0;
195 int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg,
196 uint8_t *buf, int len)
198 uint8_t adb_send[ADB_BUF_SIZE], adb_rcv[ADB_BUF_SIZE];
200 //ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd, reg, len);
201 if (dev->bus == NULL || dev->bus->req == NULL) {
202 ADB_DPRINTF("ERROR: invalid bus !\n");
203 for (;;);
205 /* Sanity checks */
206 if (cmd != ADB_LISTEN && len != 0) {
207 /* No buffer transmitted but for LISTEN command */
208 ADB_DPRINTF("in buffer for cmd %d\n", cmd);
209 return -1;
211 if (cmd == ADB_LISTEN && ((len < 2 || len > 8) || buf == NULL)) {
212 /* Need a buffer with a regular register size for LISTEN command */
213 ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len);
214 return -1;
216 if ((cmd == ADB_TALK || cmd == ADB_LISTEN) && reg > 3) {
217 /* Need a valid register number for LISTEN and TALK commands */
218 ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd, reg);
219 return -1;
221 switch (cmd) {
222 case ADB_SEND_RESET:
223 adb_send[0] = ADB_SEND_RESET;
224 break;
225 case ADB_FLUSH:
226 adb_send[0] = (dev->addr << 4) | ADB_FLUSH;
227 break;
228 case ADB_LISTEN:
229 memcpy(adb_send + 1, buf, len);
230 /* No break here */
231 case ADB_TALK:
232 adb_send[0] = (dev->addr << 4) | cmd | reg;
233 break;
235 memset(adb_rcv, 0, ADB_BUF_SIZE);
236 len = (*dev->bus->req)(dev->bus->host, adb_send, len + 1, adb_rcv);
237 #ifdef DEBUG_ADB
238 //printk("%x %x %x %x\n", adb_rcv[0], adb_rcv[1], adb_rcv[2], adb_rcv[3]);
239 #endif
240 switch (len) {
241 case 0:
242 /* No data */
243 break;
244 case 2 ... 8:
245 /* Register transmitted */
246 if (buf != NULL)
247 memcpy(buf, adb_rcv, len);
248 break;
249 default:
250 /* Should never happen */
251 //ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd, len);
252 return -1;
254 //ADB_DPRINTF("retlen: %d\n", len);
256 return len;