static int cuda_todr_get(todr_chip_handle_t tch, struct timeval *tvp) { struct cuda_softc *sc = tch->cookie; int cnt = 0; uint8_t cmd[] = { CUDA_PSEUDO, CMD_READ_RTC}; sc->sc_tod = 0; while (sc->sc_tod == 0) { cuda_send(sc, 0, 2, cmd); while ((sc->sc_tod == 0) && (cnt < 10)) { tsleep(&sc->sc_todev, 0, "todr", 10); cnt++; } if (sc->sc_tod == 0) { aprint_error_dev(sc->sc_dev, "unable to read a sane RTC value\n"); return EIO; } if ((sc->sc_tod > 0xf0000000UL) || (sc->sc_tod < DIFF19041970)) { /* huh? try again */ sc->sc_tod = 0; aprint_verbose_dev(sc->sc_dev, "got garbage reading RTC, trying again\n"); } } tvp->tv_sec = sc->sc_tod - DIFF19041970; DPRINTF("tod: %" PRIo64 "\n", tvp->tv_sec); tvp->tv_usec = 0; return 0; }
static void cuda_shutdown(void *xsc, int howto) { struct cuda_softc *sc = xsc; uint8_t cmd[] = {CUDA_PSEUDO, 0}; cmd[1] = (howto & RB_HALT) ? CMD_POWEROFF : CMD_RESET; cuda_poll(sc->sc_dev); cuda_send(sc, 1, 2, cmd); while (1) cuda_poll(sc->sc_dev); }
static int cuda_settime(device_t dev, struct timespec *ts) { struct cuda_softc *sc = device_get_softc(dev); uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0}; uint32_t sec; sec = ts->tv_sec + DIFF19041970; memcpy(&cmd[2], &sec, sizeof(sec)); mtx_lock(&sc->sc_mutex); cuda_send(sc, 0, 6, cmd); mtx_unlock(&sc->sc_mutex); return (0); }
static int cuda_gettime(device_t dev, struct timespec *ts) { struct cuda_softc *sc = device_get_softc(dev); uint8_t cmd[] = {CUDA_PSEUDO, CMD_READ_RTC}; mtx_lock(&sc->sc_mutex); sc->sc_rtc = -1; cuda_send(sc, 1, 2, cmd); if (sc->sc_rtc == -1) mtx_sleep(&sc->sc_rtc, &sc->sc_mutex, 0, "rtc", 100); ts->tv_sec = sc->sc_rtc - DIFF19041970; ts->tv_nsec = 0; mtx_unlock(&sc->sc_mutex); return (0); }
static u_int cuda_adb_send(device_t dev, u_char command_byte, int len, u_char *data, u_char poll) { struct cuda_softc *sc = device_get_softc(dev); uint8_t packet[16]; int i; /* construct an ADB command packet and send it */ packet[0] = CUDA_ADB; packet[1] = command_byte; for (i = 0; i < len; i++) packet[i + 2] = data[i]; cuda_send(sc, poll, len + 2, packet); 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_todr_set(todr_chip_handle_t tch, volatile struct timeval *tvp) { struct cuda_softc *sc = tch->cookie; uint32_t sec; uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0}; sec = tvp->tv_sec + DIFF19041970; memcpy(&cmd[2], &sec, 4); sc->sc_tod = 0; if (cuda_send(sc, 0, 6, cmd) == 0) { while (sc->sc_tod == 0) { tsleep(&sc->sc_todev, 0, "todr", 10); } return 0; } return -1; }
static u_int cuda_adb_autopoll(device_t dev, uint16_t mask) { struct cuda_softc *sc = device_get_softc(dev); uint8_t cmd[] = {CUDA_PSEUDO, CMD_AUTOPOLL, mask != 0}; mtx_lock(&sc->sc_mutex); if (cmd[2] == sc->sc_autopoll) { mtx_unlock(&sc->sc_mutex); return (0); } sc->sc_autopoll = -1; cuda_send(sc, 1, 3, cmd); mtx_unlock(&sc->sc_mutex); 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_todr_get(todr_chip_handle_t tch, volatile struct timeval *tvp) { struct cuda_softc *sc = tch->cookie; int cnt = 0; uint8_t cmd[] = { CUDA_PSEUDO, CMD_READ_RTC}; sc->sc_tod = 0; cuda_send(sc, 0, 2, cmd); while ((sc->sc_tod == 0) && (cnt < 10)) { tsleep(&sc->sc_todev, 0, "todr", 10); cnt++; } if (sc->sc_tod == 0) return EIO; tvp->tv_sec = sc->sc_tod - DIFF19041970; DPRINTF("tod: %ld\n", tvp->tv_sec); tvp->tv_usec = 0; 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; 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; }