1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/delay.h>
19#include <linux/init.h>
20#include <linux/proc_fs.h>
21
22#include <asm/bootinfo.h>
23#include <asm/macintosh.h>
24#include <asm/macints.h>
25#include <asm/mac_iop.h>
26#include <asm/mac_oss.h>
27#include <asm/adb_iop.h>
28
29#include <linux/adb.h>
30
31
32
33extern void iop_ism_irq(int, void *, struct pt_regs *);
34
35static struct adb_request *current_req;
36static struct adb_request *last_req;
37#if 0
38static unsigned char reply_buff[16];
39static unsigned char *reply_ptr;
40#endif
41
42static enum adb_iop_state {
43 idle,
44 sending,
45 awaiting_reply
46} adb_iop_state;
47
48static void adb_iop_start(void);
49static int adb_iop_probe(void);
50static int adb_iop_init(void);
51static int adb_iop_send_request(struct adb_request *, int);
52static int adb_iop_write(struct adb_request *);
53static int adb_iop_autopoll(int);
54static void adb_iop_poll(void);
55static int adb_iop_reset_bus(void);
56
57struct adb_driver adb_iop_driver = {
58 "ISM IOP",
59 adb_iop_probe,
60 adb_iop_init,
61 adb_iop_send_request,
62 adb_iop_autopoll,
63 adb_iop_poll,
64 adb_iop_reset_bus
65};
66
67static void adb_iop_end_req(struct adb_request *req, int state)
68{
69 req->complete = 1;
70 current_req = req->next;
71 if (req->done) (*req->done)(req);
72 adb_iop_state = state;
73}
74
75
76
77
78
79
80
81static void adb_iop_complete(struct iop_msg *msg, struct pt_regs *regs)
82{
83 struct adb_request *req;
84 uint flags;
85
86 save_flags(flags);
87 cli();
88
89 req = current_req;
90 if ((adb_iop_state == sending) && req && req->reply_expected) {
91 adb_iop_state = awaiting_reply;
92 }
93
94 restore_flags(flags);
95}
96
97
98
99
100
101
102
103
104static void adb_iop_listen(struct iop_msg *msg, struct pt_regs *regs)
105{
106 struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message;
107 struct adb_request *req;
108 uint flags;
109#ifdef DEBUG_ADB_IOP
110 int i;
111#endif
112
113 save_flags(flags);
114 cli();
115
116 req = current_req;
117
118#ifdef DEBUG_ADB_IOP
119 printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req,
120 (uint) amsg->count + 2, (uint) amsg->flags, (uint) amsg->cmd);
121 for (i = 0; i < amsg->count; i++)
122 printk(" %02X", (uint) amsg->data[i]);
123 printk("\n");
124#endif
125
126
127
128
129
130
131
132 if (amsg->flags & ADB_IOP_TIMEOUT) {
133 msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL;
134 msg->reply[1] = 0;
135 msg->reply[2] = 0;
136 if (req && (adb_iop_state != idle)) {
137 adb_iop_end_req(req, idle);
138 }
139 } else {
140
141
142
143 if ((adb_iop_state == awaiting_reply) &&
144 (amsg->flags & ADB_IOP_EXPLICIT)) {
145 req->reply_len = amsg->count + 1;
146 memcpy(req->reply, &amsg->cmd, req->reply_len);
147 } else {
148 adb_input(&amsg->cmd, amsg->count + 1, regs,
149 amsg->flags & ADB_IOP_AUTOPOLL);
150 }
151 memcpy(msg->reply, msg->message, IOP_MSG_LEN);
152 }
153 iop_complete_message(msg);
154 restore_flags(flags);
155}
156
157
158
159
160
161
162
163
164static void adb_iop_start(void)
165{
166 unsigned long flags;
167 struct adb_request *req;
168 struct adb_iopmsg amsg;
169#ifdef DEBUG_ADB_IOP
170 int i;
171#endif
172
173
174 req = current_req;
175 if (!req) return;
176
177 save_flags(flags);
178 cli();
179
180#ifdef DEBUG_ADB_IOP
181 printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes);
182 for (i = 0 ; i < req->nbytes ; i++)
183 printk(" %02X", (uint) req->data[i]);
184 printk("\n");
185#endif
186
187
188
189
190 amsg.flags = ADB_IOP_EXPLICIT;
191 amsg.count = req->nbytes - 2;
192
193
194
195 memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
196
197 req->sent = 1;
198 adb_iop_state = sending;
199 restore_flags(flags);
200
201
202
203
204 iop_send_message(ADB_IOP, ADB_CHAN, req,
205 sizeof(amsg), (__u8 *) &amsg, adb_iop_complete);
206}
207
208int adb_iop_probe(void)
209{
210 if (!iop_ism_present) return -ENODEV;
211 return 0;
212}
213
214int adb_iop_init(void)
215{
216 printk("adb: IOP ISM driver v0.4 for Unified ADB.\n");
217 iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
218 return 0;
219}
220
221int adb_iop_send_request(struct adb_request *req, int sync)
222{
223 int err;
224
225 err = adb_iop_write(req);
226 if (err) return err;
227
228 if (sync) {
229 while (!req->complete) adb_iop_poll();
230 }
231 return 0;
232}
233
234static int adb_iop_write(struct adb_request *req)
235{
236 unsigned long flags;
237
238 if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
239 req->complete = 1;
240 return -EINVAL;
241 }
242
243 save_flags(flags);
244 cli();
245
246 req->next = 0;
247 req->sent = 0;
248 req->complete = 0;
249 req->reply_len = 0;
250
251 if (current_req != 0) {
252 last_req->next = req;
253 last_req = req;
254 } else {
255 current_req = req;
256 last_req = req;
257 }
258
259 restore_flags(flags);
260 if (adb_iop_state == idle) adb_iop_start();
261 return 0;
262}
263
264int adb_iop_autopoll(int devs)
265{
266
267 return 0;
268}
269
270void adb_iop_poll(void)
271{
272 if (adb_iop_state == idle) adb_iop_start();
273 iop_ism_irq(0, (void *) ADB_IOP, NULL);
274}
275
276int adb_iop_reset_bus(void)
277{
278 struct adb_request req = {
279 .reply_expected = 0,
280 .nbytes = 2,
281 .data = { ADB_PACKET, 0 },
282 };
283
284 adb_iop_write(&req);
285 while (!req.complete) {
286 adb_iop_poll();
287 schedule();
288 }
289
290 return 0;
291}
292