Date: Fri, 10 Mar 1995 01:33:47 -0800 (PST) From: brian@MediaCity.Com (Brian Litzinger) To: freebsd-hackers@FreeBSD.org Subject: Cyclades driver looking for advice Message-ID: <m0rn14t-000rcJC@easynet.com>
next in thread | raw e-mail | index | archive | help
Hi Hackers,
This driver which I original ported to BSDI 1.1 and which works under
BSD/OS 2.0 just doesn't work so well under FreeBSD 2.1.0-Development.
I've hacked it to fit most of the FreeBSDisms. And it works somewhat.
All the ports are identified, and I can talk with them. However, after
10 to 60 seconds of interacting with some BBS. I get
panic: page fault
with a stack trace that looks like this:
IdlePTD 1f4000
panic: page fault
current pcb at 1e3e98
Reading in symbols for ../../i386/i386/machdep.c...done.
(kgdb) where
#0 boot (arghowto=256) (../../i386/i386/machdep.c line 754)
#1 0xf01120a3 in panic (...)
#2 0xf01976e2 in trap_fatal (...)
#3 0xf0197254 in trap_pfault (...)
#4 0xf0196f17 in trap (...)
#5 0xf018d4c1 in exception:calltrap (-266445148, -272630272, 92)
#6 0xf0118123 in ptcread (...)
#7 0xf012be10 in spec_read (...)
#8 0xf017d685 in ufsspec_read (...)
#9 0xf01294ac in vn_read (...)
#10 0xf011313f in sys_generic:__gnu_compiled_c (...)
#11 0xf01978cb in syscall (...)
I also sometimes get a 'botched clist reservation' panic, which happens
in some device other than my cyb driver.
I assume this means that my driver must somewhere be writing over
parts of memory it isn't supposed to.
Before delving into this any further I though I'd beg the indulgence
of one or more of you FreeBSD experts to look over the code and point out
any obvious mistakes that I may have made.
I suspect that I may be trying to access something in a context that I'm
not allowed to that is FreeBSD specific.
Thanks,
Brian Litzinger
brian@easynet.com
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# readme.src
# cyb.c
# cl-cd1400.h
# cyreg.h
#
echo x - readme.src
sed 's/^X//' >readme.src << 'END-of-readme.src'
XCyclades Cyclom 8Y/8Yo/16Y driver for FreeBSD 2.0
X
XBy Brian E. Litzinger (more or less) <brian@mpress.com>
X
XCopyright 1995 By Brian E. Litzinger
X
X
XThis driver may be used for educational or commericial uses
Xat no cost.
X
XThis driver may be used commercially at no cost when used
Xwith the FreeBSD Operating System.
X
XNo other uses are permitted.
X
XThis driver is provided as-is.
X
X--------------------------------------------------------------------
X
XYou must reverse the sense of RTS and DTR in the Cyclades manual!
X
XThis driver reverses their usage to correctly implement full duplex
Xhardware handshaking.
X
XWhich means, there is no DTR on the 8Y RJ12 connector. The DTR pin
Xin the manual becomes RTS. DTR does exist in the 16Y and the 8Yo.
X
XThe following assumes the kernel stuff is under the /sys directory and
Xthe paths are relative to that directory.
X
X[Installation directions are temporarily unavailable]
X
XBest of luck.
X
XBrian Litzinger <brian@easynet.com>
XP.O. Box 82 (old addr <brian@apt.bungi.com> still works)
XBoulder Creek, CA 95006
END-of-readme.src
echo x - cyb.c
sed 's/^X//' >cyb.c << 'END-of-cyb.c'
X/*-
X * Copyright (c) 1995 By Brian E. Litzinger. All rights reserved.
X *
X * <brian@mpress.com>
X */
X
X/*
X We'll call this share-source.
X
X You may use it for free for personal or educational use.
X
X You may use it in commercial applications for free if you
X buy your Cyclades cards from: bobe@MediaCity.Com
X He can sell you cyclades product for the same price that
X Cyclades offers you.
X
X Other commercial use is prohibited. Though you can email
X me with other uses you may have. <brian@mpress.com>
X
X*/
X/*
X * cyclades
X */
X
X#include "cyb.h"
X#if NCYB > 0
X/* #define CYDEBUG 1 */
X
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/ioctl.h>
X#include <sys/tty.h>
X#include <sys/proc.h>
X#include <sys/user.h>
X#include <sys/conf.h>
X#include <sys/file.h>
X#include <sys/uio.h>
X#include <sys/kernel.h>
X#include <sys/syslog.h>
X#include <sys/device.h>
X#include "sys/devconf.h"
X
X#include "machine/cpufunc.h"
X#include "machine/clock.h"
X
X#include "i386/isa/isa.h"
X#include "i386/isa/isa_device.h"
X#include "i386/isa/icu.h"
X
X#include "i386/isa/cyreg.h"
X#include "i386/isa/cl-cd1400.h"
X
X#define POLLSLICE 100 /*ms*/
X
X
X#define dprintf(x) /* */
X#define UNIT(dev) (((dev)>>5)&0x03)
X#define LINE(dev) ((dev)&0x1f)
X
X#define MAX_CHAN 16
X
Xstruct tty cyb_tty[MAX_CHAN]; /* Per-channel tty structures */
X
Xstruct cybsoftc {
X short cy_softdtr; /* software copy of DTR */
X short cy_txint; /* TX interrupt is in progress */
X short cy_inintr; /* Interrupt in progess */
X short cy_pollactive; /* Polling active */
X caddr_t cy_addr[MAX_CHAN]; /* base i/o address */
X char cy_init[MAX_CHAN]; /* line has been inited since reset */
X char cy_cmd[MAX_CHAN]; /* command bytes per channels */
X char cy_pendesc[MAX_CHAN]; /* pending escapes */
X u_int cy_orun[MAX_CHAN]; /* overruns */
X unsigned char cy_srer[MAX_CHAN];
X caddr_t cy_base;
X int cy_NbrCD1400s;
X int cy_NbrPorts;
X struct kern_devconf kdc; /* kernel configuration database info */
X} cybsoftc[NCYB];
X
X/*
X * cybmctl commands
X */
Xenum cybmctl_cmds { GET, SET, BIS, BIC };
X
Xint cybprobe __P((struct isa_device *));
Xint cybattach __P((struct isa_device *));
Xint cybopen __P((dev_t, int, int, struct proc *));
Xint cybclose __P((dev_t, int, int, struct proc *));
Xint cybread __P((dev_t, struct uio *, int));
Xint cybwrite __P((dev_t, struct uio *, int));
Xvoid cybintr __P((int));
Xvoid cybstart __P((struct tty *));
Xint cybioctl __P((dev_t, int, caddr_t, int, struct proc *));
Xstatic void cybchancmd __P((caddr_t, int));
Xint cybparam __P((struct tty *, struct termios *));
Xint cybselect __P((dev_t, int, struct proc *));
Xvoid cybstop __P((struct tty *, int));
Xstatic void cybcd1400init __P((int));
Xstatic int cybmctl __P((dev_t, enum cybmctl_cmds, int));
Xstatic int cybspeed __P((long, int *));
Xstatic void cybpoll();
X
Xstruct isa_driver cybdriver = { cybprobe, cybattach, "cyb" };
X
Xstatic struct kern_devconf kdc_tm_template = {
X 0, 0, 0, /* filled in by dev_attach */
X "cyb", 0, { MDDT_ISA, 0, "tty" },
X isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
X &kdc_isa0, /* parent */
X 0, /* parentdata */
X DC_UNCONFIGURED,
X "Cyclades-BEL" /* description */
X};
X
X
Xstatic inline void
Xcyb_registerdev(struct isa_device *id, const char *descr)
X{
X struct kern_devconf *kdc = &cybsoftc[id->id_unit].kdc;
X char *longdescr;
X *kdc = kdc_tm_template;
X kdc->kdc_unit = id->id_unit;
X kdc->kdc_parentdata = id;
X kdc->kdc_description = descr;
X dev_attach(kdc);
X}
X
X/*
X * Probe routine
X */
Xint
Xcybprobe(struct isa_device *isa_dev) {
X struct cybsoftc *sc = &cybsoftc[isa_dev->id_unit];
X
X int i,j;
X caddr_t b;
X int flags;
X int ports;
X int NbrCD1400s;
X unsigned char version;
X
X
X cyb_registerdev(isa_dev,"Cyclades-BEL");
X
X#define TEST_FOR_NbrCD1400s 4
X
X NbrCD1400s = 0;
X
X b = isa_dev->id_maddr;
X
X (void) rinb(b,cy_RESET_16);
X DELAY(500);
X
X for (i=0; i<TEST_FOR_NbrCD1400s; i++) {
X caddr_t base = b + i * CD1400_MEMSIZE;
X
X /* wait for chip to become ready for new command */
X for (j = 0; j < 500; j += 50) {
X DELAY(50); /* wait 50 us */
X if (!rinb(base,CD1400_CCR)) {
X break;
X }
X }
X
X /* clear the GFRCR register */
X routb(base,CD1400_GFRCR,0);
X
X /* issue a reset command */
X routb(base,CD1400_CCR,CCR_HARDRESET);
X
X /* wait for the CD1400 to initialize itself */
X for (j = 0; j < 10000; j += 50) {
X DELAY(50); /* wait 50 us */
X
X /* retrieve firmware version */
X version = rinb(base,CD1400_GFRCR);
X if ((version&0xf0)==0x40)
X break;
X }
X
X printf("cy returned %x\n",version);
X /* anything in the 40-4f range is fine */
X if ((version & 0xf0) == 0x40) {
X NbrCD1400s++;
X } else {
X break;
X }
X }
X sc->cy_NbrCD1400s = NbrCD1400s;
X return (NbrCD1400s>0);
X}
X
X/*
X * Attach routine
X */
Xint
Xcybattach(struct isa_device *isa_dev) {
X register struct cybsoftc *sc = &cybsoftc[isa_dev->id_unit];
X register caddr_t base;
X caddr_t b;
X int flags;
X int i,j,k;
X
X
X sc->cy_NbrPorts = sc->cy_NbrCD1400s * 4;
X printf(" ports %d",sc->cy_NbrPorts);
X
X
X sc->cy_base = b = isa_dev->id_maddr;
X
X for (i=0,k=0;i<sc->cy_NbrCD1400s;i++) {
X base = b + i * CD1400_MEMSIZE;
X routb(base, CD1400_PPR, CD1400_CLOCK_25_1MS);
X for (j=0;j<CD1400_NO_OF_CHANNELS;j++,k++) {
X sc->cy_addr[k] = base;
X /* cy_channel_init */
X routb(base, CD1400_CAR, j&0x03);
X cybchancmd(base,CCR_SOFTRESET);
X routb(base, CD1400_LIVR, 0);
X }
X }
X
X routb(b,cy_CLEAR_INTR,0); /* Clear interrupts */
X
X /* Initialize interrupt/id structures */
X
X bzero(cyb_tty,sizeof(struct tty)*MAX_CHAN);
X
X#if 0
X strcpy(sc->cy_ttydev.tty_name, cycd.cd_name);
X sc->cy_ttydev.tty_unit = sc->cy_dev.dv_unit;
X sc->cy_ttydev.tty_base = sc->cy_dev.dv_unit * 16;
X sc->cy_ttydev.tty_count = sc->cy_NbrPorts;
X sc->cy_ttydev.tty_ttys = sc->cy_tty;
X tty_attach(&sc->cy_ttydev);
X#endif
X sc->cy_inintr = 0;
X sc->cy_pollactive = 1;
X#ifdef cy_STATS
X sc->cy_statclk = 1000; /* 1000ms = 1 sec */
X#endif
X timeout((timeout_func_t)cybpoll,(caddr_t)sc,POLLSLICE);
X printf("\n");
X return(1);
X}
X
X/*
X * Open line
X */
Xint
Xcybopen(dev, flag, mode, p)
X dev_t dev;
X int flag;
X int mode;
X struct proc *p;
X{
X register struct tty *tp;
X int s;
X int error;
X register caddr_t base;
X int unit, chan;
X struct cybsoftc *sc;
X
X unit = UNIT(dev);
X sc = &cybsoftc[unit];
X if (sc == 0) {
X dprintf(("&cybsoftc[%d]=0 error\n",unit));
X return (ENXIO);
X }
X
X chan = LINE(dev);
X if (chan >= sc->cy_NbrPorts) {
X dprintf(("chan %d>NbrPorts",chan));
X return (ENXIO);
X }
X printf("opening unit %d, chan %d\n",unit,chan);
X tp = &cyb_tty[chan];
X base = sc->cy_addr[chan];
X dprintf(("cybopen: base %lx, chan %d\n",base,chan));
X tp->t_oproc = cybstart;
X tp->t_param = cybparam;
X tp->t_dev = dev;
X if ((tp->t_state & TS_ISOPEN) == 0) {
X tp->t_state |= TS_WOPEN;
X if (tp->t_ispeed == 0) {
X tp->t_iflag = 0;
X tp->t_oflag = 0;
X tp->t_cflag = TTYDEF_CFLAG;
X tp->t_lflag = 0;
X tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
X }
X cybparam(tp, &tp->t_termios);
X ttsetwater(tp);
X } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
X return (EBUSY);
X
X error = 0;
X s = spltty();
X (void) cybmctl(dev, SET, TIOCM_DTR|TIOCM_RTS);
X
X routb(base, CD1400_CAR, chan&0x03);
X if (rinb(base, CD1400_MSVR2) & MSVR2_CD) {
X dprintf(("CD PRESENT\n"));
X tp->t_state |= TS_CARR_ON;
X }
X if (!(flag & O_NONBLOCK)) {
X while (!(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON)) {
X tp->t_state |= TS_WOPEN;
X error = ttysleep(tp, (caddr_t)&tp->t_rawq,
X TTIPRI | PCATCH, ttopen, 0);
X if (error) {
X /*
X * Disable line and drop DTR.
X * Note, this is wrong if another open might
X * be in progress.
X */
X#if 1
X /*cybchancmd(base, CCR_TXDIS | CCR_RXDIS);*/
X sc->cy_init[chan] = 0;
X (void) cybmctl(dev, SET, 0);
X#endif
X break;
X }
X }
X }
X splx(s);
X if (error == 0)
X error = (*linesw[tp->t_line].l_open)(dev, tp);
X#ifdef cy_STATS
X sc->stats_ints_xmit[chan] = 0;
X sc->stats_ints_recv[chan] = 0;
X sc->stats_ints_mdm [chan] = 0;
X#endif
X return (error);
X}
X
X/*
X * Close line
X */
Xint
Xcybclose(dev, flag, mode, p)
X dev_t dev;
X int flag;
X int mode;
X struct proc *p;
X{
X struct cybsoftc *sc = &cybsoftc[UNIT(dev)];
X int chan = LINE(dev);
X register struct tty *tp = &cyb_tty[chan];
X register caddr_t base = sc->cy_addr[chan];
X int s;
X
X dprintf(("cybclose: chan %d\n",chan));
X
X s = spltty();
X (*linesw[tp->t_line].l_close)(tp, flag);
X
X /* Disable line */
X routb(base, CD1400_CAR, chan&0x03);
X cybchancmd(base, CCR_TXDIS | CCR_RXDIS);
X sc->cy_init[chan] = 0;
X routb(base, CD1400_SRER, sc->cy_srer[chan]=0);
X
X /* Hang up */
X if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
X (tp->t_state & TS_ISOPEN) == 0)
X (void) cybmctl(dev, SET, 0);
X
X ttyclose(tp);
X splx(s);
X if (sc->cy_orun[chan]) {
X log(LOG_ERR, "cy%d line %d: %d overruns\n", UNIT(dev), chan,
X sc->cy_orun[chan]);
X sc->cy_orun[chan] = 0;
X }
X#ifdef cy_STATS
X {
X int i;
X printf("cy%d:%d\n\t", UNIT(dev), LINE(dev));
X for (i = 0; i < 3; i++)
X printf("I%d=%x ", i, int_cnt[minor(dev)][i]);
X for (i = 0; i < 2; i++)
X printf("L%d=%x ", i, loops[UNIT(dev)][i]);
X printf("\n");
X }
X#endif
X return (0);
X}
X
X/*
X * Read from line
X */
Xint
Xcybread(dev, uio, flag)
X dev_t dev;
X struct uio *uio;
X int flag;
X{
X struct cybsoftc *sc = &cybsoftc[UNIT(dev)];
X struct tty *tp = &cyb_tty[LINE(dev)];
X
X dprintf(("cybread:\n"));
X return ((*linesw[(u_char)tp->t_line].l_read)(tp, uio, flag));
X}
X
X/*
X * Write to line
X */
Xint
Xcybwrite(dev, uio, flag)
X dev_t dev;
X struct uio *uio;
X int flag;
X{
X struct cybsoftc *sc = &cybsoftc[UNIT(dev)];
X struct tty *tp = &cyb_tty[LINE(dev)];
X
X dprintf(("cybwrite:\n"));
X return ((*linesw[(u_char)tp->t_line].l_write)(tp, uio, flag));
X}
X
Xint
Xcybselect(dev, flag, p)
X dev_t dev;
X int flag;
X struct proc *p;
X{
X struct cybsoftc *sc = &cybsoftc[UNIT(dev)];
X
X /* WARNING *** FreeBSD *** */
X return (ttselect(dev, flag, p));
X}
X
Xstatic void
Xcybpoll(sc)
X struct cybsoftc *sc;
X{
X register struct tty *tp;
X register caddr_t base;
X register int chan;
X int s;
X
X s = spltty();
X if (sc->cy_inintr==0) {
X for (chan=0;chan<sc->cy_NbrPorts;chan++) {
X tp = &cyb_tty[chan];
X
X if (tp->t_state&TS_BUSY /*&& (sc->cy_srer[chan]&SRER_TXD)==0*/) {
X base = sc->cy_addr[chan];
X dprintf(("prodding %d\n",chan));
X routb(base, CD1400_CAR, chan&0x03);
X routb(base, CD1400_SRER, sc->cy_srer[chan]=SRER_MDM|SRER_RXD|SRER_TXD);
X }
X }
X }
X#ifdef cy_STATS
X sc->cy_statclk -= POLLSLICE;
X if (sc->cy_statclk<=0) {
X
X sc->cy_statclk = 1000; /* 1000ms = 1 sec */
X }
X#endif
X splx(s);
X if (sc->cy_pollactive)
X timeout((timeout_func_t)cybpoll,(caddr_t)sc,POLLSLICE);
X}
X
X/*
X * Interrupt routine
X */
Xvoid
Xcybintr(int unit)
X{
X struct cybsoftc *sc = &cybsoftc[0/*unit WARN *** */];
X struct tty *tp;
X int b, c;
X unsigned cnt;
X int chan;
X caddr_t base;
X int cd;
X int domore;
X
X sc->cy_inintr = 1;
X dprintf(("cybintr:\n"));
X more:
X domore = 0;
X for (cd=0;cd<sc->cy_NbrCD1400s;cd++) {
X base = sc->cy_addr[cd*4]; /* WARNING */
X
X dprintf(("*I%d*\n", unit));
X if (base == 0) {
X printf("cy%d: bogus interrupt\n", unit);
X sc->cy_inintr = 0;
X }
X
X /* Read Board Status Register */
X dprintf(("reading from %lx\n",(unsigned long)base));
X while (b=rinb(base,CD1400_SVRR)) {
X domore = 1;
X /*
X * Need to add some code to allow return if this card is hogging
X */
X
X /* Receiver interrupt */
X if (b & CD1400_SVRR_RX) {
X unsigned char save_rir = rinb(base,CD1400_RIR);
X int chan = cd*CD1400_NO_OF_CHANNELS + (save_rir&0x03);
X unsigned char save_car = rinb(base,CD1400_CAR);
X routb(base,CD1400_CAR,save_rir);
X
X tp = &cyb_tty[chan];
X#ifdef cy_STATS
X sc->stats_ints_recv[chan]++;
X#endif
X
X switch(rinb(base,CD1400_RIVR)&0x07) {
X
X case 3:
X /* Get the count of received characters */
X cnt = rinb(base, CD1400_RDCR);
X
X /* If the line wasn't opened, throw data into bit bucket */
X if ((tp->t_state & TS_ISOPEN) == 0) {
X while (cnt--)
X (void) rinb(base, CD1400_RDSR);
X goto rxout;
X }
X
X while (cnt--) {
X c = ((rinb(base, CD1400_RDSR))&0xff);
X (*linesw[tp->t_line].l_rint)(c, tp);
X }
X break;
X
X case 7:
X (void) rinb(base,CD1400_RDSR); /* Get status */
X (void) rinb(base,CD1400_RDSR); /* Get bad data */
X break;
X }
X
X rxout:
X routb(base,CD1400_RIR,save_rir&0x3f);
X routb(base,CD1400_CAR,save_car);
X }
X
X
X
X /* TX interrupt? */
X if (b & CD1400_SVRR_TX) {
X unsigned char save_tir = rinb(base,CD1400_TIR);
X int chan = cd*CD1400_NO_OF_CHANNELS + (save_tir&0x03);
X unsigned char save_car = rinb(base,CD1400_CAR);
X routb(base,CD1400_CAR,save_tir);
X
X tp = &cyb_tty[chan];
X#ifdef cy_STATS
X sc->stats_ints_xmit[chan]++;
X#endif
X
X /* (Re-)start transmit */
X if (tp->t_state & TS_FLUSH) {
X tp->t_state &= ~(TS_BUSY|TS_FLUSH);
X /* Disable TX interrupts */
X routb(base, CD1400_SRER, sc->cy_srer[chan]=SRER_MDM|SRER_RXD);
X } else {
X tp->t_state &= ~TS_BUSY;
X sc->cy_txint = 1;
X (*linesw[tp->t_line].l_start)(tp);
X sc->cy_txint = 0;
X /* If nothing to send, disable TX interrupts */
X if ((tp->t_state&TS_BUSY) == 0)
X routb(base, CD1400_SRER, sc->cy_srer[chan]=SRER_MDM|SRER_RXD);
X
X }
X routb(base, CD1400_TIR,(save_tir & 0x3f));
X routb(base, CD1400_CAR,save_car);
X
X }
X /* goto out */
X
X /* Modem Ctl interrupt? */
X if (b & CD1400_SVRR_MDM) {
X unsigned char save_mir = rinb(base,CD1400_MIR);
X int chan = cd * CD1400_NO_OF_CHANNELS + (save_mir & 0x3);
X unsigned char save_car = rinb(base,CD1400_CAR);
X routb(base,CD1400_CAR,save_mir);
X
X tp = &cyb_tty[chan];
X#ifdef cy_STATS
X sc->stats_ints_mdm[chan]++;
X#endif
X
X if ((rinb(base, CD1400_MISR) & MISR_CDCHG)) {
X /* Get the value of CD */
X if (rinb(base,CD1400_MSVR2) & MSVR2_CD)
X (void) (*linesw[tp->t_line].l_modem)(tp, 1);
X else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
X (void) cybmctl(tp->t_dev, SET, 0);
X
X /* WARNING: May need to clear change bits here */
X }
X routb(base,CD1400_MIR,save_mir&0x3f);
X routb(base,CD1400_CAR,save_car);
X
X }
X }
X }
X if (domore) goto more;
X sc->cy_inintr = 0;
X routb(sc->cy_base, cy_CLEAR_INTR, 0);
X}
X
X/*
X * Start transmission
X */
Xvoid
Xcybstart(tp)
X register struct tty *tp;
X{
X register caddr_t base;
X register c, count;
X int s, chan;
X register struct cybsoftc *sc;
X
X dprintf(("cybstart:\n"));
X /*
X * Check if there is work to do and we're able to do more.
X */
X s = spltty();
X if (tp->t_state & TS_BUSY
X || (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
X#if 0 /* *** FreeBSD WARNING *** */
X && (tp->t_state & (TS_XON_PEND|TS_XOFF_PEND)) == 0)
X#endif
X ) {
X dprintf(("leaving early\n"));
X goto out;
X }
X
X if (tp->t_outq.c_cc <= tp->t_lowat) {
X if (tp->t_state & TS_ASLEEP) {
X tp->t_state &= ~TS_ASLEEP;
X wakeup((caddr_t)&tp->t_outq);
X }
X selwakeup(&tp->t_wsel);
X }
X
X sc = &cybsoftc[UNIT(tp->t_dev)];
X chan = LINE(tp->t_dev); /* *** WARNING *** */
X base = sc->cy_addr[chan];
X
X /*
X * If not in interrupt context, TDR is not available.
X * Simply enable TX interrupt if there is output to be done.
X */
X if (sc->cy_txint == 0) {
X if (tp->t_outq.c_cc ||
X /*tp->t_state & (TS_XON_PEND|TS_XOFF_PEND) || freeBSD WARN *** */
X sc->cy_cmd[chan] || sc->cy_pendesc[chan]) {
X tp->t_state |= TS_BUSY;
X routb(base, CD1400_CAR, chan&0x03);
X routb(base, CD1400_SRER, sc->cy_srer[chan]=SRER_MDM|SRER_RXD|SRER_TXD);
X }
X dprintf(("leaving with TXD ints enabled\n"));
X goto out;
X }
X
X /*
X * Process pending commands
X */
X count = CD1400_MAX_FIFO_SIZE;
X if (c = sc->cy_cmd[chan]) {
X sc->cy_cmd[chan] = 0;
X routb(base, CD1400_TDR, CD1400_C_ESC);
X routb(base, CD1400_TDR, c);
X count -= 2;
X }
X if (sc->cy_pendesc[chan]) {
X sc->cy_pendesc[chan] = 0;
X routb(base, CD1400_TDR, CD1400_C_ESC);
X count--;
X }
X
X
X#if 0 /* *** FreeBSD WARNING *** */
X if (tp->t_state & (TS_XON_PEND|TS_XOFF_PEND)) {
X if (tp->t_state & TS_XON_PEND) {
X routb(base, CD1400_TDR, tp->t_cc[VSTART]);
X tp->t_state &= ~TS_XON_PEND;
X } else {
X routb(base, CD1400_TDR, tp->t_cc[VSTOP]);
X tp->t_state &= ~TS_XOFF_PEND;
X }
X if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
X count = 0;
X else
X count--;
X }
X#endif
X
X /*
X * Run regular output queue
X */
X while (tp->t_outq.c_cc && count--) {
X c = getc(&tp->t_outq);
X if (c == CD1400_C_ESC) {
X if (count == 0) /* oops */
X sc->cy_pendesc[chan]++;
X else {
X routb(base, CD1400_TDR, CD1400_C_ESC);
X count--;
X }
X }
X dprintf(("txd: %c (%x)\n",(c<0x20||c>0x7e)?' ':c,c));
X routb(base, CD1400_TDR, c);
X }
X if (count<CD1400_MAX_FIFO_SIZE /*tp->t_outq.c_cc*/)
X tp->t_state |= TS_BUSY;
X
Xout:
X splx(s);
X}
X
X/*
X * Ioctl routine
X */
Xint
Xcybioctl(dev, cmd, data, flag, p)
X dev_t dev;
X int cmd;
X caddr_t data;
X int flag;
X struct proc *p;
X{
X register struct cybsoftc *sc = &cybsoftc[UNIT(dev)];
X register struct tty *tp = &cyb_tty[LINE(dev)];
X register int error;
X int s;
X
X dprintf(("cybioctl:\n"));
X error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
X if (error >= 0)
X return (error);
X error = ttioctl(tp, cmd, data, flag);
X if (error >= 0)
X return (error);
X
X s = spltty();
X switch (cmd) {
X case TIOCSBRK:
X /* Start sending BREAK */
X sc->cy_cmd[LINE(tp->t_dev)] = CD1400_C_SBRK;
X cybstart(tp);
X break;
X
X case TIOCCBRK:
X /* Stop sending BREAK */
X sc->cy_cmd[LINE(tp->t_dev)] = CD1400_C_EBRK;
X cybstart(tp);
X break;
X
X case TIOCSDTR: /* set DTR */
X (void) cybmctl(dev, BIS, TIOCM_DTR);
X break;
X
X case TIOCCDTR: /* clear DTR */
X (void) cybmctl(dev, BIC, TIOCM_DTR);
X break;
X
X case TIOCMSET:
X (void) cybmctl(dev, SET, * (int *) data);
X break;
X
X case TIOCMBIS:
X (void) cybmctl(dev, BIS, * (int *) data);
X break;
X
X case TIOCMBIC:
X (void) cybmctl(dev, BIC, * (int *) data);
X break;
X
X case TIOCMGET:
X * (int *) data = cybmctl(dev, GET, 0);
X break;
X
X default:
X splx(s);
X return (ENOTTY);
X }
X splx(s);
X return (0);
X}
X
Xstatic int cyb_fifothresh_lo = 8; /* FIFO depth, half of FIFO, < 38.4k */
Xstatic int cyb_fifothresh_hi = 4; /* FIFO depth, >= 38.4k */
X
Xstatic int cyb_doenable = 0; /* should not be needed, defeats optimization if set */
X/*
X * Set parameters and enable the line
X */
Xint
Xcybparam(tp, t)
X register struct tty *tp;
X register struct termios *t;
X{
X int s, chan;
X register struct cybsoftc *sc;
X register caddr_t base;
X int iprescaler, oprescaler;
X int ispeed, ospeed;
X int cflag = t->c_cflag;
X int iflag = t->c_iflag;
X /*
X c is initialized to 0, eventhough it isn't necessary, to stop
X gnu gcc 2.6.2 from emitting a warning that it may be used
X uninitialized.
X */
X register c = 0;
X
X dprintf(("cybparam:\n"));
X /* short-circuit the common case where there is no hardware change */
X
X if (tp->t_cflag == t->c_cflag && tp->t_state&TS_ISOPEN &&
X tp->t_iflag == t->c_iflag &&
X tp->t_ispeed == t->c_ispeed && tp->t_ospeed == t->c_ospeed)
X return (0);
X
X if ((tp->t_cflag & CLOCAL) == 0 && t->c_cflag & CLOCAL)
X wakeup((caddr_t) &tp->t_rawq);
X
X tp->t_ispeed = t->c_ispeed;
X tp->t_ospeed = t->c_ospeed;
X tp->t_cflag = t->c_cflag;
X tp->t_iflag = t->c_iflag;
X
X /* Select line */
X sc = &cybsoftc[UNIT(tp->t_dev)];
X chan = LINE(tp->t_dev);
X base = sc->cy_addr[chan];
X s = spltty();
X routb(base, CD1400_CAR, chan&0x03);
X
X /* ospeed == 0 is for HANGUP */
X if (tp->t_ospeed == 0) {
X (void) cybmctl(tp->t_dev, SET, 0);
X cybchancmd(base, CCR_TXDIS | CCR_RXDIS);
X sc->cy_init[chan] = 0;
X splx(s);
X return (0);
X }
X
X if ((ospeed = cybspeed(t->c_ospeed, &oprescaler)) < 0) {
X splx(s);
X return(EINVAL);
X }
X routb(base,CD1400_TBPR,ospeed);
X routb(base,CD1400_TCOR,oprescaler);
X
X if ((ispeed = cybspeed(t->c_ispeed, &iprescaler)) < 0) {
X splx(s);
X return(EINVAL);
X }
X routb(base,CD1400_RBPR,ispeed);
X routb(base,CD1400_RCOR,iprescaler);
X
X /* Load COR1 */
X switch (tp->t_cflag & CSIZE) {
X case CS5:
X c = COR1_5BITS;
X break;
X case CS6:
X c = COR1_6BITS;
X break;
X case CS7:
X c = COR1_7BITS;
X break;
X case CS8:
X c = COR1_8BITS;
X break;
X }
X#if 0
X printf("%s ",tp->t_cflag & CSTOPB ? "CSTOPB":"!CSTOPB");
X printf("%s ",tp->t_cflag & PARENB ? "PARENB":"!PARENB");
X printf("%s ",tp->t_cflag & PARODD ? "PARODD":"!PARODD");
X printf("%s ",tp->t_cflag & PARODD ? "PARODD":"!PARODD");
X#endif
X if (tp->t_cflag & CSTOPB)
X c |= COR1_2SB;
X if (tp->t_cflag & PARENB) {
X c |= COR1_NORMPAR;
X if (tp->t_cflag & PARODD)
X c |= COR1_ODDP;
X#if 0
X if ((tp->t_iflag & INPCK) == 0)
X c |= COR1_IGNORE;
X#endif
X } else
X c |= COR1_IGNORE;
X routb(base, CD1400_COR1, c);
X dprintf(("cor1=%x\n",c));
X
X /* Load COR2 */
X c = COR2_ETC;
X if (tp->t_cflag & CCTS_OFLOW)
X c |= COR2_CTSAE;
X#ifdef wrong
X /*
X * COR2_RTSAO enables traditional RTS (high when there is something
X * to transmit), not RTR (high when ready to receive).
X */
X if (tp->t_cflag & CRTS_IFLOW)
X c |= COR2_RTSAO;
X#endif
X
X /* there should be some logic to enable on-chip Xon/Xoff flow ctl */
X routb(base, CD1400_COR2, c);
X dprintf(("cor2=%x\n",c));
X
X /* Load COR3 */
X if (tp->t_ispeed >= 38400)
X routb(base, CD1400_COR3, cyb_fifothresh_hi); /* FIFO depth */
X else
X routb(base, CD1400_COR3, cyb_fifothresh_lo); /* FIFO depth */
X /* set the Receive Timeout Period to 20ms */
X routb(base, CD1400_RTPR, 20);
X
X /* Inform CD1400 engine about new values in COR registers */
X cybchancmd(base, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
X DELAY(500);
X
X /* Load COR4 */
X c = 0;
X if (iflag&IGNCR)
X c |= COR4_IGNCR;
X if (iflag&IGNBRK)
X c |= COR4_IGNBRK;
X if (!(iflag&BRKINT))
X c |= COR4_NBRKINT;
X if (iflag&IGNPAR)
X c |= COR4_PFODISC;
X else {
X if (iflag&PARMRK)
X c |= COR4_PFOMARK;
X else
X c |= COR4_PFONULL;
X }
X routb(base,CD1400_COR4,c);
X dprintf(("cor4=%x\n",c));
X
X /* Load COR5 */
X c = 0;
X if (iflag&ISTRIP)
X c |= COR5_ISTRIP;
X if (t->c_iflag&IEXTEN)
X c |= COR5_IEXTEN;
X routb(base,CD1400_COR5,c);
X dprintf(("cor5=%x\n",c));
X
X
X c = 0;
X if (tp->t_cflag & CRTS_IFLOW)
X c |= 8;
X routb(base, CD1400_MCOR1, MCOR1_CDZD|6); /* WARNING */
X
X dprintf(("cybparam:1\n"));
X if (sc->cy_init[chan] == 0 || cyb_doenable) {
X sc->cy_init[chan] = 1;
X /* Load modem control parameters */
X routb(base, CD1400_MCOR2, MCOR2_CDOD);
X
X /* Finally enable transmitter and receiver */
X cybchancmd(base, CCR_TXEN | CCR_RXEN);
X routb(base, CD1400_SRER, sc->cy_srer[chan]=SRER_MDM|SRER_RXD); /* WARNING */
X dprintf(("cybparam:2\n"));
X }
X splx(s);
X dprintf(("cybparam:d\n"));
X return (0);
X}
X
X/*
X * Write a command to the Channel Command Register,
X * making sure it is not busy before writing the command.
X * The channel must already have been selected.
X */
Xstatic void
Xcybchancmd(base, cmd)
X caddr_t base;
X int cmd;
X{
X int i;
X
X for (i = 0; i < 100; i++) {
X if (rinb(base, CD1400_CCR) == 0)
X goto ready;
X DELAY(100);
X }
X printf("cy: ccr not ready\n");
Xready:
X routb(base, CD1400_CCR, cmd);
X}
X
X/*
X * Stop output on a line
X */
X/*ARGSUSED*/
Xvoid
Xcybstop(tp, flag)
X register struct tty *tp;
X int flag;
X{
X int s;
X
X s = spltty();
X if (tp->t_state & TS_BUSY) {
X if ((tp->t_state & TS_TTSTOP) == 0)
X tp->t_state |= TS_FLUSH;
X }
X splx(s);
X}
X
X/*
X * Modem control routine.
X */
Xstatic int
Xcybmctl(dev, cmd, bits)
X dev_t dev;
X enum cybmctl_cmds cmd;
X int bits;
X{
X register struct cybsoftc *sc = &cybsoftc[UNIT(dev)];
X register line = LINE(dev);
X register caddr_t base = sc->cy_addr[line];
X register msvr;
X
X dprintf(("cybmctl%x: cmd=%d bits=%x base=%lx\n",
X minor(dev), cmd, bits, (unsigned long)base));
X
X routb(base, CD1400_CAR, line&0x03);
X
X switch (cmd) {
X case GET:
X msvr = rinb(base, CD1400_MSVR2);
X bits = TIOCM_LE;
X if (msvr & MSVR2_DTR)
X bits |= TIOCM_DTR;
X if (msvr & MSVR2_CTS)
X bits |= TIOCM_CTS;
X if (msvr & MSVR2_DSR)
X bits |= TIOCM_DSR;
X if (msvr & MSVR2_CD)
X bits |= TIOCM_CAR;
X if (msvr & MSVR2_RI)
X bits |= TIOCM_RI;
X msvr = rinb(base, CD1400_MSVR1);
X if (msvr & MSVR1_RTS)
X bits |= TIOCM_RTS;
X return (bits);
X
X case SET:
X if (bits&TIOCM_DTR) {
X sc->cy_softdtr |= 1 << line;
X routb(base, CD1400_MSVR1,MSVR1_RTS);
X } else {
X sc->cy_softdtr &= ~(1 << line);
X routb(base, CD1400_MSVR1,0x00); /* lower RTS */
X }
X break;
X
X case BIS:
X#if 0
X if (bits & TIOCM_RTS)
X routb(base, CD1400_MSVR2, MSVR2_RTS);
X#endif
X if (bits & TIOCM_DTR) {
X sc->cy_softdtr |= 1 << line;
X routb(base, CD1400_MSVR1,MSVR1_RTS);
X }
X
X break;
X
X case BIC:
X#if 0
X if (bits & TIOCM_RTS)
X routb(base, CD1400_MSVR, 0);
X#endif
X if (bits & TIOCM_DTR) {
X sc->cy_softdtr &= ~(1 << line);
X routb(base, CD1400_MSVR1,0x00); /* lower RTS */
X }
X break;
X }
X
X /* Enable/disable receiver on open/close */
X if (cmd == SET) {
X routb(base, CD1400_CAR, line&0x03);
X if (bits == 0) {
X cybchancmd(base, CCR_RXDIS);
X } else {
X cybchancmd(base, CCR_RXEN);
X }
X }
X return (0);
X}
X
Xstatic int
Xcybspeed(speed, prescaler_io)
X long speed;
X int *prescaler_io;
X{
X int actual;
X int error;
X int divider;
X int prescaler;
X int prescaler_unit;
X
X if (speed == 0)
X return 0;
X
X if (speed < 0 || speed > 150000)
X return -1;
X
X /* determine which prescaler to use */
X for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
X prescaler_unit--, prescaler >>= 2) {
X if (CYCLOM_CLOCK/prescaler/speed > 63)
X break;
X }
X
X divider = (CYCLOM_CLOCK/prescaler*2/speed + 1)/2; /* round off */
X if (divider > 255)
X divider = 255;
X actual = CYCLOM_CLOCK/prescaler/divider;
X error = ((actual-speed)*2000/speed +1)/2; /* percentage */
X
X /* 3.0% max error tolerance */
X if (error < -30 || error > 30)
X return -1;
X
X#if 0
X printf("speed = %ld\n",speed);
X printf("prescaler = %d (%d)\n", prescaler, prescaler_unit);
X printf("divider = %d (%x)\n", divider, divider);
X printf("actual = %d\n", actual);
X printf("error = %d\n", error);
X#endif
X
X *prescaler_io = prescaler_unit;
X return divider;
X}
X#endif /* NCYB > 0 */
END-of-cyb.c
echo x - cl-cd1400.h
sed 's/^X//' >cl-cd1400.h << 'END-of-cl-cd1400.h'
X/*-
X * Copyright (c) 1994 By Brian E. Litzinger, All rights reserved.
X * Copyright (c) 1992 Berkeley Software Design, Inc. All rights reserved.
X * The Berkeley Software Design Inc. software License Agreement specifies
X * the terms and conditions for redistribution.
X *
X */
X
X/*
X * Definitions for Cirrus Logic CL-CD1400 4-port async mux chip
X */
X
X#define CD1400_NCHAN 4 /* Total number of channels */
X#define CD1400_TPC 16 /* Ticks per character */
X
X/*
X * Global Registers
X */
X#define CD1400_GFRCR 2*0x40 /* global firmware revision code */
X#define CD1400_CAR 2*0x68 /* channel access */
X#define CD1400_GCR 2*0x4b /* global config */
X#define CD1400_SVRR 2*0x67 /* service request */
X#define CD1400_RICR 2*0x44 /* receive intr channel */
X#define CD1400_TICR 2*0x45 /* transmit intr channel */
X#define CD1400_MICR 2*0x46 /* modem intr channel */
X#define CD1400_RIR 2*0x6B /* receive interrupt status */
X#define CD1400_TIR 2*0x6A /* transmit interrupt status */
X#define CD1400_MIR 2*0x69 /* modem interrupt status */
X#define CD1400_PPR 2*0x7e
X
X/*
X Virtual Registers
X*/
X#define CD1400_RIVR 2*0x43 /* receive intr vector */
X#define CD1400_TIVR 2*0x42 /* transmit intr vector */
X#define CD1400_MIVR 2*0x41 /* modem intr vector */
X#define CD1400_LIVR 2*0x18 /* local intr vector */
X#define CD1400_TDR 2*0x63 /* tx data */
X#define CD1400_RDSR 2*0x62 /* rx data/status */
X#define CD1400_MISR 2*0x4c /* modem intr status */
X#define CD1400_EOSRR 2*0x60 /* end of service request */
X
X
X
X/*
X * Channel Registers
X */
X#define CD1400_LIVR 2*0x18 /* local intr vector */
X#define CD1400_CCR 2*0x05 /* channel control */
X#define CD1400_SRER 2*0x06 /* service request enable */
X#define CD1400_COR1 2*0x08 /* channel option 1 */
X#define CD1400_COR2 2*0x09 /* channel option 2 */
X#define CD1400_COR3 2*0x0A /* channel option 3 */
X#define CD1400_COR4 2*0x1E /* channel option 4 */
X#define CD1400_COR5 2*0x1F /* channel option 5 */
X#define CD1400_CCSR 2*0x0b /* channel control status */
X#define CD1400_RDCR 2*0x0e /* rx data count */
X#define CD1400_SCHR1 2*0x1A /* special character 1 */
X#define CD1400_SCHR2 2*0x1B /* special character 2 */
X#define CD1400_SCHR3 2*0x1C /* special character 3 */
X#define CD1400_SCHR4 2*0x1D /* special character 4 */
X#define CD1400_SCRL 2*0x22 /* special char range, low */
X#define CD1400_SCRH 2*0x23 /* special char range, high */
X#define CD1400_LNC 2*0x24 /* LNext character */
X#define CD1400_MCOR1 2*0x15 /* modem change 1 */
X#define CD1400_MCOR2 2*0x16 /* modem change 2 */
X#define CD1400_RTPR 2*0x21 /* receive timeout period */
X#define CD1400_MSVR1 2*0x6c /* modem signals */
X#define CD1400_MSVR2 2*0x6d /* modem signals */
X
X#define CD1400_RBPR 2*0x78 /* receive baud rate period */
X#define CD1400_RCOR 2*0x7C /* receive clock option */
X#define CD1400_TBPR 2*0x72 /* transmit baud rate period */
X#define CD1400_TCOR 2*0x76 /* transmit clock option */
X
X/*
X * Channel Address Register
X */
X#define CAR_CHAN 0x7 /* Channel Number Mask */
X
X/*
X * Channel Command Register
X * (commands in groups can be OR-ed)
X */
X#define CCR_HARDRESET 0x81 /* Reset the chip */
X
X#define CCR_SOFTRESET 0x80 /* Soft Channel Reset */
X
X#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */
X#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */
X#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */
X
X#define CCR_SSCH1 0x21 /* Send Special Character 1 */
X
X#define CCR_SSCH2 0x22 /* Send Special Character 2 */
X
X#define CCR_SSCH3 0x23 /* Send Special Character 3 */
X
X#define CCR_SSCH4 0x24 /* Send Special Character 4 */
X
X#define CCR_TXEN 0x18 /* Enable Transmitter */
X#define CCR_RXEN 0x12 /* Enable Receiver */
X
X#define CCR_TXDIS 0x14 /* Diasable Transmitter */
X#define CCR_RXDIS 0x11 /* Diasable Receiver */
X
X/*
X * Channel Option Register 1
X */
X#define COR1_ODDP 0x80 /* Odd Parity */
X#define COR1_PARMODE 0x60 /* Parity Mode mask */
X#define COR1_NOPAR 0x0 /* No Parity */
X#define COR1_FORCEPAR 0x20 /* Force Parity */
X#define COR1_NORMPAR 0x40 /* Normal Parity */
X#define COR1_IGNORE 0x10 /* Ignore Parity on RX */
X#define COR1_STOPBITS 0xc /* Number of Stop Bits */
X#define COR1_1SB 0x0 /* 1 Stop Bit */
X#define COR1_15SB 0x4 /* 1.5 Stop Bits */
X#define COR1_2SB 0x8 /* 2 Stop Bits */
X#define COR1_CHARLEN 0x3 /* Character Length */
X#define COR1_5BITS 0x0 /* 5 bits */
X#define COR1_6BITS 0x1 /* 6 bits */
X#define COR1_7BITS 0x2 /* 7 bits */
X#define COR1_8BITS 0x3 /* 8 bits */
X
X/*
X * Channel Option Register 2
X */
X#define COR2_IXM 0x80 /* Implied XON mode */
X#define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */
X#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */
X#define COR2_LLM 0x10 /* Local Loopback Mode */
X#define COR2_RLM 0x8 /* Remote Loopback Mode */
X#define COR2_RTSAO 0x4 /* RTS Automatic Output Enable */
X#define COR2_CTSAE 0x2 /* CTS Automatic Enable */
X#define COR2_DSRAE 0x1 /* DSR Automatic Enable */
X
X/*
X * Channel Option Register 3
X */
X#define COR3_XONCH 0x80 /* XON is a pair of characters (spec. 1&3) */
X#define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2&4) */
X#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */
X#define COR3_SCDE 0x10 /* Special Character Detection Enable */
X#define COR3_RXTH 0xf /* RX FIFO Threshold value (1-12) */
X
X/*
X Channel Option Register 4
X*/
X#define COR4_IGNCR 0x80
X#define COR4_ICRNL 0x40
X#define COR4_INLCR 0x20
X#define COR4_IGNBRK 0x10
X#define COR4_NBRKINT 0x08
X#define COR4_PFOEXCP 0x00
X#define COR4_PFOGOOD 0x01
X#define COR4_PFODISC 0x02
X#define COR4_PFONULL 0x03
X#define COR4_PFOMARK 0x04
X
X/*
X Channel Option Register 5
X*/
X
X#define COR5_ISTRIP 0x80
X#define COR5_IEXTEN 0x40
X#define COR5_ONLCR 0x02
X#define COR5_OCRNL 0x01
X
X/*
X * Modem Change Option Register 1
X */
X#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */
X#define MCOR1_CTSZD 0x40 /* Detect 0->1 transition of CTS */
X#define MCOR1_RIZD 0x20 /* Detect 0->1 transition of RI */
X#define MCOR1_CDZD 0x10 /* Detect 0->1 transition of CD */
X#define MCOR1_DTRTH 0xf /* Automatic DTR flow control Threshold (1-12)*/
X#define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */
X
X/*
X * Modem Change Option Register 2
X */
X#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */
X#define MCOR2_CTSOD 0x40 /* Detect 1->0 transition of CTS */
X#define MCOR2_RIOD 0x20 /* Detect 1->0 transition of RI */
X#define MCOR2_CDOD 0x10 /* Detect 1->0 transition of CD */
X
X/*
X * Modem Signal Value Registers
X */
X#define MSVR2_DSR 0x80 /* Current state of DSR input */
X#define MSVR2_CTS 0x40 /* Current state of CTS input */
X#define MSVR2_RI 0x20 /* Current state of RI input */
X#define MSVR2_CD 0x10 /* Current state of CD input */
X#define MSVR2_DTR 0x02 /* Current state of DTR output */
X
X#define MSVR1_RTS 0x01 /* Current state of RTS output */
X
X/*
X * Escape characters
X */
X#define CD1400_C_ESC 0x0 /* Escape character */
X#define CD1400_C_SBRK 0x81 /* Start sending BREAK */
X#define CD1400_C_DELAY 0x82 /* Delay output */
X#define CD1400_C_EBRK 0x83 /* Stop sending BREAK */
X
X#define MISR_CDCHG 0x10
X
X
X#define CD1400_SVRR_RX 0x01
X#define CD1400_SVRR_TX 0x02
X#define CD1400_SVRR_MDM 0x04
X
X#define SRER_MDM 0x80
X#define SRER_RXD 0x10
X#define SRER_TXD 0x04
X#define SRER_NNDT 0x01
END-of-cl-cd1400.h
echo x - cyreg.h
sed 's/^X//' >cyreg.h << 'END-of-cyreg.h'
X/*-
X * Copyright (c) 1994 By Brian E. Litzinger, All rights reserved.
X * Copyright (c) 1992 Berkeley Software Design, Inc. All rights reserved.
X * The Berkeley Software Design Inc. software License Agreement specifies
X * the terms and conditions for redistribution.
X *
X */
X
X/*
X * Definitions for Cyclades 8Y and 16Y Cyclom cards.
X */
X
X
X/*
X * Address mapping between Cirrus Logic CD1400 chip internal registers
X * and ISA port addresses:
X *
X */
X#define CY_ADDR(reg) (reg)
X
X/* Input Byte from CL CD1400 register */
X#define rinb(base, reg) (*((base)+CY_ADDR(reg)))
X
X/* Output Byte to CL CD1400 register */
X#define routb(base, reg, val) (*((base)+CY_ADDR(reg))=val)
X
X#define CY_NPORT 16 /* decoder recognizes 16 addresses... */
X
X#define CD1400_MEMSIZE 0x400
X#define cy_RESET_16 0x1400 /* cyclom-16y reset */
X#define cy_CLEAR_INTR 0x1800 /* intr ack address */
X#define CYCLOM_CLOCK 25000000 /* baud rate clock */
X#define CD1400_CLOCK_25_1MS 0x31
X#define CD1400_NO_OF_CHANNELS 4
X#define CD1400_MAX_FIFO_SIZE 12
X
X
END-of-cyreg.h
exit
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m0rn14t-000rcJC>
