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