/* Reset adb bus - how do we do this?? */ static int cuda_reset_adb_bus(void) { struct adb_request req; if ((via == NULL) || !cuda_fully_inited) return -ENXIO; cuda_request(&req, NULL, 2, ADB_PACKET, 0); /* maybe? */ while (!req.complete) cuda_poll(); return 0; }
/* Enable/disable autopolling */ static int cuda_adb_autopoll(int devs) { struct adb_request req; if ((via == NULL) || !cuda_fully_inited) return -ENXIO; cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0)); while (!req.complete) cuda_poll(); return 0; }
static int cuda_adb_send(void *cookie, int poll, int command, int len, uint8_t *data) { struct cuda_softc *sc = cookie; int i, s = 0; uint8_t packet[16]; /* construct an ADB command packet and send it */ packet[0] = CUDA_ADB; packet[1] = command; for (i = 0; i < len; i++) packet[i + 2] = data[i]; if (poll || cold) { s = splhigh(); cuda_poll(sc); } cuda_send(sc, poll, len + 2, packet); if (poll || cold) { cuda_poll(sc); splx(s); } return 0; }
static int cuda_send(void *cookie, int poll, int length, uint8_t *msg) { struct cuda_softc *sc = cookie; int s; DPRINTF("cuda_send %08x\n", (uint32_t)cookie); if (sc->sc_state == CUDA_NOTREADY) return -1; s = splhigh(); if ((sc->sc_state == CUDA_IDLE) /*&& ((cuda_read_reg(sc, vBufB) & vPB3) == vPB3)*/) { /* fine */ DPRINTF("chip is idle\n"); } else { DPRINTF("cuda state is %d\n", sc->sc_state); if (sc->sc_waiting == 0) { sc->sc_waiting = 1; } else { splx(s); return -1; } } sc->sc_error = 0; memcpy(sc->sc_out, msg, length); sc->sc_out_length = length; sc->sc_sent = 0; if (sc->sc_waiting != 1) { delay(150); sc->sc_state = CUDA_OUT; cuda_out(sc); cuda_write_reg(sc, vSR, sc->sc_out[0]); cuda_ack_off(sc); cuda_tip(sc); } sc->sc_waiting = 1; if (sc->sc_polling || poll || cold) { cuda_poll(sc); } splx(s); return 0; }
static void cuda_autopoll(void *cookie, int flag) { struct cuda_softc *sc = cookie; uint8_t cmd[] = {CUDA_PSEUDO, CMD_AUTOPOLL, (flag != 0)}; if (cmd[2] == sc->sc_autopoll) return; sc->sc_autopoll = -1; cuda_send(sc, 0, 3, cmd); while(sc->sc_autopoll == -1) { if (sc->sc_polling || cold) { cuda_poll(sc); } else tsleep(&sc->sc_todev, 0, "autopoll", 100); } }
static int cuda_send(void *cookie, int poll, int length, uint8_t *msg) { struct cuda_softc *sc = cookie; device_t dev = sc->sc_dev; struct cuda_packet *pkt; if (sc->sc_state == CUDA_NOTREADY) return (-1); mtx_lock(&sc->sc_mutex); pkt = STAILQ_FIRST(&sc->sc_freeq); if (pkt == NULL) { mtx_unlock(&sc->sc_mutex); return (-1); } pkt->len = length - 1; pkt->type = msg[0]; memcpy(pkt->data, &msg[1], pkt->len); STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q); STAILQ_INSERT_TAIL(&sc->sc_outq, pkt, pkt_q); /* * If we already are sending a packet, we should bail now that this * one has been added to the queue. */ if (sc->sc_waiting) { mtx_unlock(&sc->sc_mutex); return (0); } cuda_send_outbound(sc); mtx_unlock(&sc->sc_mutex); if (sc->sc_polling || poll || cold) cuda_poll(dev); return (0); }
/* Send an ADB command */ static int cuda_send_request(struct adb_request *req, int sync) { int i; if ((via == NULL) || !cuda_fully_inited) { req->complete = 1; return -ENXIO; } req->reply_expected = 1; i = cuda_write(req); if (i) return i; if (sync) { while (!req->complete) cuda_poll(); } return 0; }
int find_via_cuda(void) { int err; struct adb_request req; if (vias != 0) return 1; vias = find_devices("via-cuda"); if (vias == 0) return 0; if (vias->next != 0) printk(KERN_WARNING "Warning: only using 1st via-cuda\n"); #if 0 { int i; printk("find_via_cuda: node = %p, addrs =", vias->node); for (i = 0; i < vias->n_addrs; ++i) printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size); printk(", intrs ="); for (i = 0; i < vias->n_intrs; ++i) printk(" %x", vias->intrs[i].line); printk("\n"); } #endif if (vias->n_addrs != 1 || vias->n_intrs != 1) { printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n", vias->n_addrs, vias->n_intrs); if (vias->n_addrs < 1 || vias->n_intrs < 1) return 0; } via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000); cuda_state = idle; sys_ctrler = SYS_CTRLER_CUDA; err = cuda_init_via(); if (err) { printk(KERN_ERR "cuda_init_via() failed\n"); via = NULL; return 0; } /* Clear and enable interrupts, but only on PPC. On 68K it's done */ /* for us by the the main VIA driver in arch/m68k/mac/via.c */ #ifndef CONFIG_MAC via[IFR] = 0x7f; eieio(); /* clear interrupts by writing 1s */ via[IER] = IER_SET|SR_INT; eieio(); /* enable interrupt from SR */ #endif /* enable autopoll */ cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); while (!req.complete) cuda_poll(); return 1; }
static int cuda_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *_send, size_t send_len, void *_recv, size_t recv_len, int flags) { struct cuda_softc *sc = cookie; const uint8_t *send = _send; uint8_t *recv = _recv; uint8_t command[16] = {CUDA_PSEUDO, CMD_IIC}; DPRINTF("cuda_i2c_exec(%02x)\n", addr); command[2] = addr; memcpy(&command[3], send, min((int)send_len, 12)); sc->sc_iic_done = 0; cuda_send(sc, sc->sc_polling, send_len + 3, command); while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) { if (sc->sc_polling || cold) { cuda_poll(sc); } else tsleep(&sc->sc_todev, 0, "i2c", 1000); } if (sc->sc_error) { sc->sc_error = 0; return -1; } /* see if we're supposed to do a read */ if (recv_len > 0) { sc->sc_iic_done = 0; command[2] |= 1; command[3] = 0; /* * XXX we need to do something to limit the size of the answer * - apparently the chip keeps sending until we tell it to stop */ sc->sc_i2c_read_len = recv_len; DPRINTF("rcv_len: %d\n", recv_len); cuda_send(sc, sc->sc_polling, 3, command); while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) { if (sc->sc_polling || cold) { cuda_poll(sc); } else tsleep(&sc->sc_todev, 0, "i2c", 1000); } if (sc->sc_error) { printf("error trying to read\n"); sc->sc_error = 0; return -1; } } DPRINTF("received: %d\n", sc->sc_iic_done); if ((sc->sc_iic_done > 3) && (recv_len > 0)) { int rlen; /* we got an answer */ rlen = min(sc->sc_iic_done - 3, recv_len); memcpy(recv, &sc->sc_in[4], rlen); #ifdef CUDA_DEBUG { int i; printf("ret:"); for (i = 0; i < rlen; i++) printf(" %02x", recv[i]); printf("\n"); } #endif return rlen; } return 0; }
static int cuda_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *_send, size_t send_len, void *_recv, size_t recv_len, int flags) { struct cuda_softc *sc = cookie; const uint8_t *send = _send; uint8_t *recv = _recv; uint8_t command[16] = {CUDA_PSEUDO, CMD_IIC}; DPRINTF("cuda_i2c_exec(%02x)\n", addr); command[2] = addr; /* Copy command and output data bytes, if any, to buffer */ if (send_len > 0) memcpy(&command[3], send, min((int)send_len, 12)); else if (I2C_OP_READ_P(op) && (recv_len == 0)) { /* * If no data bytes in either direction, it's a "quick" * i2c operation. We don't know how to do a quick_read * since that requires us to set the low bit of the * address byte after it has been left-shifted. */ sc->sc_error = 0; return -1; } sc->sc_iic_done = 0; cuda_send(sc, sc->sc_polling, send_len + 3, command); while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) { if (sc->sc_polling || cold) { cuda_poll(sc); } else tsleep(&sc->sc_todev, 0, "i2c", 1000); } if (sc->sc_error) { sc->sc_error = 0; aprint_error_dev(sc->sc_dev, "error doing I2C\n"); return -1; } /* see if we're supposed to do a read */ if (recv_len > 0) { sc->sc_iic_done = 0; command[2] |= 1; command[3] = 0; /* * XXX we need to do something to limit the size of the answer * - apparently the chip keeps sending until we tell it to stop */ sc->sc_i2c_read_len = recv_len; DPRINTF("rcv_len: %d\n", recv_len); cuda_send(sc, sc->sc_polling, 3, command); while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) { if (sc->sc_polling || cold) { cuda_poll(sc); } else tsleep(&sc->sc_todev, 0, "i2c", 1000); } if (sc->sc_error) { aprint_error_dev(sc->sc_dev, "error trying to read from I2C\n"); sc->sc_error = 0; return -1; } } DPRINTF("received: %d\n", sc->sc_iic_done); if ((sc->sc_iic_done > 3) && (recv_len > 0)) { int rlen; /* we got an answer */ rlen = min(sc->sc_iic_done - 3, recv_len); memcpy(recv, &sc->sc_in[4], rlen); #ifdef CUDA_DEBUG { int i; printf("ret:"); for (i = 0; i < rlen; i++) printf(" %02x", recv[i]); printf("\n"); } #endif return rlen; } return 0; }