freebsd-dev/sys/dev/sx/sx_util.h
Warner Losh 7134a2219c Frank Mayhar's <frank@exit.com> sx driver for older Specialix
I/O8+ and I/O4+ intelligent serial controllers.  si is for
completely different hardware, also made by Specialix.
2004-04-11 19:32:20 +00:00

160 lines
4.5 KiB
C

/*
* Device driver for Specialix I/O8+ multiport serial card.
*
* Copyright 2003 Frank Mayhar <frank@exit.com>
*
* Derived from the "si" driver by Peter Wemm <peter@netplex.com.au>, using
* lots of information from the Linux "specialix" driver by Roger Wolff
* <R.E.Wolff@BitWizard.nl> and from the Intel CD1865 "Intelligent Eight-
* Channel Communications Controller" datasheet. Roger was also nice
* enough to answer numerous questions about stuff specific to the I/O8+
* not covered by the CD1865 datasheet.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notices, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notices, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE.
*
* $FreeBSD$
*/
/* Utility functions and macros for the Specialix I/O8+ driver. */
/*
* sx_cd1865_out()
* Write a CD1865 register on the card.
*/
static __inline void
sx_cd1865_out(
struct sx_softc *sc,
unsigned int reg,
unsigned char val)
{
bus_space_write_1(sc->sc_st, sc->sc_sh, SX_ADDR_REG, reg);
bus_space_write_1(sc->sc_st, sc->sc_sh, SX_DATA_REG, val);
}
/*
* sx_cd1865_in()
* Read a register from the card.
*/
static __inline unsigned char
sx_cd1865_in(
struct sx_softc *sc,
unsigned int reg)
{
bus_space_write_1(sc->sc_st, sc->sc_sh, SX_ADDR_REG, reg);
return(bus_space_read_1(sc->sc_st, sc->sc_sh, SX_DATA_REG));
}
/*
* sx_cd1865_bis()
* Set bits in a CD1865 register.
*/
static __inline void
sx_cd1865_bis(
struct sx_softc *sc,
unsigned int reg,
unsigned char bits)
{
register unsigned char rval;
rval = sx_cd1865_in(sc, reg);
rval |= bits;
sx_cd1865_out(sc, reg, rval);
}
/*
* sx_cd1865_bic()
* Clear bits in a CD1865 register.
*/
static __inline void
sx_cd1865_bic(
struct sx_softc *sc,
unsigned int reg,
unsigned char bits)
{
register unsigned char rval;
rval = sx_cd1865_in(sc, reg);
rval &= ~bits;
sx_cd1865_out(sc, reg, rval);
}
/*
* sx_cd1865_wait_CCR()
* Spin waiting for the board Channel Command Register to clear.
*
* Description:
* The CD1865 processor clears the Channel Command Register to
* indicate that it has completed the last command. This routine
* waits for the CCR to become zero by watching the register,
* delaying ten microseconds between each check. We time out after
* ten milliseconds (or SX_CCR_TIMEOUT microseconds).
*/
static __inline void
sx_cd1865_wait_CCR(
struct sx_softc *sc,
unsigned int ei_flag)
{
unsigned int to = SX_CCR_TIMEOUT/10;
while (to-- > 0) {
if (sx_cd1865_in(sc, CD1865_CCR|ei_flag) == 0)
return;
DELAY(10);
}
printf("sx: Timeout waiting for CCR to clear.\n");
}
/*
* sx_cd1865_etcmode()
* Set or clear embedded transmit command mode on a CD1865 port.
*
* Description:
* We can use commands embedded in the transmit data stream to do
* things like start and stop breaks or insert time delays. We normally
* run with embedded commands disabled; this routine selects the channel
* we're dealing with and enables or disables embedded commands depending
* on the flag passed to it. The caller must remember this state and
* escape any NULs it sends while embedded commands are enabled.
* Should be called at spltty(). Disables interrupts for the duration
* of the routine.
*/
static __inline void
sx_cd1865_etcmode(
struct sx_softc *sc,
unsigned int ei_flag,
int chan,
int mode)
{
sx_cd1865_out(sc, CD1865_CAR|ei_flag, chan); /* Select channel. */
if (mode) { /* Enable embedded commands? */
sx_cd1865_bis(sc, CD1865_COR2|ei_flag, CD1865_COR2_ETC);
}
else {
sx_cd1865_bic(sc, CD1865_COR2|ei_flag, CD1865_COR2_ETC);
}
/*
* Wait for the CCR to clear, ding the card, let it know stuff
* changed, then wait for CCR to clear again.
*/
sx_cd1865_wait_CCR(sc, ei_flag);
sx_cd1865_out(sc, CD1865_CCR|ei_flag, CD1865_CCR_CORCHG2);
sx_cd1865_wait_CCR(sc, ei_flag);
}
int sx_probe_io8(device_t dev);
int sx_init_cd1865(struct sx_softc *sc, int unit);
struct sx_port *sx_int_port(struct sx_softc *sc, int unit);