#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,v 1.11 2020/12/19 21:48:04 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/device.h>
#include <sys/kmem.h>
#include <sys/event.h>
#include <sys/callout.h>
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/time.h>
#include <sys/timetc.h>
#include <sys/kernel.h>
#include <sys/syslog.h>
#include <sys/errno.h>
#include <machine/intr.h>
#include <machine/bus.h>
#include <machine/viareg.h>
#include <dev/ic/z8536reg.h>
#include <mac68k/nubus/nubus.h>
#include <mac68k/nubus/cpi_nubusvar.h>
#include "ioconf.h"
#ifdef DEBUG
#define CPI_DEBUG
#endif
#ifdef CPI_DEBUG
#define M_TRACE_CONFIG 0x0001
#define M_TRACE_OPEN 0x0002
#define M_TRACE_CLOSE 0x0004
#define M_TRACE_READ 0x0008
#define M_TRACE_WRITE 0x0010
#define M_TRACE_IOCTL 0x0020
#define M_TRACE_STATUS 0x0040
#define M_TRACE_TCNTR 0x0080
#define M_TRACE_ALL 0xFFFF
#define M_TRACE_NONE 0x0000
#define TRACE_CONFIG (cpi_debug_mask & M_TRACE_CONFIG)
#define TRACE_OPEN (cpi_debug_mask & M_TRACE_OPEN)
#define TRACE_CLOSE (cpi_debug_mask & M_TRACE_CLOSE)
#define TRACE_READ (cpi_debug_mask & M_TRACE_READ)
#define TRACE_WRITE (cpi_debug_mask & M_TRACE_WRITE)
#define TRACE_IOCTL (cpi_debug_mask & M_TRACE_IOCTL)
#define TRACE_STATUS (cpi_debug_mask & M_TRACE_STATUS)
#define TRACE_TCNTR (cpi_debug_mask & M_TRACE_TCNTR)
#define TRACE_ALL (cpi_debug_mask & M_TRACE_ALL)
#define TRACE_NONE (cpi_debug_mask & M_TRACE_NONE)
uint32_t cpi_debug_mask = M_TRACE_NONE ;
#else
#define TRACE_CONFIG 0
#define TRACE_OPEN 0
#define TRACE_CLOSE 0
#define TRACE_READ 0
#define TRACE_WRITE 0
#define TRACE_IOCTL 0
#define TRACE_STATUS 0
#define TRACE_TCNTR 0
#define TRACE_ALL 0
#define TRACE_NONE 0
#endif
int cpi_nubus_match(device_t, cfdata_t, void *);
void cpi_nubus_attach(device_t, device_t, void *);
void cpi_nubus_intr(void *);
CFATTACH_DECL_NEW(cpi, sizeof(struct cpi_softc),
cpi_nubus_match, cpi_nubus_attach, NULL, NULL);
dev_type_open(cpi_open);
dev_type_close(cpi_close);
dev_type_read(cpi_read);
dev_type_write(cpi_write);
dev_type_ioctl(cpi_ioctl);
const struct cdevsw cpi_cdevsw = {
.d_open = cpi_open,
.d_close = cpi_close,
.d_read = noread,
.d_write = cpi_write,
.d_ioctl = cpi_ioctl,
.d_stop = nostop,
.d_tty = notty,
.d_poll = nopoll,
.d_mmap = nommap,
.d_kqfilter = nokqfilter,
.d_discard = nodiscard,
.d_flag = D_OTHER
};
static void cpi_lpreset(struct cpi_softc *);
static int cpi_notready(struct cpi_softc *);
static void cpi_wakeup(void *);
static int cpi_flush(struct cpi_softc *);
static void cpi_intr(void *);
static void cpi_tc_initclock(struct cpi_softc *);
static uint cpi_get_timecount(struct timecounter *);
static uint z8536_read_counter1(bus_space_tag_t, bus_space_handle_t);
static uint z8536_read_counter2(bus_space_tag_t, bus_space_handle_t);
static void z8536_reg_set(bus_space_tag_t, bus_space_handle_t,
uint8_t, uint8_t);
static uint8_t z8536_reg_get(bus_space_tag_t, bus_space_handle_t,
uint8_t);
const uint8_t cio_reset[] = {
Z8536_MICR, 0x00,
Z8536_MICR, MICR_RESET,
Z8536_MICR, 0x00
};
const uint8_t cio_init[] = {
Z8536_IVRA, 0x00,
Z8536_IVRB, 0x00,
Z8536_IVRCT, 0x20 ,
Z8536_PMSRA, PMSR_PTS_OUT | PMSR_LPM,
Z8536_PHSRA, PHSR_HTS_PUL,
Z8536_DPPRA, 0x00,
Z8536_DDRA, 0x00,
Z8536_SIOCRA, 0x00,
Z8536_PMSRB, PMSR_PMS_OR_PEV,
Z8536_PHSRB, 0x00,
Z8536_DPPRB, 0x00,
Z8536_DDRB, 0xee ,
Z8536_SIOCRB, 0x00,
Z8536_PPRB, 0x00,
Z8536_PTRB, 0x00,
Z8536_PMRB, 0x40 ,
Z8536_PDRB, 0xFE,
Z8536_PCSRA, 0x00,
Z8536_DDRC, 0x07 ,
Z8536_DPPRC, 0x00,
Z8536_SIOCRC, 0x00,
Z8536_CTCSR3, CTCS_CLR_IP_IUS | CTCS_GCB | CTCS_TCB,
Z8536_CTMSR3, CTMS_DCS_ONESHOT,
Z8536_CTTCR3_MSB, 0x00,
Z8536_CTTCR3_LSB, 0x03,
Z8536_MCCR, MCCR_PAE | MCCR_PBE | MCCR_PC_CT3E,
Z8536_MICR, MICR_MIE | MICR_DLC | MICR_NV | MICR_PAVIS |
MICR_PBVIS | MICR_CTVIS,
Z8536_PDRB, 0xFE,
};
int
cpi_nubus_match(device_t parent, cfdata_t cf, void *aux)
{
struct nubus_attach_args *na;
na = aux;
if ((na->category == NUBUS_CATEGORY_COMMUNICATIONS) &&
(na->type == NUBUS_TYPE_CENTRONICS) &&
(na->drsw == NUBUS_DRSW_CPI) &&
(na->drhw == NUBUS_DRHW_CPI))
return 1;
else
return 0;
}
void
cpi_nubus_attach(device_t parent, device_t self, void *aux)
{
struct cpi_softc *sc;
struct nubus_attach_args *na;
int err, ii;
sc = device_private(self);
sc->sc_options = (device_cfdata(self)->cf_flags & CPI_OPTIONS_MASK);
na = aux;
sc->sc_bst = na->na_tag;
memcpy(&sc->sc_slot, na->fmt, sizeof(nubus_slot));
sc->sc_basepa = (bus_addr_t)NUBUS_SLOT2PA(na->slot);
if (TRACE_CONFIG) {
printf("\n");
printf("\tcpi_nubus_attach() mapping 8536 CIO at 0x%lx.\n",
sc->sc_basepa + CIO_BASE_OFFSET);
}
err = bus_space_map(sc->sc_bst, sc->sc_basepa + CIO_BASE_OFFSET,
(Z8536_IOSIZE << 4), 0, &sc->sc_bsh);
if (err) {
aprint_normal(": failed to map memory space.\n");
return;
}
sc->sc_lpstate = LP_INITIAL;
sc->sc_intcount = 0;
sc->sc_bytestoport = 0;
if (TRACE_CONFIG)
printf("\tcpi_nubus_attach() about to set up 8536 CIO.\n");
for (ii = 0; ii < sizeof(cio_reset); ii += 2)
z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_reset[ii],
cio_reset[ii + 1]);
delay(1000);
for (ii = 0; ii < sizeof(cio_init); ii += 2) {
z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_init[ii],
cio_init[ii + 1]);
}
if (TRACE_CONFIG)
printf("\tcpi_nubus_attach() done with 8536 CIO setup.\n");
aprint_normal(": CSI Hurdler II Centronics\n");
if (sc->sc_options & CPI_CTC12_IS_TIMECOUNTER) {
cpi_tc_initclock(sc);
}
callout_init(&sc->sc_wakeupchan, 0);
add_nubus_intr(na->slot, cpi_nubus_intr, sc);
}
void
cpi_nubus_intr(void *arg)
{
struct cpi_softc *sc;
int s;
sc = (struct cpi_softc *)arg;
s = spltty();
sc->sc_intcount++;
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IUS);
cpi_intr(sc);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IUS);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
splx(s);
}
int
cpi_open(dev_t device, int flag, int mode, struct lwp *l)
{
int err, ii, s;
struct cpi_softc *sc;
if (TRACE_OPEN)
printf("\tcpi_open() called...\n");
sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
if (NULL == sc) {
if (TRACE_OPEN)
printf("Tried to cpi_open() with NULL softc\n");
return ENXIO;
}
if (sc->sc_lpstate != LP_INITIAL) {
if (TRACE_OPEN)
printf("Not in initial state (%x).\n",
sc->sc_lpstate);
return EBUSY;
}
sc->sc_lpstate = LP_OPENING;
if (TRACE_OPEN)
printf("\tcpi_open() resetting the printer...\n");
cpi_lpreset(sc);
if (TRACE_OPEN)
printf("\tcpi_open() waiting for printer ready...\n");
for (ii = 15; cpi_notready(sc); ii--) {
if (0 == ii) {
sc->sc_lpstate = LP_INITIAL;
return EBUSY;
}
err = tsleep(sc, PZERO | PCATCH, "cpi_open", hz);
if (err != EWOULDBLOCK) {
sc->sc_lpstate = LP_INITIAL;
return err;
}
}
if (TRACE_OPEN)
printf("\tcpi_open() allocating printer buffer...\n");
sc->sc_printbuf = kmem_alloc(CPI_BUFSIZE, KM_SLEEP);
sc->sc_bufbytes = 0;
sc->sc_lpstate = LP_OPEN;
sc->sc_intcount = 0;
sc->sc_bytestoport = 0;
cpi_wakeup(sc);
s = spltty();
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
splx(s);
if (TRACE_OPEN)
printf("\tcpi_open() done...\n");
return 0;
}
int
cpi_close(dev_t device, int flag, int mode, struct lwp *l)
{
struct cpi_softc *sc;
sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
if (TRACE_CLOSE)
printf("\tcpi_close() called (%lu hard, %lu bytes to port)\n",
sc->sc_intcount, sc->sc_bytestoport);
if (0 < sc->sc_bufbytes)
(void)cpi_flush(sc);
callout_stop(&sc->sc_wakeupchan);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
sc->sc_lpstate = LP_INITIAL;
kmem_free(sc->sc_printbuf, CPI_BUFSIZE);
return 0;
}
int
cpi_write(dev_t device, struct uio *uio, int flags)
{
int err;
size_t numbytes;
struct cpi_softc *sc;
err = 0;
if (TRACE_WRITE)
printf("\tcpi_write() called for %u bytes\n", uio->uio_resid);
sc = device_lookup_private(&cpi_cd, CPI_UNIT(device));
while (uio->uio_resid > 0) {
numbytes = uimin(CPI_BUFSIZE, uio->uio_resid);
sc->sc_cp = sc->sc_printbuf;
uiomove(sc->sc_cp, numbytes, uio);
sc->sc_bufbytes = numbytes;
if (TRACE_WRITE)
printf("\tQueuing %u bytes\n", numbytes);
err = cpi_flush(sc);
if (err) {
if (TRACE_WRITE)
printf("\tQueuing failed with %d\n", err);
uio->uio_resid += sc->sc_bufbytes;
sc->sc_bufbytes = 0;
break;
}
}
return err;
}
int
cpi_ioctl(dev_t device, unsigned long cmd, void *data,
int flag, struct lwp *l)
{
int err;
err = 0;
if (TRACE_IOCTL)
printf("\tcpi_ioctl() called with %ld...\n", cmd);
switch (cmd) {
default:
if (TRACE_IOCTL)
printf("\tcpi_ioctl() unknown ioctl %ld\n", cmd);
err = ENODEV;
break;
}
return err;
}
static int
cpi_flush(struct cpi_softc *sc)
{
int err, s;
err = 0;
while (0 < sc->sc_bufbytes) {
if ( !cpi_notready(sc)) {
if (TRACE_WRITE)
printf("\tcpi_flush() writes %u bytes "
"(%lu hard, %lu bytes to port)\n",
sc->sc_bufbytes, sc->sc_intcount,
sc->sc_bytestoport);
s = spltty();
cpi_intr(sc);
splx(s);
}
err = tsleep((void *)sc, PZERO | PCATCH,
"cpi_flush", (60 * hz));
}
return err;
}
static void
cpi_wakeup(void *param)
{
struct cpi_softc *sc;
int s;
sc = param;
s = spltty();
cpi_intr(sc);
splx(s);
callout_reset(&sc->sc_wakeupchan, hz, cpi_wakeup, sc);
}
static void
cpi_lpreset(struct cpi_softc *sc)
{
uint8_t portb;
portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb & ~CPI_RESET);
delay(100);
portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb | CPI_RESET);
}
static int
cpi_notready(struct cpi_softc *sc)
{
uint8_t portb, portc;
int is_busy, is_select, is_fault, is_paper_empty;
if (TRACE_STATUS)
printf("\tcpi_notready() checking printer status...\n");
portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
if (TRACE_STATUS)
printf("\tPort B has 0x0%X\n", portb);
is_busy = CPI_BUSY & portb;
if (TRACE_STATUS)
printf("\t\tBUSY = %d\n", is_busy);
is_select = CPI_SELECT & portb;
if (TRACE_STATUS)
printf("\t\tSELECT = %d\n", is_select);
is_fault = CPI_FAULT & portb;
if (TRACE_STATUS)
printf("\t\t/FAULT = %d\n", is_fault);
portc = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTC);
if (TRACE_STATUS)
printf("\tPort C has 0x0%X\n", portc);
is_paper_empty = CPI_PAPER_EMPTY & portc;
if (TRACE_STATUS)
printf("\t\tPAPER EMPTY = %d\n", is_paper_empty);
return (is_busy || !is_select || !is_fault || is_paper_empty);
}
static void
cpi_intr(void *arg)
{
struct cpi_softc *sc;
sc = arg;
if (cpi_notready(sc))
return;
if (0 && TRACE_WRITE)
printf("\tcpi_soft_intr() has %u bytes.\n", sc->sc_bufbytes);
if (sc->sc_bufbytes) {
bus_space_write_1(sc->sc_bst, sc->sc_bsh,
CIO_PORTA, *sc->sc_cp++);
sc->sc_bufbytes--;
sc->sc_bytestoport++;
}
if (0 == sc->sc_bufbytes)
wakeup((void *)sc);
}
static void
cpi_tc_initclock(struct cpi_softc *sc)
{
uint8_t reg;
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
reg & ~(MCCR_CT1E | MCCR_CT2E));
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1, CTCS_CLR_IE);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2, CTCS_CLR_IE);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR1,
CTMS_CSC | CTMS_DCS_PULSE);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_MSB, 0x00);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_LSB, 0x00);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR2,
CTMS_CSC | CTMS_DCS_PULSE);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_MSB, 0x00);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_LSB, 0x00);
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR, reg | MCCR_CT1CT2);
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
reg | (MCCR_CT1E | MCCR_CT2E));
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
CTCSR_MASK(reg | CTCS_TCB | CTCS_GCB));
if (TRACE_TCNTR) {
printf("Before tc_init():\n");
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
printf("Counter 1 CTCSR setup bits are 0x%03x\n", reg);
printf("Counter 1 (LSW) is now 0x%05x\n",
z8536_read_counter1(sc->sc_bst, sc->sc_bsh));
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
printf("Counter 2 CTCSR setup bits are 0x%03x\n", reg);
printf("Counter 2 (MSW) is now 0x%05x\n",
z8536_read_counter2(sc->sc_bst, sc->sc_bsh));
delay(1000);
}
sc->sc_timecounter.tc_get_timecount = cpi_get_timecount;
sc->sc_timecounter.tc_poll_pps = 0;
sc->sc_timecounter.tc_counter_mask = ~0u;
sc->sc_timecounter.tc_frequency = CPI_CLK_FREQ;
sc->sc_timecounter.tc_name = "Nubus CPI";
sc->sc_timecounter.tc_quality = 1000;
sc->sc_timecounter.tc_priv = sc;
sc->sc_timecounter.tc_next = NULL;
tc_init(&(sc->sc_timecounter));
if (TRACE_TCNTR) {
delay(1000);
printf("After tc_init():\n");
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
printf("Counter 1 CTCSR setup bits are 0x%03x\n", reg);
printf("Counter 1 (LSW) is now 0x%05x\n",
z8536_read_counter1(sc->sc_bst, sc->sc_bsh));
reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
printf("Counter 2 CTCSR setup bits are 0x%03x\n", reg);
printf("Counter 2 (MSW) is now 0x%05x\n",
z8536_read_counter2(sc->sc_bst, sc->sc_bsh));
}
}
static u_int
cpi_get_timecount(struct timecounter *tc)
{
int s;
uint msw, msw2, lsw;
uint8_t reg;
bus_space_tag_t bst;
bus_space_handle_t bsh;
bst = ((struct cpi_softc *)tc->tc_priv)->sc_bst;
bsh = ((struct cpi_softc *)tc->tc_priv)->sc_bsh;
do {
#define delay(a)
s = splhigh();
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
delay(1);
reg = bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_MSB);
delay(1);
msw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_LSB);
delay(1);
msw |= bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
delay(1);
reg = bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg |CTCS_RCC));
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_MSB);
delay(1);
lsw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_LSB);
delay(1);
lsw |= bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
delay(1);
reg = bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_MSB);
delay(1);
msw2 = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_LSB);
delay(1);
msw2 |= bus_space_read_1(bst, bsh, CIO_CTRL);
splx(s);
} while (msw2 != msw);
return ~0u - ((msw << 16) | lsw);
}
static uint
z8536_read_counter1(bus_space_tag_t bst, bus_space_handle_t bsh)
{
uint8_t reg;
uint32_t lsw;
int s;
s = splhigh();
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
delay(1);
reg = bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_MSB);
delay(1);
lsw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_LSB);
delay(1);
lsw |= bus_space_read_1(bst, bsh, CIO_CTRL);
splx(s);
return lsw;
}
static uint
z8536_read_counter2(bus_space_tag_t bst, bus_space_handle_t bsh)
{
uint8_t reg;
uint32_t msw;
int s;
s = splhigh();
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
delay(1);
reg = bus_space_read_1(bst, bsh, CIO_CTRL);
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_MSB);
delay(1);
msw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_LSB);
delay(1);
msw |= bus_space_read_1(bst, bsh, CIO_CTRL);
splx(s);
return msw;
}
static void
z8536_reg_set(bus_space_tag_t bspace, bus_space_handle_t bhandle,
uint8_t reg, uint8_t val)
{
int s;
s = splhigh();
bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
delay(1);
bus_space_write_1(bspace, bhandle, CIO_CTRL, val);
splx(s);
}
static uint8_t
z8536_reg_get(bus_space_tag_t bspace, bus_space_handle_t bhandle, uint8_t reg)
{
int s;
uint8_t val;
s = splhigh();
bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
delay(1);
val = bus_space_read_1(bspace, bhandle, CIO_CTRL);
splx(s);
return val;
}