xref: /linux/drivers/macintosh/adb-iop.c (revision 92178fcabbcd39fc9ccd4e58ec4be83dd5323a46)
1 /*
2  * I/O Processor (IOP) ADB Driver
3  * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
4  * Based on via-cuda.c by Paul Mackerras.
5  *
6  * 1999-07-01 (jmt) - First implementation for new driver architecture.
7  *
8  * 1999-07-31 (jmt) - First working version.
9  *
10  * TODO:
11  *
12  * o Implement SRQ handling.
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/macintosh.h>
23 #include <asm/macints.h>
24 #include <asm/mac_iop.h>
25 #include <asm/mac_oss.h>
26 #include <asm/adb_iop.h>
27 
28 #include <linux/adb.h>
29 
30 /*#define DEBUG_ADB_IOP*/
31 
32 static struct adb_request *current_req;
33 static struct adb_request *last_req;
34 #if 0
35 static unsigned char reply_buff[16];
36 static unsigned char *reply_ptr;
37 #endif
38 
39 static enum adb_iop_state {
40     idle,
41     sending,
42     awaiting_reply
43 } adb_iop_state;
44 
45 static void adb_iop_start(void);
46 static int adb_iop_probe(void);
47 static int adb_iop_init(void);
48 static int adb_iop_send_request(struct adb_request *, int);
49 static int adb_iop_write(struct adb_request *);
50 static int adb_iop_autopoll(int);
51 static void adb_iop_poll(void);
52 static int adb_iop_reset_bus(void);
53 
54 struct adb_driver adb_iop_driver = {
55 	"ISM IOP",
56 	adb_iop_probe,
57 	adb_iop_init,
58 	adb_iop_send_request,
59 	adb_iop_autopoll,
60 	adb_iop_poll,
61 	adb_iop_reset_bus
62 };
63 
64 static void adb_iop_end_req(struct adb_request *req, int state)
65 {
66 	req->complete = 1;
67 	current_req = req->next;
68 	if (req->done) (*req->done)(req);
69 	adb_iop_state = state;
70 }
71 
72 /*
73  * Completion routine for ADB commands sent to the IOP.
74  *
75  * This will be called when a packet has been successfully sent.
76  */
77 
78 static void adb_iop_complete(struct iop_msg *msg)
79 {
80 	struct adb_request *req;
81 	unsigned long flags;
82 
83 	local_irq_save(flags);
84 
85 	req = current_req;
86 	if ((adb_iop_state == sending) && req && req->reply_expected) {
87 		adb_iop_state = awaiting_reply;
88 	}
89 
90 	local_irq_restore(flags);
91 }
92 
93 /*
94  * Listen for ADB messages from the IOP.
95  *
96  * This will be called when unsolicited messages (usually replies to TALK
97  * commands or autopoll packets) are received.
98  */
99 
100 static void adb_iop_listen(struct iop_msg *msg)
101 {
102 	struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message;
103 	struct adb_request *req;
104 	unsigned long flags;
105 #ifdef DEBUG_ADB_IOP
106 	int i;
107 #endif
108 
109 	local_irq_save(flags);
110 
111 	req = current_req;
112 
113 #ifdef DEBUG_ADB_IOP
114 	printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req,
115 		(uint) amsg->count + 2, (uint) amsg->flags, (uint) amsg->cmd);
116 	for (i = 0; i < amsg->count; i++)
117 		printk(" %02X", (uint) amsg->data[i]);
118 	printk("\n");
119 #endif
120 
121 	/* Handle a timeout. Timeout packets seem to occur even after */
122 	/* we've gotten a valid reply to a TALK, so I'm assuming that */
123 	/* a "timeout" is actually more like an "end-of-data" signal. */
124 	/* We need to send back a timeout packet to the IOP to shut   */
125 	/* it up, plus complete the current request, if any.          */
126 
127 	if (amsg->flags & ADB_IOP_TIMEOUT) {
128 		msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL;
129 		msg->reply[1] = 0;
130 		msg->reply[2] = 0;
131 		if (req && (adb_iop_state != idle)) {
132 			adb_iop_end_req(req, idle);
133 		}
134 	} else {
135 		/* TODO: is it possible for more than one chunk of data  */
136 		/*       to arrive before the timeout? If so we need to */
137 		/*       use reply_ptr here like the other drivers do.  */
138 		if ((adb_iop_state == awaiting_reply) &&
139 		    (amsg->flags & ADB_IOP_EXPLICIT)) {
140 			req->reply_len = amsg->count + 1;
141 			memcpy(req->reply, &amsg->cmd, req->reply_len);
142 		} else {
143 			adb_input(&amsg->cmd, amsg->count + 1,
144 				  amsg->flags & ADB_IOP_AUTOPOLL);
145 		}
146 		memcpy(msg->reply, msg->message, IOP_MSG_LEN);
147 	}
148 	iop_complete_message(msg);
149 	local_irq_restore(flags);
150 }
151 
152 /*
153  * Start sending an ADB packet, IOP style
154  *
155  * There isn't much to do other than hand the packet over to the IOP
156  * after encapsulating it in an adb_iopmsg.
157  */
158 
159 static void adb_iop_start(void)
160 {
161 	unsigned long flags;
162 	struct adb_request *req;
163 	struct adb_iopmsg amsg;
164 #ifdef DEBUG_ADB_IOP
165 	int i;
166 #endif
167 
168 	/* get the packet to send */
169 	req = current_req;
170 	if (!req) return;
171 
172 	local_irq_save(flags);
173 
174 #ifdef DEBUG_ADB_IOP
175 	printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes);
176 	for (i = 0 ; i < req->nbytes ; i++)
177 		printk(" %02X", (uint) req->data[i]);
178 	printk("\n");
179 #endif
180 
181 	/* The IOP takes MacII-style packets, so */
182 	/* strip the initial ADB_PACKET byte.    */
183 
184 	amsg.flags = ADB_IOP_EXPLICIT;
185 	amsg.count = req->nbytes - 2;
186 
187 	/* amsg.data immediately follows amsg.cmd, effectively making */
188 	/* amsg.cmd a pointer to the beginning of a full ADB packet.  */
189 	memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
190 
191 	req->sent = 1;
192 	adb_iop_state = sending;
193 	local_irq_restore(flags);
194 
195 	/* Now send it. The IOP manager will call adb_iop_complete */
196 	/* when the packet has been sent.                          */
197 
198 	iop_send_message(ADB_IOP, ADB_CHAN, req,
199 			 sizeof(amsg), (__u8 *) &amsg, adb_iop_complete);
200 }
201 
202 int adb_iop_probe(void)
203 {
204 	if (!iop_ism_present) return -ENODEV;
205 	return 0;
206 }
207 
208 int adb_iop_init(void)
209 {
210 	printk("adb: IOP ISM driver v0.4 for Unified ADB.\n");
211 	iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
212 	return 0;
213 }
214 
215 int adb_iop_send_request(struct adb_request *req, int sync)
216 {
217 	int err;
218 
219 	err = adb_iop_write(req);
220 	if (err) return err;
221 
222 	if (sync) {
223 		while (!req->complete) adb_iop_poll();
224 	}
225 	return 0;
226 }
227 
228 static int adb_iop_write(struct adb_request *req)
229 {
230 	unsigned long flags;
231 
232 	if ((req->nbytes < 2) || (req->data[0] != ADB_PACKET)) {
233 		req->complete = 1;
234 		return -EINVAL;
235 	}
236 
237 	local_irq_save(flags);
238 
239 	req->next = NULL;
240 	req->sent = 0;
241 	req->complete = 0;
242 	req->reply_len = 0;
243 
244 	if (current_req != 0) {
245 		last_req->next = req;
246 		last_req = req;
247 	} else {
248 		current_req = req;
249 		last_req = req;
250 	}
251 
252 	local_irq_restore(flags);
253 	if (adb_iop_state == idle) adb_iop_start();
254 	return 0;
255 }
256 
257 int adb_iop_autopoll(int devs)
258 {
259 	/* TODO: how do we enable/disable autopoll? */
260 	return 0;
261 }
262 
263 void adb_iop_poll(void)
264 {
265 	if (adb_iop_state == idle) adb_iop_start();
266 	iop_ism_irq_poll(ADB_IOP);
267 }
268 
269 int adb_iop_reset_bus(void)
270 {
271 	struct adb_request req = {
272 		.reply_expected = 0,
273 		.nbytes = 2,
274 		.data = { ADB_PACKET, 0 },
275 	};
276 
277 	adb_iop_write(&req);
278 	while (!req.complete) {
279 		adb_iop_poll();
280 		schedule();
281 	}
282 
283 	return 0;
284 }
285