root/drivers/macintosh/adb-iop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adb_iop_end_req
  2. adb_iop_complete
  3. adb_iop_listen
  4. adb_iop_start
  5. adb_iop_probe
  6. adb_iop_init
  7. adb_iop_send_request
  8. adb_iop_write
  9. adb_iop_autopoll
  10. adb_iop_poll
  11. adb_iop_reset_bus

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * I/O Processor (IOP) ADB Driver
   4  * Written and (C) 1999 by Joshua M. Thompson (funaho@jurai.org)
   5  * Based on via-cuda.c by Paul Mackerras.
   6  *
   7  * 1999-07-01 (jmt) - First implementation for new driver architecture.
   8  *
   9  * 1999-07-31 (jmt) - First working version.
  10  *
  11  * TODO:
  12  *
  13  * o Implement SRQ handling.
  14  */
  15 
  16 #include <linux/types.h>
  17 #include <linux/kernel.h>
  18 #include <linux/mm.h>
  19 #include <linux/delay.h>
  20 #include <linux/init.h>
  21 #include <linux/proc_fs.h>
  22 
  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 /*#define DEBUG_ADB_IOP*/
  32 
  33 static struct adb_request *current_req;
  34 static struct adb_request *last_req;
  35 #if 0
  36 static unsigned char reply_buff[16];
  37 static unsigned char *reply_ptr;
  38 #endif
  39 
  40 static enum adb_iop_state {
  41         idle,
  42         sending,
  43         awaiting_reply
  44 } adb_iop_state;
  45 
  46 static void adb_iop_start(void);
  47 static int adb_iop_probe(void);
  48 static int adb_iop_init(void);
  49 static int adb_iop_send_request(struct adb_request *, int);
  50 static int adb_iop_write(struct adb_request *);
  51 static int adb_iop_autopoll(int);
  52 static void adb_iop_poll(void);
  53 static int adb_iop_reset_bus(void);
  54 
  55 struct adb_driver adb_iop_driver = {
  56         .name         = "ISM IOP",
  57         .probe        = adb_iop_probe,
  58         .init         = adb_iop_init,
  59         .send_request = adb_iop_send_request,
  60         .autopoll     = adb_iop_autopoll,
  61         .poll         = adb_iop_poll,
  62         .reset_bus    = adb_iop_reset_bus
  63 };
  64 
  65 static void adb_iop_end_req(struct adb_request *req, int state)
  66 {
  67         req->complete = 1;
  68         current_req = req->next;
  69         if (req->done)
  70                 (*req->done)(req);
  71         adb_iop_state = state;
  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) {
  89                 adb_iop_state = awaiting_reply;
  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) {
 130                 msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL;
 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         }
 150         iop_complete_message(msg);
 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)
 173                 return;
 174 
 175         local_irq_save(flags);
 176 
 177 #ifdef DEBUG_ADB_IOP
 178         printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes);
 179         for (i = 0; i < req->nbytes; i++)
 180                 printk(" %02X", (uint)req->data[i]);
 181         printk("\n");
 182 #endif
 183 
 184         /* The IOP takes MacII-style packets, so */
 185         /* strip the initial ADB_PACKET byte.    */
 186 
 187         amsg.flags = ADB_IOP_EXPLICIT;
 188         amsg.count = req->nbytes - 2;
 189 
 190         /* amsg.data immediately follows amsg.cmd, effectively making */
 191         /* amsg.cmd a pointer to the beginning of a full ADB packet.  */
 192         memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1);
 193 
 194         req->sent = 1;
 195         adb_iop_state = sending;
 196         local_irq_restore(flags);
 197 
 198         /* Now send it. The IOP manager will call adb_iop_complete */
 199         /* when the packet has been sent.                          */
 200 
 201         iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg,
 202                          adb_iop_complete);
 203 }
 204 
 205 int adb_iop_probe(void)
 206 {
 207         if (!iop_ism_present)
 208                 return -ENODEV;
 209         return 0;
 210 }
 211 
 212 int adb_iop_init(void)
 213 {
 214         pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n");
 215         iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB");
 216         return 0;
 217 }
 218 
 219 int adb_iop_send_request(struct adb_request *req, int sync)
 220 {
 221         int err;
 222 
 223         err = adb_iop_write(req);
 224         if (err)
 225                 return err;
 226 
 227         if (sync) {
 228                 while (!req->complete)
 229                         adb_iop_poll();
 230         }
 231         return 0;
 232 }
 233 
 234 static 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         local_irq_save(flags);
 244 
 245         req->next = NULL;
 246         req->sent = 0;
 247         req->complete = 0;
 248         req->reply_len = 0;
 249 
 250         if (current_req != 0) {
 251                 last_req->next = req;
 252                 last_req = req;
 253         } else {
 254                 current_req = req;
 255                 last_req = req;
 256         }
 257 
 258         local_irq_restore(flags);
 259 
 260         if (adb_iop_state == idle)
 261                 adb_iop_start();
 262         return 0;
 263 }
 264 
 265 int adb_iop_autopoll(int devs)
 266 {
 267         /* TODO: how do we enable/disable autopoll? */
 268         return 0;
 269 }
 270 
 271 void adb_iop_poll(void)
 272 {
 273         if (adb_iop_state == idle)
 274                 adb_iop_start();
 275         iop_ism_irq_poll(ADB_IOP);
 276 }
 277 
 278 int adb_iop_reset_bus(void)
 279 {
 280         struct adb_request req = {
 281                 .reply_expected = 0,
 282                 .nbytes = 2,
 283                 .data = { ADB_PACKET, 0 },
 284         };
 285 
 286         adb_iop_write(&req);
 287         while (!req.complete) {
 288                 adb_iop_poll();
 289                 schedule();
 290         }
 291 
 292         return 0;
 293 }

/* [<][>][^][v][top][bottom][index][help] */