xref: /netbsd-src/sys/arch/mac68k/nubus/cpi_nubus.c (revision cac8e449158efc7261bebc8657cbb0125a2cfdde)
1 /*	$NetBSD: cpi_nubus.c,v 1.3 2008/06/11 23:54:45 cegger Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 Hauke Fath
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,v 1.3 2008/06/11 23:54:45 cegger Exp $");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/proc.h>
33 #include <sys/device.h>
34 #include <sys/malloc.h>
35 #include <sys/event.h>
36 #include <sys/callout.h>
37 #include <sys/conf.h>
38 #include <sys/file.h>
39 #include <sys/uio.h>
40 #include <sys/ioctl.h>
41 #include <sys/tty.h>
42 #include <sys/time.h>
43 #include <sys/kernel.h>
44 #include <sys/syslog.h>
45 #include <sys/errno.h>
46 
47 #include <machine/intr.h>
48 #include <machine/bus.h>
49 #include <machine/viareg.h>
50 
51 #include <dev/ic/z8536reg.h>
52 #include <mac68k/nubus/nubus.h>
53 #include <mac68k/nubus/cpi_nubusvar.h>
54 
55 #include "ioconf.h"
56 
57 #ifdef DEBUG
58 #define CPI_DEBUG
59 #endif
60 
61 /*
62  * Stuff taken from Egan/Teixeira ch 8: 'if(TRACE_FOO)' debug output
63  * statements don't break indentation, and when DEBUG is not defined,
64  * the compiler code optimizer drops them as dead code.
65  */
66 #ifdef CPI_DEBUG
67 #define M_TRACE_CONFIG	0x0001
68 #define M_TRACE_OPEN	0x0002
69 #define M_TRACE_CLOSE	0x0004
70 #define M_TRACE_READ	0x0008
71 #define M_TRACE_WRITE	0x0010
72 #define M_TRACE_IOCTL	0x0020
73 #define M_TRACE_STATUS	0x0040
74 #define M_TRACE_ALL	0xFFFF
75 #define M_TRACE_NONE	0x0000
76 
77 #define TRACE_CONFIG	(cpi_debug_mask & M_TRACE_CONFIG)
78 #define TRACE_OPEN	(cpi_debug_mask & M_TRACE_OPEN)
79 #define TRACE_CLOSE	(cpi_debug_mask & M_TRACE_CLOSE)
80 #define TRACE_READ	(cpi_debug_mask & M_TRACE_READ)
81 #define TRACE_WRITE	(cpi_debug_mask & M_TRACE_WRITE)
82 #define TRACE_IOCTL	(cpi_debug_mask & M_TRACE_IOCTL)
83 #define TRACE_STATUS	(cpi_debug_mask & M_TRACE_STATUS)
84 #define TRACE_ALL	(cpi_debug_mask & M_TRACE_ALL)
85 #define TRACE_NONE	(cpi_debug_mask & M_TRACE_NONE)
86 
87 uint32_t cpi_debug_mask = M_TRACE_NONE /* |�M_TRACE_WRITE */ ;
88 
89 #else
90 #define TRACE_CONFIG	0
91 #define TRACE_OPEN	0
92 #define TRACE_CLOSE	0
93 #define TRACE_READ	0
94 #define TRACE_WRITE	0
95 #define TRACE_IOCTL	0
96 #define TRACE_STATUS	0
97 #define TRACE_ALL	0
98 #define TRACE_NONE	0
99 #endif
100 
101 #undef USE_CIO_TIMERS		/* TBD */
102 
103 /* autoconf interface */
104 int cpi_nubus_match(device_t, cfdata_t, void *);
105 void cpi_nubus_attach(device_t, device_t, void *);
106 void cpi_nubus_intr(void *);
107 
108 CFATTACH_DECL(cpi, sizeof(struct cpi_softc),
109     cpi_nubus_match, cpi_nubus_attach, NULL, NULL);
110 
111 dev_type_open(cpi_open);
112 dev_type_close(cpi_close);
113 dev_type_read(cpi_read);
114 dev_type_write(cpi_write);
115 dev_type_ioctl(cpi_ioctl);
116 
117 const struct cdevsw cpi_cdevsw = {
118 	cpi_open, cpi_close, noread, cpi_write, cpi_ioctl,
119 	nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
120 };
121 
122 /* prototypes */
123 static void cpi_lpreset(struct cpi_softc *);
124 static int cpi_notready(struct cpi_softc *);
125 static void cpi_wakeup(void *);
126 static int cpi_flush(struct cpi_softc *);
127 static void cpi_intr(void *);
128 
129 #ifdef USE_CIO_TIMERS
130 static void cpi_initclock(struct cpi_softc *);
131 static u_int cpi_get_timecount(struct timecounter *);
132 #endif
133 
134 static inline void z8536_reg_set(bus_space_tag_t, bus_space_handle_t,
135     uint8_t, uint8_t);
136 static inline uint8_t z8536_reg_get(bus_space_tag_t, bus_space_handle_t,
137     uint8_t);
138 
139 
140 const uint8_t cio_reset[] = {
141 	/* register	value */
142 	Z8536_MICR, 	0x00,
143 	Z8536_MICR, 	MICR_RESET,
144 	Z8536_MICR, 	0x00
145 };
146 
147 const uint8_t cio_init[] = {
148 	/* register	value */
149 
150 	/* Interrupt vectors - clear all */
151 	Z8536_IVRA, 	0x00,
152 	Z8536_IVRB, 	0x00,
153 	Z8536_IVRCT, 	0x20 /* ??? Do we use this? */,
154 
155 	/*
156 	 * Port A specification - bit port, single buffered,
157 	 * latched output, pulsed handshake, all bits non-inverting
158 	 * non-special I/O
159 	 */
160 	Z8536_PMSRA, 	PMSR_PTS_OUT | PMSR_LPM,
161 	Z8536_PHSRA, 	PHSR_HTS_PUL,
162 	Z8536_DPPRA, 	0x00,
163 	Z8536_DDRA, 	0x00,
164 	Z8536_SIOCRA, 	0x00,
165 
166 	/*
167 	 * Port B specification - bit port, transparent output,
168 	 * pulsed handshake, all bits non-inverting
169 	 * bits 0, 4 output; bits 1-3, 5-8 input,
170 	 * non-special I/O
171 	 * Pattern matching: Bit 6 (BUSY) matching "1"
172 	 * Alternatively: Bit 3 (/ACK) matching "0"
173 	 */
174 	Z8536_PMSRB, 	PMSR_PMS_OR_PEV,
175 	Z8536_PHSRB, 	0x00,
176 	Z8536_DPPRB, 	0x00,
177 	Z8536_DDRB, 	0xee /*11101110b*/,
178 	Z8536_SIOCRB, 	0x00,
179 	Z8536_PPRB, 	0x00,
180 	Z8536_PTRB, 	0x00,
181 	Z8536_PMRB, 	0x40 /*01000000b = PB6 */,
182 
183 	Z8536_PDRB, 	0xFE,	/* Assign printer -RESET */
184 	Z8536_PCSRA, 	0x00,	/* Clear port A interrupt bits */
185 
186 	/*
187 	 * Port C specification - bit 3 out, bits 0-2 in,
188 	 * all 4 non-inverting, non-special I/O
189 	 */
190 	Z8536_DDRC, 	0x07 /*00000111b*/,
191 	Z8536_DPPRC, 	0x00,
192 	Z8536_SIOCRC, 	0x00,
193 
194 #ifdef USE_CIO_TIMERS
195 	/*
196 	 * Counter/Timers 1+2 are joined to form a free-running
197 	 * 32 bit timecounter
198 	 */
199 	Z8536_CTMSR1, 	CTMS_CSC,
200 	Z8536_CTTCR1_MSB, 0x00,
201 	Z8536_CTTCR1_LSB, 0x00,
202 	Z8536_CTMSR2, 	CTMS_CSC,
203 	Z8536_CTTCR2_MSB, 0x00,
204 	Z8536_CTTCR2_LSB, 0x00,
205 #endif /* USE_CIO_TIMERS */
206 
207 	/*
208 	 * We need Timer 3 for running port A in strobed mode.
209 	 *
210 	 * Counter/Timer 3 specification -- clear IP & IUS, trigger +
211 	 * gate command bit, one-shot operation
212 	 */
213 	Z8536_CTCSR3, 	CTCS_CLR_IP_IUS | CTCS_GCB | CTCS_TCB,
214 	Z8536_CTMSR3, 	CTMS_DCS_ONESHOT,
215 	Z8536_CTTCR3_MSB, 0x00,
216 	Z8536_CTTCR3_LSB, 0x03,
217 
218 	/*
219 	 * Enable ports A+B+C+CT3
220 	 * Set timer 1 to clock timer 2, but not yet enabled.
221 	 */
222 	Z8536_MCCR,	MCCR_PAE | MCCR_PBE | MCCR_CT1CT2 | MCCR_PC_CT3E,
223 	/* Master Interrupt Enable, Disable Lower Chain,
224 	 * No Vector, port A+B+CT vectors include status */
225 	Z8536_MICR,  	MICR_MIE | MICR_DLC | MICR_NV | MICR_PAVIS |
226 	MICR_PBVIS | MICR_CTVIS,
227 	Z8536_PDRB, 	0xFE,	/* Clear printer -RESET */
228 };
229 
230 
231 /*
232  * Look for Creative Systems Inc. "Hurdler Centronics Parallel Interface"
233  */
234 int
235 cpi_nubus_match(device_t parent, cfdata_t cf, void *aux)
236 {
237 	struct nubus_attach_args *na;
238 
239 	na = aux;
240 	if ((na->category == NUBUS_CATEGORY_COMMUNICATIONS) &&
241 	    (na->type == NUBUS_TYPE_CENTRONICS) &&
242 	    (na->drsw == NUBUS_DRSW_CPI) &&
243 	    (na->drhw == NUBUS_DRHW_CPI))
244 		return 1;
245 	else
246 		return 0;
247 }
248 
249 void
250 cpi_nubus_attach(device_t parent, device_t self, void *aux)
251 {
252 	struct cpi_softc *sc;
253 	struct nubus_attach_args *na;
254 	int err, ii;
255 
256 	sc = device_private(self);
257 	na = aux;
258 	sc->sc_bst = na->na_tag;
259 	memcpy(&sc->sc_slot, na->fmt, sizeof(nubus_slot));
260 	sc->sc_basepa = (bus_addr_t)NUBUS_SLOT2PA(na->slot);
261 
262 	/*
263 	 * The CIO sits on the MSB (top byte lane) of the 32 bit
264 	 * Nubus, so map 16 byte.
265 	 */
266 	if (TRACE_CONFIG) {
267 		printf("\n");
268 		printf("\tcpi_nubus_attach() mapping 8536 CIO at 0x%lx.\n",
269 		    sc->sc_basepa + CIO_BASE_OFFSET);
270 	}
271 
272 	err = bus_space_map(sc->sc_bst, sc->sc_basepa + CIO_BASE_OFFSET,
273 	    (Z8536_IOSIZE << 4), 0, &sc->sc_bsh);
274 	if (err) {
275 		aprint_normal(": failed to map memory space.\n");
276 		return;
277 	}
278 
279 	sc->sc_lpstate = LP_INITIAL;
280 	sc->sc_intcount = 0;
281 	sc->sc_bytestoport = 0;
282 
283 	if (TRACE_CONFIG)
284 		printf("\tcpi_nubus_attach() about to set up 8536 CIO.\n");
285 
286 	for (ii = 0; ii < sizeof(cio_reset); ii += 2)
287 		z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_reset[ii],
288 		    cio_reset[ii + 1]);
289 
290 	delay(1000);		/* Just in case */
291 	for (ii = 0; ii < sizeof(cio_init); ii += 2) {
292 		z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_init[ii],
293 		    cio_init[ii + 1]);
294 	}
295 
296 	if (TRACE_CONFIG)
297 		printf("\tcpi_nubus_attach() done with 8536 CIO setup.\n");
298 
299 	/* XXX Get the information strings from the card's ROM */
300 	aprint_normal(": CSI Hurdler II Centronics\n");
301 
302 #ifdef USE_CIO_TIMERS
303 	/* Attach CIO timers as timecounters */
304 	if (TRACE_CONFIG)
305 		printf("\tcpi_nubus_attach() about to attach timers\n");
306 
307 	cpi_initclock(sc);
308 #endif /* USE_CIO_TIMERS */
309 
310 	callout_init(&sc->sc_wakeupchan, 0);	/* XXX */
311 
312 	/* make sure interrupts are vectored to us */
313 	add_nubus_intr(na->slot, cpi_nubus_intr, sc);
314 }
315 
316 void
317 cpi_nubus_intr(void *arg)
318 {
319         struct cpi_softc *sc;
320 	int s;
321 
322 	sc = (struct cpi_softc *)arg;
323 
324 	s = spltty();
325 
326 	sc->sc_intcount++;
327 
328 	/* Check for interrupt source, and clear interrupt */
329 
330 	/*
331 	 * Clear port A interrupt
332 	 * Interrupt from register A, clear "pending"
333 	 * and set "under service"
334 	 */
335 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
336 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP);
337 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IUS);
338 
339 	cpi_intr(sc);
340 
341 	/* Interrupt from register A, mark serviced */
342 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IUS);
343 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
344 
345 	splx(s);
346 }
347 
348 
349 /* cpi nuts and bolts */
350 
351 int
352 cpi_open(dev_t device, int flag, int mode, struct lwp *l)
353 {
354 	int err, ii, s;
355         struct cpi_softc *sc;
356 
357 	if (TRACE_OPEN)
358 		printf("\tcpi_open() called...\n");
359 
360 	/* Consistency checks: Valid unit number, softc, device state */
361 	sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
362 	if (NULL == sc) {
363 		if (TRACE_OPEN)
364 			printf("Tried to cpi_open() with NULL softc\n");
365 		return ENXIO;
366 	}
367 	if (sc->sc_lpstate != LP_INITIAL) {
368 		if (TRACE_OPEN)
369 			printf("%s not in initial state (%x).\n",
370 			    sc->sc_dev.dv_xname, sc->sc_lpstate);
371 		return EBUSY;
372 	}
373 	sc->sc_lpstate = LP_OPENING;
374 
375 	if (TRACE_OPEN)
376 		printf("\tcpi_open() resetting the printer...\n");
377 	cpi_lpreset(sc);
378 
379 	if (TRACE_OPEN)
380 		printf("\tcpi_open() waiting for printer ready...\n");
381 
382 	/* Wait max 15 sec for printer to get ready */
383 	for (ii = 15; cpi_notready(sc); ii--) {
384 		if (0 == ii) {
385 			sc->sc_lpstate = LP_INITIAL;
386 			return EBUSY;
387 		}
388 		/* sleep for a second, unless we get a signal */
389 		err = ltsleep(sc, PZERO | PCATCH, "cpi_open", hz, NULL);
390 		if (err != EWOULDBLOCK) {
391 			sc->sc_lpstate = LP_INITIAL;
392 			return err;
393 		}
394 	}
395 	if (TRACE_OPEN)
396 		printf("\tcpi_open() allocating printer buffer...\n");
397 
398 	/* Allocate the driver's line buffer */
399 	sc->sc_printbuf = malloc(CPI_BUFSIZE, M_DEVBUF, M_WAITOK);
400 	sc->sc_bufbytes = 0;
401 	sc->sc_lpstate = LP_OPEN;
402 
403 	/* Statistics */
404 	sc->sc_intcount = 0;
405 	sc->sc_bytestoport = 0;
406 
407 	/* Kick off transfer */
408 	cpi_wakeup(sc);
409 
410 	/*
411 	 * Reset "interrupt {pending, under service}" bits, then
412 	 * enable Port A interrupts
413 	 */
414 	s = spltty();
415 
416 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
417 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
418 	splx(s);
419 
420 	if (TRACE_OPEN)
421 		printf("\tcpi_open() done...\n");
422 
423 	return 0;
424 }
425 
426 int
427 cpi_close(dev_t device, int flag, int mode, struct lwp *l)
428 {
429         struct cpi_softc *sc;
430 
431 	sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
432 
433 	if (TRACE_CLOSE)
434 		printf("\tcpi_close() called (%lu hard, %lu bytes to port)\n",
435 		    sc->sc_intcount, sc->sc_bytestoport);
436 
437 	/* Flush the remaining buffer content, ignoring any errors */
438 	if (0 < sc->sc_bufbytes)
439 		(void)cpi_flush(sc);
440 
441 	callout_stop(&sc->sc_wakeupchan);
442 
443 	/* Disable Port A interrupts */
444 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
445 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
446 
447 	sc->sc_lpstate = LP_INITIAL;
448 	free(sc->sc_printbuf, M_DEVBUF);
449 
450 	return 0;
451 }
452 
453 int
454 cpi_write(dev_t device, struct uio *uio, int flags)
455 {
456 	int err;
457 	size_t numbytes;
458         struct cpi_softc *sc;
459 
460 	err = 0;
461 
462 	if (TRACE_WRITE)
463 		printf("\tcpi_write() called for %u bytes\n", uio->uio_resid);
464 
465 	sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
466 
467 	/* Send data to printer, a line buffer full at a time */
468 	while (uio->uio_resid > 0) {
469 		numbytes = min(CPI_BUFSIZE, uio->uio_resid);
470 		sc->sc_cp = sc->sc_printbuf;
471 		uiomove(sc->sc_cp, numbytes, uio);
472 		sc->sc_bufbytes = numbytes;
473 
474 		if (TRACE_WRITE)
475 			printf("\tQueuing %u bytes\n", numbytes);
476 		err = cpi_flush(sc);
477 		if (err) {
478 			/* Failure; adjust residual counter */
479 			if (TRACE_WRITE)
480 				printf("\tQueuing failed with %d\n", err);
481 			uio->uio_resid += sc->sc_bufbytes;
482 			sc->sc_bufbytes = 0;
483 			break;
484 		}
485 	}
486 	return err;
487 }
488 
489 int
490 cpi_ioctl(dev_t device, unsigned long cmd, void *data,
491     int flag, struct lwp *l)
492 {
493 	int err;
494 
495 	err = 0;
496 
497 	if (TRACE_IOCTL)
498 		printf("\tcpi_ioctl() called with %ld...\n", cmd);
499 
500 	switch (cmd) {
501 	default:
502 		if (TRACE_IOCTL)
503 			printf("\tcpi_ioctl() unknown ioctl %ld\n", cmd);
504 		err = ENODEV;
505 		break;
506 	}
507 	return err;
508 }
509 
510 /*
511  * Flush the print buffer that our top half uses to provide data to
512  * our bottom, interrupt-driven half.
513  */
514 static int
515 cpi_flush(struct cpi_softc *sc)
516 {
517 	int err, s;
518 
519 	err = 0;
520 	while (0 < sc->sc_bufbytes) {
521 		/* Feed the printer a char, if it's ready */
522 		if ( !cpi_notready(sc)) {
523 			if (TRACE_WRITE)
524 				printf("\tcpi_flush() writes %u bytes "
525 				    "(%lu hard, %lu bytes to port)\n",
526 				    sc->sc_bufbytes, sc->sc_intcount,
527 				    sc->sc_bytestoport);
528 			s = spltty();
529 			cpi_intr(sc);
530 			splx(s);
531 		}
532 		/* XXX Sure we want to wait forever for the printer? */
533 		err = ltsleep((void *)sc, PZERO | PCATCH,
534 		    "cpi_flush", (60 * hz), NULL);
535 	}
536 	return err;
537 }
538 
539 
540 static void
541 cpi_wakeup(void *param)
542 {
543 	struct cpi_softc *sc;
544 	int s;
545 
546 	sc = param;
547 
548 	s = spltty();
549 	cpi_intr(sc);
550 	splx(s);
551 
552 	callout_reset(&sc->sc_wakeupchan, hz, cpi_wakeup, sc);
553 }
554 
555 
556 static void
557 cpi_lpreset(struct cpi_softc *sc)
558 {
559 	uint8_t portb;		/* Centronics -RESET is on port B, bit 0 */
560 #ifdef DIRECT_PORT_ACCESS
561 	int s;
562 
563 	s = spltty();
564 
565 	portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
566 	bus_space_write_1(sc->sc_bst, sc->sc_bsh,
567 	    CIO_PORTB, portb & ~CPI_RESET);
568 	delay(100);
569 	portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
570 	bus_space_write_1(sc->sc_bst, sc->sc_bsh,
571 	    CIO_PORTB, portb | CPI_RESET);
572 
573 	splx(s);
574 #else
575 	portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
576 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb & ~CPI_RESET);
577 	delay(100);
578 	portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
579 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb | CPI_RESET);
580 #endif /* DIRECT_PORT_ACCESS */
581 }
582 
583 
584 /*
585  * Centronics BUSY 		is on port B, bit 6
586  *	      SELECT		is on Port B, bit 5
587  *	      /FAULT		is on Port B, bit 1
588  *            PAPER EMPTY	is on Port C, bit 1
589  */
590 static int
591 cpi_notready(struct cpi_softc *sc)
592 {
593 	uint8_t portb, portc;
594 	int is_busy, is_select, is_fault, is_paper_empty;
595 
596 	if (TRACE_STATUS)
597 		printf("\tcpi_notready() checking printer status...\n");
598 
599 	portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
600 	if (TRACE_STATUS)
601 		printf("\tPort B has 0x0%X\n", portb);
602 
603 	is_busy = CPI_BUSY & portb;
604 	if (TRACE_STATUS)
605 		printf("\t\tBUSY = %d\n", is_busy);
606 
607 	is_select = CPI_SELECT & portb;
608 	if (TRACE_STATUS)
609 		printf("\t\tSELECT = %d\n", is_select);
610 
611 	is_fault = CPI_FAULT & portb;
612 	if (TRACE_STATUS)
613 		printf("\t\t/FAULT = %d\n", is_fault);
614 
615 	portc = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTC);
616 	if (TRACE_STATUS)
617 		printf("\tPort C has 0x0%X\n", portc);
618 
619 	is_paper_empty = CPI_PAPER_EMPTY & portc;
620 	if (TRACE_STATUS)
621 		printf("\t\tPAPER EMPTY = %d\n", is_paper_empty);
622 
623 	return (is_busy || !is_select || !is_fault || is_paper_empty);
624 }
625 
626 static void
627 cpi_intr(void *arg)
628 {
629 	struct cpi_softc *sc;
630 
631 	sc = arg;
632 
633 	/* Printer ready for output? */
634 	if (cpi_notready(sc))
635 		return;
636 
637 	if (0 && TRACE_WRITE)
638 		printf("\tcpi_soft_intr() has %u bytes.\n", sc->sc_bufbytes);
639 
640 	/* Anything to print? */
641 	if (sc->sc_bufbytes) {
642 		/* Data byte */
643 		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
644 		    CIO_PORTA, *sc->sc_cp++);
645 		sc->sc_bufbytes--;
646 		sc->sc_bytestoport++;
647 	}
648 	if (0 == sc->sc_bufbytes)
649 		/* line buffer empty, wake up our top half */
650 		wakeup((void *)sc);
651 }
652 
653 #ifdef USE_CIO_TIMERS
654 /*
655  * Z8536 CIO timers 1 + 2 used for timecounter(9) support
656  */
657 static void
658 cpi_initclock(struct cpi_softc *sc)
659 {
660 	static struct timecounter cpi_timecounter = {
661 		.tc_get_timecount = cpi_get_timecount,
662 		.tc_poll_pps	  = 0,
663 		.tc_counter_mask  = 0x0ffffu,
664 		.tc_frequency	  = CLK_FREQ,
665 		.tc_name	  = "CPI Z8536 CIO",
666 		.tc_quality	  = 50,
667 		.tc_priv	  = NULL,
668 		.tc_next	  = NULL
669 	};
670 
671 	/*
672 	 * Set up timers A and B as a single, free-running 32 bit counter
673 	 */
674 
675 	/* Disable counters A and B */
676 	reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
677 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
678 	    reg & ~(MCCR_CT1E |�MCCR_CT2E));
679 
680 	/* Make sure interrupt enable bits are cleared */
681 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
682 	    CTCS_CLR_IE);
683 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2,
684 	    CTCS_CLR_IE);
685 
686 	/* Initialise counter start values, and set to continuous cycle */
687 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR1, CTMS_CSC);
688 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_MSB, 0x00);
689 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_LSB, 0x00);
690 
691 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR2, CTMS_CSC);
692 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_MSB, 0x00);
693 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_LSB, 0x00);
694 
695 	/* Re-enable counters A and B */
696 	reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
697 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
698 	    reg |�MCCR_CT1E |�MCCR_CT2E |�MCCR_CT1CT2);
699 
700 	/* Start counters A and B */
701 	reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
702 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
703 	    reg | CTCS_TCB);
704 	reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
705 	z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2,
706 	    reg |�CTCS_TCB);
707 
708 	tc_init(&cpi_timecounter);
709 }
710 
711 static u_int
712 cpi_get_timecount(struct timecounter *tc)
713 {
714 	uint8_t high, high2, low;
715 	int s;
716 
717 	/*
718 	 * Make the timer access atomic
719 	 *
720 	 * XXX How expensive is this? And is it really necessary?
721 	 */
722 	s = splhigh();
723 
724 	/* TBD */
725 
726 }
727 #endif /* USE_CIO_TIMERS */
728 
729 
730 /*
731  * Z8536 CIO nuts and bolts
732  */
733 
734 static inline void
735 z8536_reg_set(bus_space_tag_t bspace, bus_space_handle_t bhandle,
736     uint8_t reg, uint8_t val)
737 {
738 	int s;
739 
740 	s = splhigh();
741 	bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
742 	delay(1);
743 	bus_space_write_1(bspace, bhandle, CIO_CTRL, val);
744 	splx(s);
745 }
746 
747 static inline uint8_t
748 z8536_reg_get(bus_space_tag_t bspace, bus_space_handle_t bhandle, uint8_t reg)
749 {
750 	int s;
751 	uint8_t val;
752 
753 	s = splhigh();
754 	bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
755 	delay(1);
756 	val = bus_space_read_1(bspace, bhandle, CIO_CTRL);
757 	splx(s);
758 
759 	return val;
760 }
761