/* Send an ADB retransmit (Talk, appended to the request queue) */ static void macii_retransmit(int device) { static int in_retransmit = 0; static struct adb_request rt; unsigned long flags; if (in_retransmit) printk("macii_retransmit: double retransmit!\n"); in_retransmit++; adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1, ADB_READREG(device, 0)); save_flags(flags); cli(); if (current_req != NULL) { last_req->next = &rt; last_req = &rt; } else { current_req = &rt; last_req = &rt; } if (macii_state == idle) macii_start(); restore_flags(flags); in_retransmit--; }
/* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */ static void macii_queue_poll(void) { static int device = 0; static int in_poll=0; static struct adb_request req; unsigned long flags; if (in_poll) printk("macii_queue_poll: double poll!\n"); in_poll++; if (++device > 15) device = 1; adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1, ADB_READREG(device, 0)); save_flags(flags); cli(); req.next = current_req; current_req = &req; restore_flags(flags); macii_start(); in_poll--; }
/* XXX: move that to cuda ? */ int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask) { ADBDevice *d; int olen, i; uint8_t buf[1]; olen = 0; for(i = 0; i < s->nb_devices; i++) { if (s->poll_index >= s->nb_devices) s->poll_index = 0; d = s->devices[s->poll_index]; if ((1 << d->devaddr) & poll_mask) { buf[0] = ADB_READREG | (d->devaddr << 4); olen = adb_request(s, obuf + 1, buf, 1); /* if there is data, we poll again the same device */ if (olen > 0) { obuf[0] = buf[0]; olen++; break; } } s->poll_index++; } return olen; }
/* Reset the bus */ static int macii_reset_bus(void) { static struct adb_request req; /* Command = 0, Address = ignored */ adb_request(&req, NULL, 0, 1, ADB_BUSRESET); return 0; }
/* Try to change handler to new_id. Will return 1 if successful. */ static int try_handler_change(int address, int new_id) { struct adb_request req; if (adb_handler[address].handler_id == new_id) return 1; adb_request(&req, NULL, ADBREQ_SYNC, 3, ADB_WRITEREG(address, 3), address | 0x20, new_id); adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, ADB_READREG(address, 3)); if (req.reply_len < 2) return 0; if (req.reply[2] != new_id) return 0; adb_handler[address].handler_id = req.reply[2]; return 1; }
static int adb_scan_bus(void) { int i, highFree=0, noMovement; int devmask = 0; struct adb_request req; /* assumes adb_handler[] is all zeroes at this point */ for (i = 1; i < 16; i++) { /* see if there is anything at address i */ adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, (i << 4) | 0xf); if (req.reply_len > 1) /* one or more devices at this address */ adb_handler[i].original_address = i; else if (i > highFree) highFree = i; } /* Note we reset noMovement to 0 each time we move a device */ for (noMovement = 1; noMovement < 2 && highFree > 0; noMovement++) { for (i = 1; i < 16; i++) { if (adb_handler[i].original_address == 0) continue; /* * Send a "talk register 3" command to address i * to provoke a collision if there is more than * one device at this address. */ adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, (i << 4) | 0xf); /* * Move the device(s) which didn't detect a * collision to address `highFree'. Hopefully * this only moves one device. */ adb_request(&req, NULL, ADBREQ_SYNC, 3, (i<< 4) | 0xb, (highFree | 0x60), 0xfe); /* * See if anybody actually moved. This is suggested * by HW TechNote 01: * * http://developer.apple.com/technotes/hw/hw_01.html */ adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, (highFree << 4) | 0xf); if (req.reply_len <= 1) continue; /* * Test whether there are any device(s) left * at address i. */ adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, (i << 4) | 0xf); if (req.reply_len > 1) { /* * There are still one or more devices * left at address i. Register the one(s) * we moved to `highFree', and find a new * value for highFree. */ adb_handler[highFree].original_address = adb_handler[i].original_address; while (highFree > 0 && adb_handler[highFree].original_address) highFree--; if (highFree <= 0) break; noMovement = 0; } else { /* * No devices left at address i; move the * one(s) we moved to `highFree' back to i. */ adb_request(&req, NULL, ADBREQ_SYNC, 3, (highFree << 4) | 0xb, (i | 0x60), 0xfe); } } } /* Now fill in the handler_id field of the adb_handler entries. */ printk(KERN_DEBUG "adb devices:"); for (i = 1; i < 16; i++) { if (adb_handler[i].original_address == 0) continue; adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, (i << 4) | 0xf); adb_handler[i].handler_id = req.reply[2]; printk(" [%d]: %d %x", i, adb_handler[i].original_address, adb_handler[i].handler_id); devmask |= 1 << i; } printk("\n"); return devmask; }