summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2020-05-31 01:17:03 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2020-07-26 15:34:24 +0200
commitc66da95a39ec2bb95544c3def974d96e8c178f57 (patch)
treee3f8613c23c2a99c743b4b302872f73b0d011ab9 /drivers
parentmacintosh/adb-iop: Implement sending -> idle state transition (diff)
downloadlinux-c66da95a39ec2bb95544c3def974d96e8c178f57.tar.xz
linux-c66da95a39ec2bb95544c3def974d96e8c178f57.zip
macintosh/adb-iop: Implement SRQ autopolling
The adb_driver.autopoll method is needed during ADB bus scan and device address assignment. Implement this method so that the IOP's list of device addresses can be updated. When the list is empty, disable SRQ autopolling. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Tested-by: Stan Johnson <userm57@yahoo.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/0fb7fdcd99d7820bb27faf1f27f7f6f1923914ef.1590880623.git.fthain@telegraphics.com.au
Diffstat (limited to 'drivers')
-rw-r--r--drivers/macintosh/adb-iop.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index 8594e4f9a830..f3d1a460fbce 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -7,10 +7,6 @@
* 1999-07-01 (jmt) - First implementation for new driver architecture.
*
* 1999-07-31 (jmt) - First working version.
- *
- * TODO:
- *
- * o Implement SRQ handling.
*/
#include <linux/types.h>
@@ -28,6 +24,7 @@
static struct adb_request *current_req;
static struct adb_request *last_req;
+static unsigned int autopoll_devs;
static enum adb_iop_state {
idle,
@@ -123,7 +120,7 @@ static void adb_iop_listen(struct iop_msg *msg)
amsg->flags & ADB_IOP_AUTOPOLL);
}
- msg->reply[0] = ADB_IOP_AUTOPOLL;
+ msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0;
iop_complete_message(msg);
if (req_done)
@@ -231,9 +228,32 @@ static int adb_iop_write(struct adb_request *req)
return 0;
}
+static void adb_iop_set_ap_complete(struct iop_msg *msg)
+{
+ struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
+
+ autopoll_devs = (amsg->data[1] << 8) | amsg->data[0];
+}
+
static int adb_iop_autopoll(int devs)
{
- /* TODO: how do we enable/disable autopoll? */
+ struct adb_iopmsg amsg;
+ unsigned long flags;
+ unsigned int mask = (unsigned int)devs & 0xFFFE;
+
+ local_irq_save(flags);
+
+ amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0);
+ amsg.count = 2;
+ amsg.cmd = 0;
+ amsg.data[0] = mask & 0xFF;
+ amsg.data[1] = (mask >> 8) & 0xFF;
+
+ iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg,
+ adb_iop_set_ap_complete);
+
+ local_irq_restore(flags);
+
return 0;
}