Home | History | Annotate | Line # | Download | only in dev
cuda.c revision 1.2
      1 /*	$NetBSD: cuda.c,v 1.2 2007/02/05 18:26:06 macallan Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2006 Michael Lorenz
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of The NetBSD Foundation nor the names of its
     16  *    contributors may be used to endorse or promote products derived
     17  *    from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: cuda.c,v 1.2 2007/02/05 18:26:06 macallan Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/kernel.h>
     38 #include <sys/device.h>
     39 #include <sys/proc.h>
     40 
     41 #include <machine/bus.h>
     42 #include <machine/autoconf.h>
     43 #include <dev/clock_subr.h>
     44 #include <dev/i2c/i2cvar.h>
     45 
     46 #include <macppc/dev/viareg.h>
     47 #include <macppc/dev/cudavar.h>
     48 
     49 #include <dev/ofw/openfirm.h>
     50 #include <dev/adb/adbvar.h>
     51 #include "opt_cuda.h"
     52 
     53 #ifdef CUDA_DEBUG
     54 #define DPRINTF printf
     55 #else
     56 #define DPRINTF while (0) printf
     57 #endif
     58 
     59 #define CUDA_NOTREADY	0x1	/* has not been initialized yet */
     60 #define CUDA_IDLE	0x2	/* the bus is currently idle */
     61 #define CUDA_OUT	0x3	/* sending out a command */
     62 #define CUDA_IN		0x4	/* receiving data */
     63 #define CUDA_POLLING	0x5	/* polling - II only */
     64 
     65 static void cuda_attach(struct device *, struct device *, void *);
     66 static int cuda_match(struct device *, struct cfdata *, void *);
     67 static void cuda_autopoll(void *, int);
     68 
     69 static int cuda_intr(void *);
     70 
     71 typedef struct _cuda_handler {
     72 	int (*handler)(void *, int, uint8_t *);
     73 	void *cookie;
     74 } CudaHandler;
     75 
     76 struct cuda_softc {
     77 	struct device sc_dev;
     78 	void *sc_ih;
     79 	CudaHandler sc_handlers[16];
     80 	struct todr_chip_handle sc_todr;
     81 	struct adb_bus_accessops sc_adbops;
     82 	struct i2c_controller sc_i2c;
     83 	struct lock sc_buslock;
     84 	bus_space_tag_t sc_memt;
     85 	bus_space_handle_t sc_memh;
     86 	int sc_node;
     87 	int sc_state;
     88 	int sc_waiting;
     89 	int sc_polling;
     90 	int sc_sent;
     91 	int sc_out_length;
     92 	int sc_received;
     93 	int sc_iic_done;
     94 	int sc_error;
     95 	/* time */
     96 	uint32_t sc_tod;
     97 	uint32_t sc_autopoll;
     98 	uint32_t sc_todev;
     99 	/* ADB */
    100 	void (*sc_adb_handler)(void *, int, uint8_t *);
    101 	void *sc_adb_cookie;
    102 	uint32_t sc_i2c_read_len;
    103 	/* internal buffers */
    104 	uint8_t sc_in[256];
    105 	uint8_t sc_out[256];
    106 };
    107 
    108 CFATTACH_DECL(cuda, sizeof(struct cuda_softc),
    109     cuda_match, cuda_attach, NULL, NULL);
    110 
    111 static inline void cuda_write_reg(struct cuda_softc *, int, uint8_t);
    112 static inline uint8_t cuda_read_reg(struct cuda_softc *, int);
    113 static void cuda_idle(struct cuda_softc *);
    114 static void cuda_tip(struct cuda_softc *);
    115 static void cuda_clear_tip(struct cuda_softc *);
    116 static void cuda_in(struct cuda_softc *);
    117 static void cuda_out(struct cuda_softc *);
    118 static void cuda_toggle_ack(struct cuda_softc *);
    119 static void cuda_ack_off(struct cuda_softc *);
    120 static int cuda_intr_state(struct cuda_softc *);
    121 
    122 static void cuda_init(struct cuda_softc *);
    123 
    124 /*
    125  * send a message to Cuda.
    126  */
    127 /* cookie, flags, length, data */
    128 static int cuda_send(void *, int, int, uint8_t *);
    129 static void cuda_poll(void *);
    130 static void cuda_adb_poll(void *);
    131 static int cuda_set_handler(void *, int, int (*)(void *, int, uint8_t *), void *);
    132 
    133 static int cuda_error_handler(void *, int, uint8_t *);
    134 
    135 static int cuda_todr_handler(void *, int, uint8_t *);
    136 static int cuda_todr_set(todr_chip_handle_t, volatile struct timeval *);
    137 static int cuda_todr_get(todr_chip_handle_t, volatile struct timeval *);
    138 
    139 static int cuda_adb_handler(void *, int, uint8_t *);
    140 static void cuda_final(struct device *);
    141 
    142 static struct cuda_attach_args *cuda0 = NULL;
    143 
    144 /* ADB bus attachment stuff */
    145 static 	int cuda_adb_send(void *, int, int, int, uint8_t *);
    146 static	int cuda_adb_set_handler(void *, void (*)(void *, int, uint8_t *), void *);
    147 
    148 /* i2c stuff */
    149 static int cuda_i2c_acquire_bus(void *, int);
    150 static void cuda_i2c_release_bus(void *, int);
    151 static int cuda_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
    152 		    void *, size_t, int);
    153 
    154 static int
    155 cuda_match(struct device *parent, struct cfdata *cf, void *aux)
    156 {
    157 	struct confargs *ca = aux;
    158 
    159 	if (ca->ca_nreg < 8)
    160 		return 0;
    161 
    162 	if (ca->ca_nintr < 4)
    163 		return 0;
    164 
    165 	if (strcmp(ca->ca_name, "via-cuda") == 0) {
    166 		return 10;	/* beat adb* at obio? */
    167 	}
    168 
    169 	return 0;
    170 }
    171 
    172 static void
    173 cuda_attach(struct device *parent, struct device *dev, void *aux)
    174 {
    175 	struct confargs *ca = aux;
    176 	struct cuda_softc *sc = (struct cuda_softc *)dev;
    177 	struct i2cbus_attach_args iba;
    178 	static struct cuda_attach_args caa;
    179 	int irq = ca->ca_intr[0];
    180 	int node, i, child;
    181 	char name[32];
    182 
    183 	node = getnodebyname(OF_parent(ca->ca_node), "extint-gpio1");
    184 	if (node)
    185 		OF_getprop(node, "interrupts", &irq, 4);
    186 
    187 	printf(" irq %d: ", irq);
    188 
    189 	sc->sc_node = ca->ca_node;
    190 	sc->sc_memt = ca->ca_tag;
    191 
    192 	sc->sc_sent = 0;
    193 	sc->sc_received = 0;
    194 	sc->sc_waiting = 0;
    195 	sc->sc_polling = 0;
    196 	sc->sc_state = CUDA_NOTREADY;
    197 	sc->sc_error = 0;
    198 	sc->sc_i2c_read_len = 0;
    199 
    200 	if (bus_space_map(sc->sc_memt, ca->ca_reg[0] + ca->ca_baseaddr,
    201 	    ca->ca_reg[1], 0, &sc->sc_memh) != 0) {
    202 
    203 		printf("%s: unable to map registers\n", dev->dv_xname);
    204 		return;
    205 	}
    206 	sc->sc_ih = intr_establish(irq, IST_LEVEL, IPL_HIGH, cuda_intr, sc);
    207 	printf("\n");
    208 
    209 	for (i = 0; i < 16; i++) {
    210 		sc->sc_handlers[i].handler = NULL;
    211 		sc->sc_handlers[i].cookie = NULL;
    212 	}
    213 
    214 	cuda_init(sc);
    215 
    216 	/* now attach children */
    217 	config_interrupts(dev, cuda_final);
    218 	cuda_set_handler(sc, CUDA_ERROR, cuda_error_handler, sc);
    219 	cuda_set_handler(sc, CUDA_PSEUDO, cuda_todr_handler, sc);
    220 
    221 	child = OF_child(ca->ca_node);
    222 	while (child != 0) {
    223 
    224 		if (OF_getprop(child, "name", name, 32) == 0)
    225 			continue;
    226 		if (strncmp(name, "adb", 4) == 0) {
    227 
    228 			cuda_set_handler(sc, CUDA_ADB, cuda_adb_handler, sc);
    229 			sc->sc_adbops.cookie = sc;
    230 			sc->sc_adbops.send = cuda_adb_send;
    231 			sc->sc_adbops.poll = cuda_adb_poll;
    232 			sc->sc_adbops.autopoll = cuda_autopoll;
    233 			sc->sc_adbops.set_handler = cuda_adb_set_handler;
    234 			config_found_ia(dev, "adb_bus", &sc->sc_adbops,
    235 			    nadb_print);
    236 		} else if (strncmp(name, "rtc", 4) == 0) {
    237 
    238 			sc->sc_todr.todr_gettime = cuda_todr_get;
    239 			sc->sc_todr.todr_settime = cuda_todr_set;
    240 			sc->sc_todr.cookie = sc;
    241 			todr_attach(&sc->sc_todr);
    242 		}
    243 		child = OF_peer(child);
    244 	}
    245 
    246 	caa.cookie = sc;
    247 	caa.set_handler = cuda_set_handler;
    248 	caa.send = cuda_send;
    249 	caa.poll = cuda_poll;
    250 #if notyet
    251 	config_found(dev, &caa, cuda_print);
    252 #endif
    253 
    254 	iba.iba_tag = &sc->sc_i2c;
    255 	sc->sc_i2c.ic_cookie = sc;
    256 	sc->sc_i2c.ic_acquire_bus = cuda_i2c_acquire_bus;
    257 	sc->sc_i2c.ic_release_bus = cuda_i2c_release_bus;
    258 	sc->sc_i2c.ic_send_start = NULL;
    259 	sc->sc_i2c.ic_send_stop = NULL;
    260 	sc->sc_i2c.ic_initiate_xfer = NULL;
    261 	sc->sc_i2c.ic_read_byte = NULL;
    262 	sc->sc_i2c.ic_write_byte = NULL;
    263 	sc->sc_i2c.ic_exec = cuda_i2c_exec;
    264 	config_found_ia(&sc->sc_dev, "i2cbus", &iba, iicbus_print);
    265 
    266 	if (cuda0 == NULL)
    267 		cuda0 = &caa;
    268 }
    269 
    270 static void
    271 cuda_init(struct cuda_softc *sc)
    272 {
    273 	volatile int i;
    274 	uint8_t reg;
    275 
    276 	reg = cuda_read_reg(sc, vDirB);
    277 	reg |= 0x30;	/* register B bits 4 and 5: outputs */
    278 	cuda_write_reg(sc, vDirB, reg);
    279 
    280 	reg = cuda_read_reg(sc, vDirB);
    281 	reg &= 0xf7;	/* register B bit 3: input */
    282 	cuda_write_reg(sc, vDirB, reg);
    283 
    284 	reg = cuda_read_reg(sc, vACR);
    285 	reg &= ~vSR_OUT;	/* make sure SR is set to IN */
    286 	cuda_write_reg(sc, vACR, reg);
    287 
    288 	cuda_write_reg(sc, vACR, (cuda_read_reg(sc, vACR) | 0x0c) & ~0x10);
    289 
    290 	sc->sc_state = CUDA_IDLE;	/* used by all types of hardware */
    291 
    292 	cuda_write_reg(sc, vIER, 0x84); /* make sure VIA interrupts are on */
    293 	cuda_idle(sc);	/* set ADB bus state to idle */
    294 
    295 	/* sort of a device reset */
    296 	i = cuda_read_reg(sc, vSR);	/* clear interrupt */
    297 	cuda_write_reg(sc, vIER, 0x04); /* no interrupts while clearing */
    298 	cuda_idle(sc);	/* reset state to idle */
    299 	delay(150);
    300 	cuda_tip(sc);	/* signal start of frame */
    301 	delay(150);
    302 	cuda_toggle_ack(sc);
    303 	delay(150);
    304 	cuda_clear_tip(sc);
    305 	delay(150);
    306 	cuda_idle(sc);	/* back to idle state */
    307 	i = cuda_read_reg(sc, vSR);	/* clear interrupt */
    308 	cuda_write_reg(sc, vIER, 0x84);	/* ints ok now */
    309 }
    310 
    311 static void
    312 cuda_final(struct device *dev)
    313 {
    314 	struct cuda_softc *sc = (struct cuda_softc *)dev;
    315 
    316 	sc->sc_polling = 0;
    317 #if 0
    318 	{
    319 		int err;
    320 		uint8_t buffer[2], buf2[2];
    321 
    322 		/* trying to read */
    323 		printf("reading\n");
    324 		buffer[0] = 0;
    325 		buffer[1] = 1;
    326 		buf2[0] = 0;
    327 		err = cuda_i2c_exec(sc, I2C_OP_WRITE, 0x8a, buffer, 2, buf2, 0, 0);
    328 		buf2[0] = 0;
    329 		err = cuda_i2c_exec(sc, I2C_OP_WRITE | I2C_OP_READ, 0x8a, buffer, 1, buf2, 2, 0);
    330 		printf("buf2: %02x\n", buf2[0]);
    331 	}
    332 #endif
    333 }
    334 
    335 static inline void
    336 cuda_write_reg(struct cuda_softc *sc, int offset, uint8_t value)
    337 {
    338 
    339 	bus_space_write_1(sc->sc_memt, sc->sc_memh, offset, value);
    340 }
    341 
    342 static inline uint8_t
    343 cuda_read_reg(struct cuda_softc *sc, int offset)
    344 {
    345 
    346 	return bus_space_read_1(sc->sc_memt, sc->sc_memh, offset);
    347 }
    348 
    349 static int
    350 cuda_set_handler(void *cookie, int type,
    351     int (*handler)(void *, int, uint8_t *), void *hcookie)
    352 {
    353 	struct cuda_softc *sc = cookie;
    354 	CudaHandler *me;
    355 
    356 	if ((type >= 0) && (type < 16)) {
    357 		me = &sc->sc_handlers[type];
    358 		me->handler = handler;
    359 		me->cookie = hcookie;
    360 		return 0;
    361 	}
    362 	return -1;
    363 }
    364 
    365 static int
    366 cuda_send(void *cookie, int poll, int length, uint8_t *msg)
    367 {
    368 	struct cuda_softc *sc = cookie;
    369 	int s;
    370 
    371 	DPRINTF("cuda_send %08x\n", (uint32_t)cookie);
    372 	if (sc->sc_state == CUDA_NOTREADY)
    373 		return -1;
    374 
    375 	s = splhigh();
    376 
    377 	if ((sc->sc_state == CUDA_IDLE) /*&&
    378 	    ((cuda_read_reg(sc, vBufB) & vPB3) == vPB3)*/) {
    379 		/* fine */
    380 		DPRINTF("chip is idle\n");
    381 	} else {
    382 		DPRINTF("cuda state is %d\n", sc->sc_state);
    383 		if (sc->sc_waiting == 0) {
    384 			sc->sc_waiting = 1;
    385 		} else {
    386 			splx(s);
    387 			return -1;
    388 		}
    389 	}
    390 
    391 	sc->sc_error = 0;
    392 	memcpy(sc->sc_out, msg, length);
    393 	sc->sc_out_length = length;
    394 	sc->sc_sent = 0;
    395 
    396 	if (sc->sc_waiting != 1) {
    397 
    398 		delay(150);
    399 		sc->sc_state = CUDA_OUT;
    400 		cuda_out(sc);
    401 		cuda_write_reg(sc, vSR, sc->sc_out[0]);
    402 		cuda_ack_off(sc);
    403 		cuda_tip(sc);
    404 	}
    405 	sc->sc_waiting = 1;
    406 
    407 	if (sc->sc_polling || poll || cold) {
    408 		cuda_poll(sc);
    409 	}
    410 
    411 	splx(s);
    412 
    413 	return 0;
    414 }
    415 
    416 static void
    417 cuda_poll(void *cookie)
    418 {
    419 	struct cuda_softc *sc = cookie;
    420 	int s;
    421 
    422 	DPRINTF("polling\n");
    423 	while ((sc->sc_state != CUDA_IDLE) ||
    424 	       (cuda_intr_state(sc)) ||
    425 	       (sc->sc_waiting == 1)) {
    426 		if ((cuda_read_reg(sc, vIFR) & vSR_INT) == vSR_INT) {
    427 			s = splhigh();
    428 			cuda_intr(sc);
    429 			splx(s);
    430 		}
    431 	}
    432 }
    433 
    434 static void
    435 cuda_adb_poll(void *cookie)
    436 {
    437 	struct cuda_softc *sc = cookie;
    438 	int s;
    439 
    440 	s = splhigh();
    441 	cuda_intr(sc);
    442 	splx(s);
    443 }
    444 
    445 static void
    446 cuda_idle(struct cuda_softc *sc)
    447 {
    448 	uint8_t reg;
    449 
    450 	reg = cuda_read_reg(sc, vBufB);
    451 	reg |= (vPB4 | vPB5);
    452 	cuda_write_reg(sc, vBufB, reg);
    453 }
    454 
    455 static void
    456 cuda_tip(struct cuda_softc *sc)
    457 {
    458 	uint8_t reg;
    459 
    460 	reg = cuda_read_reg(sc, vBufB);
    461 	reg &= ~vPB5;
    462 	cuda_write_reg(sc, vBufB, reg);
    463 }
    464 
    465 static void
    466 cuda_clear_tip(struct cuda_softc *sc)
    467 {
    468 	uint8_t reg;
    469 
    470 	reg = cuda_read_reg(sc, vBufB);
    471 	reg |= vPB5;
    472 	cuda_write_reg(sc, vBufB, reg);
    473 }
    474 
    475 static void
    476 cuda_in(struct cuda_softc *sc)
    477 {
    478 	uint8_t reg;
    479 
    480 	reg = cuda_read_reg(sc, vACR);
    481 	reg &= ~vSR_OUT;
    482 	cuda_write_reg(sc, vACR, reg);
    483 }
    484 
    485 static void
    486 cuda_out(struct cuda_softc *sc)
    487 {
    488 	uint8_t reg;
    489 
    490 	reg = cuda_read_reg(sc, vACR);
    491 	reg |= vSR_OUT;
    492 	cuda_write_reg(sc, vACR, reg);
    493 }
    494 
    495 static void
    496 cuda_toggle_ack(struct cuda_softc *sc)
    497 {
    498 	uint8_t reg;
    499 
    500 	reg = cuda_read_reg(sc, vBufB);
    501 	reg ^= vPB4;
    502 	cuda_write_reg(sc, vBufB, reg);
    503 }
    504 
    505 static void
    506 cuda_ack_off(struct cuda_softc *sc)
    507 {
    508 	uint8_t reg;
    509 
    510 	reg = cuda_read_reg(sc, vBufB);
    511 	reg |= vPB4;
    512 	cuda_write_reg(sc, vBufB, reg);
    513 }
    514 
    515 static int
    516 cuda_intr_state(struct cuda_softc *sc)
    517 {
    518 	return ((cuda_read_reg(sc, vBufB) & vPB3) == 0);
    519 }
    520 
    521 static int
    522 cuda_intr(void *arg)
    523 {
    524 	struct cuda_softc *sc = arg;
    525 	int i, ending, type;
    526 	uint8_t reg;
    527 
    528 	reg = cuda_read_reg(sc, vIFR);		/* Read the interrupts */
    529 	DPRINTF("[");
    530 	if ((reg & 0x80) == 0) {
    531 		DPRINTF("irq %02x]", reg);
    532 		return 0;			/* No interrupts to process */
    533 	}
    534 	DPRINTF(":");
    535 
    536 	cuda_write_reg(sc, vIFR, 0x7f);	/* Clear 'em */
    537 
    538 switch_start:
    539 	switch (sc->sc_state) {
    540 	case CUDA_IDLE:
    541 		/*
    542 		 * This is an unexpected packet, so grab the first (dummy)
    543 		 * byte, set up the proper vars, and tell the chip we are
    544 		 * starting to receive the packet by setting the TIP bit.
    545 		 */
    546 		sc->sc_in[1] = cuda_read_reg(sc, vSR);
    547 		DPRINTF("start: %02x", sc->sc_in[1]);
    548 		if (cuda_intr_state(sc) == 0) {
    549 			/* must have been a fake start */
    550 			DPRINTF(" ... fake start\n");
    551 			if (sc->sc_waiting) {
    552 				/* start over */
    553 				delay(150);
    554 				sc->sc_state = CUDA_OUT;
    555 				sc->sc_sent = 0;
    556 				cuda_out(sc);
    557 				cuda_write_reg(sc, vSR, sc->sc_out[1]);
    558 				cuda_ack_off(sc);
    559 				cuda_tip(sc);
    560 			}
    561 			break;
    562 		}
    563 
    564 		cuda_in(sc);
    565 		cuda_tip(sc);
    566 
    567 		sc->sc_received = 1;
    568 		sc->sc_state = CUDA_IN;
    569 		DPRINTF(" CUDA_IN");
    570 		break;
    571 
    572 	case CUDA_IN:
    573 		sc->sc_in[sc->sc_received] = cuda_read_reg(sc, vSR);
    574 		DPRINTF(" %02x", sc->sc_in[sc->sc_received]);
    575 		ending = 0;
    576 		if (sc->sc_received > 255) {
    577 			/* bitch only once */
    578 			if (sc->sc_received == 256) {
    579 				printf("%s: input overflow\n",
    580 				    sc->sc_dev.dv_xname);
    581 				ending = 1;
    582 			}
    583 		} else
    584 			sc->sc_received++;
    585 		if (sc->sc_received > 3) {
    586 			if ((sc->sc_in[3] == CMD_IIC) &&
    587 			    (sc->sc_received > (sc->sc_i2c_read_len + 4))) {
    588 				ending = 1;
    589 			}
    590 		}
    591 
    592 		/* intr off means this is the last byte (end of frame) */
    593 		if (cuda_intr_state(sc) == 0) {
    594 			ending = 1;
    595 			DPRINTF(".\n");
    596 		} else {
    597 			cuda_toggle_ack(sc);
    598 		}
    599 
    600 		if (ending == 1) {	/* end of message? */
    601 
    602 			sc->sc_in[0] = sc->sc_received - 1;
    603 
    604 			/* reset vars and signal the end of this frame */
    605 			cuda_idle(sc);
    606 
    607 			/* check if we have a handler for this message */
    608 			type = sc->sc_in[1];
    609 			if ((type >= 0) && (type < 16)) {
    610 				CudaHandler *me = &sc->sc_handlers[type];
    611 
    612 				if (me->handler != NULL) {
    613 					me->handler(me->cookie,
    614 					    sc->sc_received - 1, &sc->sc_in[1]);
    615 				} else {
    616 					printf("no handler for type %02x\n", type);
    617 					panic("barf");
    618 				}
    619 			}
    620 
    621 			DPRINTF("CUDA_IDLE");
    622 			sc->sc_state = CUDA_IDLE;
    623 
    624 			sc->sc_received = 0;
    625 
    626 			/*
    627 			 * If there is something waiting to be sent out,
    628 			 * set everything up and send the first byte.
    629 			 */
    630 			if (sc->sc_waiting == 1) {
    631 
    632 				DPRINTF("pending write\n");
    633 				delay(1500);	/* required */
    634 				sc->sc_sent = 0;
    635 				sc->sc_state = CUDA_OUT;
    636 
    637 				/*
    638 				 * If the interrupt is on, we were too slow
    639 				 * and the chip has already started to send
    640 				 * something to us, so back out of the write
    641 				 * and start a read cycle.
    642 				 */
    643 				if (cuda_intr_state(sc)) {
    644 					cuda_in(sc);
    645 					cuda_idle(sc);
    646 					sc->sc_sent = 0;
    647 					sc->sc_state = CUDA_IDLE;
    648 					sc->sc_received = 0;
    649 					delay(150);
    650 					DPRINTF("too slow - incoming message\n");
    651 					goto switch_start;
    652 				}
    653 				/*
    654 				 * If we got here, it's ok to start sending
    655 				 * so load the first byte and tell the chip
    656 				 * we want to send.
    657 				 */
    658 				DPRINTF("sending ");
    659 
    660 				cuda_out(sc);
    661 				cuda_write_reg(sc, vSR,
    662 				    sc->sc_out[sc->sc_sent]);
    663 				cuda_ack_off(sc);
    664 				cuda_tip(sc);
    665 			}
    666 		}
    667 		break;
    668 
    669 	case CUDA_OUT:
    670 		i = cuda_read_reg(sc, vSR);	/* reset SR-intr in IFR */
    671 
    672 		sc->sc_sent++;
    673 		if (cuda_intr_state(sc)) {	/* ADB intr low during write */
    674 
    675 			DPRINTF("incoming msg during send\n");
    676 			cuda_in(sc);	/* make sure SR is set to IN */
    677 			cuda_idle(sc);
    678 			sc->sc_sent = 0;	/* must start all over */
    679 			sc->sc_state = CUDA_IDLE;	/* new state */
    680 			sc->sc_received = 0;
    681 			sc->sc_waiting = 1;	/* must retry when done with
    682 						 * read */
    683 			delay(150);
    684 			goto switch_start;	/* process next state right
    685 						 * now */
    686 			break;
    687 		}
    688 		if (sc->sc_out_length == sc->sc_sent) {	/* check for done */
    689 
    690 			sc->sc_waiting = 0;	/* done writing */
    691 			sc->sc_state = CUDA_IDLE;	/* signal bus is idle */
    692 			cuda_in(sc);
    693 			cuda_idle(sc);
    694 			DPRINTF("done sending\n");
    695 		} else {
    696 			/* send next byte */
    697 			cuda_write_reg(sc, vSR, sc->sc_out[sc->sc_sent]);
    698 			cuda_toggle_ack(sc);	/* signal byte ready to
    699 							 * shift */
    700 		}
    701 		break;
    702 
    703 	case CUDA_NOTREADY:
    704 		DPRINTF("adb: not yet initialized\n");
    705 		break;
    706 
    707 	default:
    708 		DPRINTF("intr: unknown ADB state\n");
    709 		break;
    710 	}
    711 
    712 	DPRINTF("]");
    713 	return 1;
    714 }
    715 
    716 static int
    717 cuda_error_handler(void *cookie, int len, uint8_t *data)
    718 {
    719 	struct cuda_softc *sc = cookie;
    720 
    721 	/*
    722 	 * something went wrong
    723 	 * byte 3 seems to be the failed command
    724 	 */
    725 	sc->sc_error = 1;
    726 	wakeup(&sc->sc_todev);
    727 	return 0;
    728 }
    729 
    730 
    731 /* real time clock */
    732 
    733 static int
    734 cuda_todr_handler(void *cookie, int len, uint8_t *data)
    735 {
    736 	struct cuda_softc *sc = cookie;
    737 
    738 #ifdef CUDA_DEBUG
    739 	int i;
    740 	printf("msg: %02x", data[0]);
    741 	for (i = 1; i < len; i++) {
    742 		printf(" %02x", data[i]);
    743 	}
    744 	printf("\n");
    745 #endif
    746 
    747 	switch(data[2]) {
    748 		case CMD_READ_RTC:
    749 			memcpy(&sc->sc_tod, &data[3], 4);
    750 			break;
    751 		case CMD_WRITE_RTC:
    752 			sc->sc_tod = 0xffffffff;
    753 			break;
    754 		case CMD_AUTOPOLL:
    755 			sc->sc_autopoll = 1;
    756 			break;
    757 		case CMD_IIC:
    758 			sc->sc_iic_done = len;
    759 			break;
    760 	}
    761 	wakeup(&sc->sc_todev);
    762 	return 0;
    763 }
    764 
    765 #define DIFF19041970 2082844800
    766 
    767 static int
    768 cuda_todr_get(todr_chip_handle_t tch, volatile struct timeval *tvp)
    769 {
    770 	struct cuda_softc *sc = tch->cookie;
    771 	int cnt = 0;
    772 	uint8_t cmd[] = { CUDA_PSEUDO, CMD_READ_RTC};
    773 
    774 	sc->sc_tod = 0;
    775 	cuda_send(sc, 0, 2, cmd);
    776 
    777 	while ((sc->sc_tod == 0) && (cnt < 10)) {
    778 		tsleep(&sc->sc_todev, 0, "todr", 10);
    779 		cnt++;
    780 	}
    781 
    782 	if (sc->sc_tod == 0)
    783 		return EIO;
    784 
    785 	tvp->tv_sec = sc->sc_tod - DIFF19041970;
    786 	DPRINTF("tod: %ld\n", tvp->tv_sec);
    787 	tvp->tv_usec = 0;
    788 	return 0;
    789 }
    790 
    791 static int
    792 cuda_todr_set(todr_chip_handle_t tch, volatile struct timeval *tvp)
    793 {
    794 	struct cuda_softc *sc = tch->cookie;
    795 	uint32_t sec;
    796 	uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0};
    797 
    798 	sec = tvp->tv_sec + DIFF19041970;
    799 	memcpy(&cmd[2], &sec, 4);
    800 	sc->sc_tod = 0;
    801 	if (cuda_send(sc, 0, 6, cmd) == 0) {
    802 		while (sc->sc_tod == 0) {
    803 			tsleep(&sc->sc_todev, 0, "todr", 10);
    804 		}
    805 		return 0;
    806 	}
    807 	return -1;
    808 
    809 }
    810 
    811 /* poweroff and reboot */
    812 
    813 void
    814 cuda_poweroff()
    815 {
    816 	struct cuda_softc *sc;
    817 	uint8_t cmd[] = {CUDA_PSEUDO, CMD_POWEROFF};
    818 
    819 	if (cuda0 == NULL)
    820 		return;
    821 	sc = cuda0->cookie;
    822 	sc->sc_polling = 1;
    823 	cuda0->poll(sc);
    824 	if (cuda0->send(sc, 1, 2, cmd) == 0)
    825 		while (1);
    826 }
    827 
    828 void
    829 cuda_restart()
    830 {
    831 	struct cuda_softc *sc;
    832 	uint8_t cmd[] = {CUDA_PSEUDO, CMD_RESET};
    833 
    834 	if (cuda0 == NULL)
    835 		return;
    836 	sc = cuda0->cookie;
    837 	sc->sc_polling = 1;
    838 	cuda0->poll(sc);
    839 	if (cuda0->send(sc, 1, 2, cmd) == 0)
    840 		while (1);
    841 }
    842 
    843 /* ADB message handling */
    844 
    845 static void
    846 cuda_autopoll(void *cookie, int flag)
    847 {
    848 	struct cuda_softc *sc = cookie;
    849 	uint8_t cmd[] = {CUDA_PSEUDO, CMD_AUTOPOLL, (flag != 0)};
    850 
    851 	if (cmd[2] == sc->sc_autopoll)
    852 		return;
    853 
    854 	sc->sc_autopoll = -1;
    855 	cuda_send(sc, 0, 3, cmd);
    856 	while(sc->sc_autopoll == -1) {
    857 		if (sc->sc_polling || cold) {
    858 			cuda_poll(sc);
    859 		} else
    860 			tsleep(&sc->sc_todev, 0, "autopoll", 100);
    861 	}
    862 }
    863 
    864 static int
    865 cuda_adb_handler(void *cookie, int len, uint8_t *data)
    866 {
    867 	struct cuda_softc *sc = cookie;
    868 
    869 	if (sc->sc_adb_handler != NULL) {
    870 		sc->sc_adb_handler(sc->sc_adb_cookie, len - 1,
    871 		    &data[1]);
    872 		return 0;
    873 	}
    874 	return -1;
    875 }
    876 
    877 static int
    878 cuda_adb_send(void *cookie, int poll, int command, int len, uint8_t *data)
    879 {
    880 	struct cuda_softc *sc = cookie;
    881 	int i, s = 0;
    882 	uint8_t packet[16];
    883 
    884 	/* construct an ADB command packet and send it */
    885 	packet[0] = CUDA_ADB;
    886 	packet[1] = command;
    887 	for (i = 0; i < len; i++)
    888 		packet[i + 2] = data[i];
    889 	if (poll || cold) {
    890 		s = splhigh();
    891 		cuda_poll(sc);
    892 	}
    893 	cuda_send(sc, poll, len + 2, packet);
    894 	if (poll || cold) {
    895 		cuda_poll(sc);
    896 		splx(s);
    897 	}
    898 	return 0;
    899 }
    900 
    901 static int
    902 cuda_adb_set_handler(void *cookie, void (*handler)(void *, int, uint8_t *),
    903     void *hcookie)
    904 {
    905 	struct cuda_softc *sc = cookie;
    906 
    907 	/* register a callback for incoming ADB messages */
    908 	sc->sc_adb_handler = handler;
    909 	sc->sc_adb_cookie = hcookie;
    910 	return 0;
    911 }
    912 
    913 /* i2c message handling */
    914 
    915 static int
    916 cuda_i2c_acquire_bus(void *cookie, int flags)
    917 {
    918 	/* nothing yet */
    919 	return 0;
    920 }
    921 
    922 static void
    923 cuda_i2c_release_bus(void *cookie, int flags)
    924 {
    925 	/* nothing here either */
    926 }
    927 
    928 static int
    929 cuda_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *_send,
    930     size_t send_len, void *_recv, size_t recv_len, int flags)
    931 {
    932 	struct cuda_softc *sc = cookie;
    933 	const uint8_t *send = _send;
    934 	uint8_t *recv = _recv;
    935 	uint8_t command[16] = {CUDA_PSEUDO, CMD_IIC};
    936 
    937 	DPRINTF("cuda_i2c_exec(%02x)\n", addr);
    938 	command[2] = addr;
    939 
    940 	memcpy(&command[3], send, min((int)send_len, 12));
    941 
    942 	sc->sc_iic_done = 0;
    943 	cuda_send(sc, sc->sc_polling, send_len + 3, command);
    944 
    945 	while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) {
    946 		if (sc->sc_polling || cold) {
    947 			cuda_poll(sc);
    948 		} else
    949 			tsleep(&sc->sc_todev, 0, "i2c", 1000);
    950 	}
    951 
    952 	if (sc->sc_error) {
    953 		sc->sc_error = 0;
    954 		return -1;
    955 	}
    956 
    957 	/* see if we're supposed to do a read */
    958 	if (recv_len > 0) {
    959 		sc->sc_iic_done = 0;
    960 		command[2] |= 1;
    961 		command[3] = 0;
    962 
    963 		/*
    964 		 * XXX we need to do something to limit the size of the answer
    965 		 * - apparently the chip keeps sending until we tell it to stop
    966 		 */
    967 		sc->sc_i2c_read_len = recv_len;
    968 		DPRINTF("rcv_len: %d\n", recv_len);
    969 		cuda_send(sc, sc->sc_polling, 3, command);
    970 		while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) {
    971 			if (sc->sc_polling || cold) {
    972 				cuda_poll(sc);
    973 			} else
    974 				tsleep(&sc->sc_todev, 0, "i2c", 1000);
    975 		}
    976 
    977 		if (sc->sc_error) {
    978 			printf("error trying to read\n");
    979 			sc->sc_error = 0;
    980 			return -1;
    981 		}
    982 	}
    983 
    984 	DPRINTF("received: %d\n", sc->sc_iic_done);
    985 	if ((sc->sc_iic_done > 3) && (recv_len > 0)) {
    986 		int rlen;
    987 
    988 		/* we got an answer */
    989 		rlen = min(sc->sc_iic_done - 3, recv_len);
    990 		memcpy(recv, &sc->sc_in[4], rlen);
    991 #ifdef CUDA_DEBUG
    992 		{
    993 			int i;
    994 			printf("ret:");
    995 			for (i = 0; i < rlen; i++)
    996 				printf(" %02x", recv[i]);
    997 			printf("\n");
    998 		}
    999 #endif
   1000 		return rlen;
   1001 	}
   1002 	return 0;
   1003 }
   1004