Message ID | 58bba4310da4c29b068345a4b36af8a531397ff7.1605847196.git.fthain@telegraphics.com.au (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | macintosh/adb-iop: Send correct poll command | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch powerpc/merge (9d1aa2f025c6cc516125c42c70f6a9ce087c49ea) |
snowpatch_ozlabs/build-ppc64le | success | Build succeeded |
snowpatch_ozlabs/build-ppc64be | success | Build succeeded |
snowpatch_ozlabs/build-ppc64e | success | Build succeeded |
snowpatch_ozlabs/build-pmac32 | success | Build succeeded |
snowpatch_ozlabs/checkpatch | warning | total: 0 errors, 1 warnings, 0 checks, 77 lines checked |
snowpatch_ozlabs/needsstable | fail |
Hi Finn, On Fri, Nov 20, 2020 at 5:54 AM Finn Thain <fthain@telegraphics.com.au> wrote: > The behaviour of the IOP firmware is not well documented but we do know > that IOP message reply data can be used to issue new ADB commands. > Use the message reply to better control autopoll behaviour by sending > a Talk Register 0 command after every ADB response, not unlike the > algorithm in the via-macii driver. This poll command is addressed to > that device which last received a Talk command (explicit or otherwise). > > Cc: Joshua Thompson <funaho@jurai.org> > Fixes: fa3b5a9929fc ("macintosh/adb-iop: Implement idle -> sending state transition") WARNING: Unknown commit id 'fa3b5a9929fc', maybe rebased or not pulled? 32226e817043? > Tested-by: Stan Johnson <userm57@yahoo.com> > Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Thanks, will queue in the m68k for-v5.11 branch. Gr{oetje,eeting}s, Geert
On Fri, 4 Dec 2020, Geert Uytterhoeven wrote: > Hi Finn, > > On Fri, Nov 20, 2020 at 5:54 AM Finn Thain <fthain@telegraphics.com.au> wrote: > > The behaviour of the IOP firmware is not well documented but we do know > > that IOP message reply data can be used to issue new ADB commands. > > Use the message reply to better control autopoll behaviour by sending > > a Talk Register 0 command after every ADB response, not unlike the > > algorithm in the via-macii driver. This poll command is addressed to > > that device which last received a Talk command (explicit or otherwise). > > > > Cc: Joshua Thompson <funaho@jurai.org> > > Fixes: fa3b5a9929fc ("macintosh/adb-iop: Implement idle -> sending state transition") > > WARNING: Unknown commit id 'fa3b5a9929fc', maybe rebased or not pulled? > > 32226e817043? > Yes, that's the one. I accidentally gave a commit id from one of my backport branches. > > Tested-by: Stan Johnson <userm57@yahoo.com> > > Signed-off-by: Finn Thain <fthain@telegraphics.com.au> > > Thanks, will queue in the m68k for-v5.11 branch. > Thanks. > Gr{oetje,eeting}s, > > Geert > >
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index f3d1a460fbce..6b26b6a2c463 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -25,6 +25,7 @@ static struct adb_request *current_req; static struct adb_request *last_req; static unsigned int autopoll_devs; +static u8 autopoll_addr; static enum adb_iop_state { idle, @@ -41,6 +42,11 @@ static int adb_iop_autopoll(int); static void adb_iop_poll(void); static int adb_iop_reset_bus(void); +/* ADB command byte structure */ +#define ADDR_MASK 0xF0 +#define OP_MASK 0x0C +#define TALK 0x0C + struct adb_driver adb_iop_driver = { .name = "ISM IOP", .probe = adb_iop_probe, @@ -96,17 +102,24 @@ static void adb_iop_complete(struct iop_msg *msg) static void adb_iop_listen(struct iop_msg *msg) { struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message; + u8 addr = (amsg->cmd & ADDR_MASK) >> 4; + u8 op = amsg->cmd & OP_MASK; unsigned long flags; bool req_done = false; local_irq_save(flags); - /* Handle a timeout. Timeout packets seem to occur even after - * we've gotten a valid reply to a TALK, presumably because of - * autopolling. + /* Responses to Talk commands may be unsolicited as they are + * produced when the IOP polls devices. They are mostly timeouts. */ - - if (amsg->flags & ADB_IOP_EXPLICIT) { + if (op == TALK && ((1 << addr) & autopoll_devs)) + autopoll_addr = addr; + + switch (amsg->flags & (ADB_IOP_EXPLICIT | + ADB_IOP_AUTOPOLL | + ADB_IOP_TIMEOUT)) { + case ADB_IOP_EXPLICIT: + case ADB_IOP_EXPLICIT | ADB_IOP_TIMEOUT: if (adb_iop_state == awaiting_reply) { struct adb_request *req = current_req; @@ -115,12 +128,16 @@ static void adb_iop_listen(struct iop_msg *msg) req_done = true; } - } else if (!(amsg->flags & ADB_IOP_TIMEOUT)) { - adb_input(&amsg->cmd, amsg->count + 1, - amsg->flags & ADB_IOP_AUTOPOLL); + break; + case ADB_IOP_AUTOPOLL: + if (((1 << addr) & autopoll_devs) && + amsg->cmd == ADB_READREG(addr, 0)) + adb_input(&amsg->cmd, amsg->count + 1, 1); + break; } - - msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0; + msg->reply[0] = autopoll_addr ? ADB_IOP_AUTOPOLL : 0; + msg->reply[1] = 0; + msg->reply[2] = autopoll_addr ? ADB_READREG(autopoll_addr, 0) : 0; iop_complete_message(msg); if (req_done) @@ -233,6 +250,9 @@ 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]; + if (autopoll_devs & (1 << autopoll_addr)) + return; + autopoll_addr = autopoll_devs ? (ffs(autopoll_devs) - 1) : 0; } static int adb_iop_autopoll(int devs)