mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
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.
This commit is contained in:
parent
37f5f2397d
commit
7134a2219c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128133
313
sys/dev/sx/cd1865.h
Normal file
313
sys/dev/sx/cd1865.h
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* 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$
|
||||
*/
|
||||
|
||||
|
||||
/* CD1865 chip register definitions. */
|
||||
|
||||
/*
|
||||
* Service Match Register interrupt acknowledgement values.
|
||||
*
|
||||
* These values are "obligatory" if you use the register based
|
||||
* interrupt acknowledgements; the wrong values can cause a lockup.
|
||||
* See section 8.11.1 of the Intel CD1865 "Intelligent Eight-Channel
|
||||
* Communications Controller" datasheet.
|
||||
*/
|
||||
#define CD1865_ACK_MINT 0x75 /* goes to MSMR */
|
||||
#define CD1865_ACK_TINT 0x76 /* goes to TSMR */
|
||||
#define CD1865_ACK_RINT 0x77 /* goes to RSMR */
|
||||
|
||||
|
||||
#define CD1865_NUMCHAN 8 /* Total number of channels. */
|
||||
#define CD1865_CHARTICK 16 /* Ticks per character. */
|
||||
#define CD1865_TFIFOSZ 8 /* TX FIFO size. */
|
||||
#define CD1865_RFIFOSZ 8 /* RX FIFO size. */
|
||||
|
||||
/*
|
||||
* Global registers.
|
||||
* These registers are not associated with any particular channel;
|
||||
* some define the general behavior of the card and others are only
|
||||
* active during service requests.
|
||||
*/
|
||||
#define CD1865_GIVR 0x40 /* Global Interrupt Vector Register. */
|
||||
/* The CD1865 datasheet calls this the */
|
||||
/* "Global Vector Register" _and_ the */
|
||||
/* "Global Service Vector Register," GSVR. */
|
||||
#define CD1865_GSVR CD1865_GIVR
|
||||
#define CD1865_GICR 0x41 /* Global Interrupting Channel Register. */
|
||||
/* The CD1865 datasheet calls this the */
|
||||
/* "Global Channel Register 1," GSCR1. */
|
||||
#define CD1865_GSCR1 CD1865_GICR
|
||||
#define CD1865_GSCR2 0x42 /* Global Channel Register 2. */
|
||||
#define CD1865_GSCR3 0x43 /* Global Channel Register 3. */
|
||||
#define CD1865_MSMR 0x61 /* Priority Interrupt Level Register 1. */
|
||||
#define CD1865_TSMR 0x62 /* Priority Interrupt Level Register 2. */
|
||||
#define CD1865_RSMR 0x63 /* Priority Interrupt Level Register 3. */
|
||||
#define CD1865_CAR 0x64 /* Channel Access Register. */
|
||||
#define CD1865_SRSR 0x65 /* Service Request Status Register. */
|
||||
#define CD1865_SRCR 0x66 /* Service Request Configuration Register. */
|
||||
#define CD1865_GFRCR 0x6b /* Global Firmware Revision Code Register. */
|
||||
#define CD1865_PPRH 0x70 /* Prescaler Period Register High. */
|
||||
#define CD1865_PPRL 0x71 /* Prescaler Period Register Low. */
|
||||
#define CD1865_RDR 0x78 /* Receiver Data Register. */
|
||||
#define CD1865_RCSR 0x7a /* Receiver Character Status Register. */
|
||||
#define CD1865_TDR 0x7b /* Transmit Data Register. */
|
||||
#define CD1865_EOIR 0x7f /* End of Interrupt Register. */
|
||||
#define CD1865_MRAR 0x75 /* Modem Request Acknowlege Register. */
|
||||
#define CD1865_TRAR 0x76 /* Transmit Request Acknowlege Register. */
|
||||
#define CD1865_RRAR 0x77 /* Receive Request Acknowlege Register. */
|
||||
|
||||
/*
|
||||
* Channel Registers
|
||||
* These registers control or provide status for individual channels.
|
||||
* Use the CD1865_CAR register to set up access to the channel before
|
||||
* using these registers.
|
||||
*/
|
||||
#define CD1865_CCR 0x01 /* Channel Command Register. */
|
||||
#define CD1865_IER 0x02 /* Interrupt Enable Register. */
|
||||
/* The CD1865 datasheet calls this the */
|
||||
/* "Service Request Enable Register," SRER. */
|
||||
#define CD1865_SRER CD1865_IER
|
||||
#define CD1865_COR1 0x03 /* Channel Option Register 1. */
|
||||
#define CD1865_COR2 0x04 /* Channel Option Register 2. */
|
||||
#define CD1865_COR3 0x05 /* Channel Option Register 3. */
|
||||
#define CD1865_CCSR 0x06 /* Channel Control Status Register. */
|
||||
#define CD1865_RDCR 0x07 /* Receive Data Count Register. */
|
||||
#define CD1865_SCHR1 0x09 /* Special Character Register 1. */
|
||||
#define CD1865_SCHR2 0x0a /* Special Character Register 2. */
|
||||
#define CD1865_SCHR3 0x0b /* Special Character Register 3. */
|
||||
#define CD1865_SCHR4 0x0c /* Special Character Register 4. */
|
||||
#define CD1865_MCOR1 0x10 /* Modem Change Option 1 Register. */
|
||||
#define CD1865_MCOR2 0x11 /* Modem Change Option 2 Register. */
|
||||
#define CD1865_MCR 0x12 /* Modem Change Register. */
|
||||
#define CD1865_RTPR 0x18 /* Receive Timeout Period Register. */
|
||||
#define CD1865_MSVR 0x28 /* Modem Signal Value Register. */
|
||||
#define CD1865_MSVRTS 0x29 /* Modem Signal Value Register. */
|
||||
#define CD1865_MSVDTR 0x2a /* Modem Signal Value Register. */
|
||||
#define CD1865_RBPRH 0x31 /* Receive Baud Rate Period Register High. */
|
||||
#define CD1865_RBPRL 0x32 /* Receive Baud Rate Period Register Low. */
|
||||
#define CD1865_TBPRH 0x39 /* Transmit Baud Rate Period Register High. */
|
||||
#define CD1865_TBPRL 0x3a /* Transmit Baud Rate Period Register Low. */
|
||||
|
||||
|
||||
/*
|
||||
* Global Interrupt Vector Register, read/write (0x40).
|
||||
*/
|
||||
#define CD1865_GIVR_ITMASK 0x07 /* Interrupt type mask. */
|
||||
#define CD1865_GIVR_IT_MODEM 0x01 /* Modem Signal Change Interrupt. */
|
||||
#define CD1865_GIVR_IT_TX 0x02 /* Transmit Data Interrupt. */
|
||||
#define CD1865_GIVR_IT_RCV 0x03 /* Receive Good Data Interrupt. */
|
||||
#define CD1865_GIVR_IT_REXC 0x07 /* Receive Exception Interrupt. */
|
||||
|
||||
|
||||
/*
|
||||
* Global Interrupt Channel Register read/write (0x41)
|
||||
*/
|
||||
#define CD1865_GICR_CHAN_MASK 0x1c /* Channel Number Mask. */
|
||||
#define CD1865_GICR_CHAN_SHIFT 2 /* Channel Number shift. */
|
||||
|
||||
|
||||
/*
|
||||
* Channel Access Register, read/write (0x64).
|
||||
*/
|
||||
#define CD1865_CAR_CHAN_MASK 0x07 /* Channel Number Mask. */
|
||||
#define CD1865_CAR_A7 0x08 /* A7 Address Extension (unused). */
|
||||
|
||||
|
||||
/*
|
||||
* Receive Character Status Register, readonly (0x7a).
|
||||
*/
|
||||
#define CD1865_RCSR_TOUT 0x80 /* Rx Timeout. */
|
||||
#define CD1865_RCSR_SCDET 0x70 /* Special Character Detected Mask. */
|
||||
#define CD1865_RCSR_NO_SC 0x00 /* No Special Characters Detected. */
|
||||
#define CD1865_RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected. */
|
||||
#define CD1865_RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected. */
|
||||
#define CD1865_RCSR_SC_3 0x30 /* Special Char 3 Detected. */
|
||||
#define CD1865_RCSR_SC_4 0x40 /* Special Char 4 Detected. */
|
||||
#define CD1865_RCSR_BREAK 0x08 /* Break detected. */
|
||||
#define CD1865_RCSR_PE 0x04 /* Parity Error. */
|
||||
#define CD1865_RCSR_FE 0x02 /* Frame Error. */
|
||||
#define CD1865_RCSR_OE 0x01 /* Overrun Error. */
|
||||
|
||||
|
||||
/*
|
||||
* Channel Command Register, read/write (0x01)
|
||||
* Commands in groups can be OR-ed together.
|
||||
*/
|
||||
#define CD1865_CCR_HARDRESET 0x81 /* Reset the CD1865 (like a powercycle). */
|
||||
|
||||
#define CD1865_CCR_SOFTRESET 0x80 /* Soft Channel Reset (one channel). */
|
||||
|
||||
#define CD1865_CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed. */
|
||||
#define CD1865_CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed. */
|
||||
#define CD1865_CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed. */
|
||||
|
||||
#define CD1865_CCR_SSCH1 0x21 /* Send Special Character 1. */
|
||||
|
||||
#define CD1865_CCR_SSCH2 0x22 /* Send Special Character 2. */
|
||||
|
||||
#define CD1865_CCR_SSCH3 0x23 /* Send Special Character 3. */
|
||||
|
||||
#define CD1865_CCR_SSCH4 0x24 /* Send Special Character 4. */
|
||||
|
||||
#define CD1865_CCR_TXEN 0x18 /* Enable Transmitter. */
|
||||
#define CD1865_CCR_RXEN 0x12 /* Enable Receiver. */
|
||||
|
||||
#define CD1865_CCR_TXDIS 0x14 /* Disable Transmitter. */
|
||||
#define CD1865_CCR_RXDIS 0x11 /* Disable Receiver. */
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt Enable Register, read/write (0x02).
|
||||
* (aka Service Request Enable Register)
|
||||
*/
|
||||
#define CD1865_IER_DSR 0x80 /* Enable DSR change interrupt. */
|
||||
#define CD1865_IER_CD 0x40 /* Enable CD change interrupt. */
|
||||
#define CD1865_IER_CTS 0x20 /* Enable CTS change interrupt. */
|
||||
#define CD1865_IER_RXD 0x10 /* Enable Receive Data interrupt. */
|
||||
#define CD1865_IER_RXSC 0x08 /* Enable Receive Special Character int. */
|
||||
#define CD1865_IER_TXRDY 0x04 /* Enable Transmit ready interrupt. */
|
||||
#define CD1865_IER_TXEMPTY 0x02 /* Enable Transmit empty interrupt. */
|
||||
#define CD1865_IER_NNDT 0x01 /* Enable "No New Data Timeout" int. */
|
||||
|
||||
|
||||
/*
|
||||
* Channel Option Register 1, read/write (0x03).
|
||||
*/
|
||||
#define CD1865_COR1_ODDP 0x80 /* Odd Parity. */
|
||||
#define CD1865_COR1_PARMODE 0x60 /* Parity enable mask. */
|
||||
#define CD1865_COR1_NOPAR 0x00 /* No Parity. */
|
||||
#define CD1865_COR1_FORCEPAR 0x20 /* Force Parity. */
|
||||
#define CD1865_COR1_NORMPAR 0x40 /* Normal Parity. */
|
||||
#define CD1865_COR1_IGNORE 0x10 /* Ignore Parity on RX. */
|
||||
#define CD1865_COR1_STOPBITS 0x0c /* Number of Stop Bits. */
|
||||
#define CD1865_COR1_1SB 0x00 /* 1 Stop Bit. */
|
||||
#define CD1865_COR1_15SB 0x04 /* 1.5 Stop Bits. */
|
||||
#define CD1865_COR1_2SB 0x08 /* 2 Stop Bits. */
|
||||
#define CD1865_COR1_CHARLEN 0x03 /* Character Length. */
|
||||
#define CD1865_COR1_5BITS 0x00 /* 5 bits. */
|
||||
#define CD1865_COR1_6BITS 0x01 /* 6 bits. */
|
||||
#define CD1865_COR1_7BITS 0x02 /* 7 bits. */
|
||||
#define CD1865_COR1_8BITS 0x03 /* 8 bits. */
|
||||
|
||||
|
||||
/*
|
||||
* Channel Option Register 2, read/write (0x04).
|
||||
*/
|
||||
#define CD1865_COR2_IXM 0x80 /* Implied XON mode. */
|
||||
#define CD1865_COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control*/
|
||||
#define CD1865_COR2_ETC 0x20 /* Embedded Tx Commands Enable. */
|
||||
#define CD1865_COR2_LLM 0x10 /* Local Loopback Mode. */
|
||||
#define CD1865_COR2_RLM 0x08 /* Remote Loopback Mode. */
|
||||
#define CD1865_COR2_RTSAO 0x04 /* RTS Automatic Output Enable. */
|
||||
#define CD1865_COR2_CTSAE 0x02 /* CTS Automatic Enable. */
|
||||
#define CD1865_COR2_DSRAE 0x01 /* DSR Automatic Enable. */
|
||||
|
||||
|
||||
/*
|
||||
* Channel Option Register 3, read/write (0x05).
|
||||
*/
|
||||
#define CD1865_COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3). */
|
||||
#define CD1865_COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4). */
|
||||
#define CD1865_COR3_FCT 0x20 /* Flow-Control Transparency Mode. */
|
||||
#define CD1865_COR3_SCDE 0x10 /* Special Character Detection Enable. */
|
||||
#define CD1865_COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8). */
|
||||
|
||||
|
||||
/*
|
||||
* Channel Control Status Register, readonly (0x06)
|
||||
*/
|
||||
#define CD1865_CCSR_RXEN 0x80 /* Receiver Enabled. */
|
||||
#define CD1865_CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent). */
|
||||
#define CD1865_CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent). */
|
||||
#define CD1865_CCSR_TXEN 0x08 /* Transmitter Enabled. */
|
||||
#define CD1865_CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF). */
|
||||
#define CD1865_CCSR_TXFLON 0x02 /* Transmit Flow On (got XON). */
|
||||
|
||||
|
||||
/*
|
||||
* Modem Change Option Register 1, read/write (0x10).
|
||||
*/
|
||||
#define CD1865_MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR. */
|
||||
#define CD1865_MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD. */
|
||||
#define CD1865_MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS. */
|
||||
#define CD1865_MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8).*/
|
||||
#define CD1865_MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled. */
|
||||
|
||||
|
||||
/*
|
||||
* Modem Change Option Register 2, read/write (0x11).
|
||||
*/
|
||||
#define CD1865_MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR. */
|
||||
#define CD1865_MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD. */
|
||||
#define CD1865_MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS. */
|
||||
|
||||
/*
|
||||
* Modem Change Register, read/write (0x12).
|
||||
*/
|
||||
#define CD1865_MCR_DSRCHG 0x80 /* DSR Changed. */
|
||||
#define CD1865_MCR_CDCHG 0x40 /* CD Changed. */
|
||||
#define CD1865_MCR_CTSCHG 0x20 /* CTS Changed. */
|
||||
|
||||
|
||||
/*
|
||||
* Modem Signal Value Register, read/write (0x28)
|
||||
*
|
||||
* Note:
|
||||
* These are inverted with respect to the actual signals! If the
|
||||
* signal is present, the bit is zero, else the bit is one.
|
||||
*/
|
||||
#define CD1865_MSVR_DSR 0x80 /* Current state of DSR input. */
|
||||
#define CD1865_MSVR_CD 0x40 /* Current state of CD input. */
|
||||
#define CD1865_MSVR_CTS 0x20 /* Current state of CTS input. */
|
||||
#define CD1865_MSVR_DTR 0x02 /* Current state of DTR output. */
|
||||
#define CD1865_MSVR_RTS 0x01 /* Current state of RTS output. */
|
||||
#define CD1865_MSVR_OFF 0xe3 /* All signals off. */
|
||||
#define CD1865_MSVR_ON 0x00 /* All signals on. */
|
||||
|
||||
/*
|
||||
* Escape characters. These are sent in-band when embedded commands are
|
||||
* enabled with CD1865_COR2_ETC.
|
||||
*/
|
||||
#define CD1865_C_ESC 0x00 /* Escape character. */
|
||||
#define CD1865_C_SBRK 0x81 /* Start sending BREAK. */
|
||||
#define CD1865_C_DELAY 0x82 /* Delay output. */
|
||||
#define CD1865_C_EBRK 0x83 /* Stop sending BREAK. */
|
||||
|
||||
#define CD1865_SRSR_RREQint 0x10 /* Receive request interrupt. */
|
||||
#define CD1865_SRSR_TREQint 0x04 /* Transmit request interrupt. */
|
||||
#define CD1865_SRSR_MREQint 0x01 /* Modem signal change request interrupt.*/
|
||||
#define CD1865_SRSR_REQint 0x15 /* All of the above. */
|
||||
|
||||
#define CD1865_SRCR_PKGTYPE 0x80
|
||||
#define CD1865_SRCR_REGACKEN 0x40
|
||||
#define CD1865_SRCR_DAISYEN 0x20
|
||||
#define CD1865_SRCR_GLOBPRI 0x10
|
||||
#define CD1865_SRCR_UNFAIR 0x08
|
||||
#define CD1865_SRCR_AUTOPRI 0x02
|
||||
#define CD1865_SRCR_PRISEL 0x01
|
2039
sys/dev/sx/sx.c
Normal file
2039
sys/dev/sx/sx.c
Normal file
File diff suppressed because it is too large
Load Diff
210
sys/dev/sx/sx.h
Normal file
210
sys/dev/sx/sx.h
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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$
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Per-channel soft information structure, stored in the driver. It's called
|
||||
* "sx_port" just because the si driver calls it "si_port."
|
||||
*
|
||||
* This information is mostly visible via ioctl().
|
||||
*/
|
||||
struct sx_port {
|
||||
int sp_chan; /* Channel number, for convenience. */
|
||||
struct tty *sp_tty;
|
||||
int sp_state;
|
||||
int sp_active_out; /* callout is open */
|
||||
int sp_dtr_wait; /* DTR holddown in hz */
|
||||
int sp_delta_overflows;
|
||||
u_int sp_wopeners; /* Processes waiting for DCD. */
|
||||
u_char sp_hotchar; /* ldisc specific ASAP char */
|
||||
struct termios sp_iin; /* Initial state. */
|
||||
struct termios sp_iout;
|
||||
struct termios sp_lin; /* Lock state. */
|
||||
struct termios sp_lout;
|
||||
#ifdef SX_DEBUG
|
||||
int sp_debug; /* debug mask */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Various important values.
|
||||
*/
|
||||
#define SX_NUMCHANS 8 /* Eight channels on an I/O8+. */
|
||||
#define SX_PCI_IO_SPACE 8 /* How much address space to use. */
|
||||
#define SX_CCR_TIMEOUT 10000 /* Channel Command Register timeout, 10ms. */
|
||||
#define SX_GSVR_TIMEOUT 1000 /* GSVR reset timeout, 1ms. */
|
||||
#define SX_CD1865_ID 0x10 /* ID of the I/O8+ CD1865 chip. */
|
||||
#define SX_EI 0x80 /* "Enable interrupt" flag for I/O8+ commands.*/
|
||||
|
||||
#define SX_DATA_REG 0 /* Data register. */
|
||||
#define SX_ADDR_REG 1 /* Address register. */
|
||||
|
||||
/*
|
||||
* The I/O8+ has a 25MHz oscillator on board, but the CD1865 runs at half
|
||||
* that.
|
||||
*/
|
||||
#define SX_CD1865_CLOCK 12500000 /* CD1865 clock on I/O8+. */
|
||||
#define SX_CD1865_TICK 4000 /* Timer tick rate, via prescaler. */
|
||||
#define SX_CD1865_PRESCALE (SX_CD1865_CLOCK/SX_CD1865_TICK) /* Prescale value.*/
|
||||
|
||||
#include <sys/callout.h>
|
||||
|
||||
/*
|
||||
* Device numbering for the sx device.
|
||||
*
|
||||
* The minor number is broken up into four fields as follows:
|
||||
* Field Bits Mask
|
||||
* --------------------- ---- ----
|
||||
* Channel (port) number 0-2 0x07
|
||||
* "DTR pin is DTR" flag 3 0x08
|
||||
* Unused (zero) 4 0x10
|
||||
* Card number 5-6 0x60
|
||||
* Callout device flag 7 0x80
|
||||
*
|
||||
* The next 8 bits in the word is the major number, followed by the
|
||||
* "initial state device" flag and then the "lock state device" flag.
|
||||
*/
|
||||
#define SX_CHAN_MASK 0x07
|
||||
#define SX_DTRPIN_MASK 0x08
|
||||
#define SX_CARD_MASK 0x60
|
||||
#define SX_TTY_MASK 0x7f
|
||||
#define SX_CALLOUT_MASK 0x80
|
||||
#define SX_INIT_STATE_MASK 0x10000
|
||||
#define SX_LOCK_STATE_MASK 0x20000
|
||||
#define SX_STATE_MASK 0x30000
|
||||
#define SX_SPECIAL_MASK 0x30000
|
||||
|
||||
#define SX_CARDSHIFT 5
|
||||
#define SX_MINOR2CHAN(m) (m & SX_CHAN_MASK)
|
||||
#define SX_MINOR2CARD(m) ((m & SX_CARD_MASK) >> SX_CARDSHIFT)
|
||||
#define SX_MINOR2TTY(m) (m & SX_TTY_MASK)
|
||||
|
||||
#define DEV_IS_CALLOUT(m) (m & SX_CALLOUT_MASK)
|
||||
#define DEV_IS_STATE(m) (m & SX_STATE_MASK)
|
||||
#define DEV_IS_SPECIAL(m) (m & SX_SPECIAL_MASK)
|
||||
#define DEV_DTRPIN(m) (m & SX_DTRPIN_MASK)
|
||||
|
||||
#define MINOR2SC(m) ((struct sx_softc *)devclass_get_softc(sx_devclass,\
|
||||
SX_MINOR2CARD(m)))
|
||||
#define MINOR2PP(m) (MINOR2SC((m))->sc_ports + SX_MINOR2CHAN((m)))
|
||||
#define MINOR2TP(m) (MINOR2PP((m))->sp_tty)
|
||||
#define TP2PP(tp) (MINOR2PP(SX_MINOR2TTY(minor((tp)->t_dev))))
|
||||
#define TP2SC(tp) (MINOR2SC(minor((tp)->t_dev)))
|
||||
#define PP2SC(pp) (MINOR2SC(minor((pp)->sp_tty->t_dev)))
|
||||
|
||||
/* Buffer parameters */
|
||||
#define SX_BUFFERSIZE CD1865_RFIFOSZ /* Just the size of the receive FIFO. */
|
||||
#define SX_I_HIGH_WATER (TTYHOG - 2 * SX_BUFFERSIZE)
|
||||
|
||||
/*
|
||||
* Precomputed bitrate clock divisors. Formula is
|
||||
*
|
||||
* Clock rate (Hz) 12500000
|
||||
* divisor = --------------- or ------------
|
||||
* 16 * bit rate 16 * bitrate
|
||||
*
|
||||
* All values are rounded to the nearest integer.
|
||||
*/
|
||||
#define CLK75 0x28b1 /* 10416.666667 */
|
||||
#define CLK110 0x1bbe /* 7102.272727 */
|
||||
#define CLK150 0x1458 /* 5208.333333 */
|
||||
#define CLK300 0x0a2c /* 2604.166667 */
|
||||
#define CLK600 0x0516 /* 1302.083333 */
|
||||
#define CLK1200 0x028b /* 651.0416667 */
|
||||
#define CLK2000 0x0187 /* 390.625 */
|
||||
#define CLK2400 0x0146 /* 325.5208333 */
|
||||
#define CLK4800 0x00a3 /* 162.7604167 */
|
||||
#define CLK7200 0x006d /* 108.5069444 */
|
||||
#define CLK9600 0x0051 /* 81.38020833 */
|
||||
#define CLK19200 0x0029 /* 40.69010417 */
|
||||
#define CLK38400 0x0014 /* 20.34505208 */
|
||||
#define CLK57600 0x000e /* 13.56336806 */
|
||||
#define CLK115200 0x0007 /* 6.781684028 */
|
||||
|
||||
|
||||
/* sp_state */
|
||||
#define SX_SS_CLOSED 0x00000 /* Port is closed. */
|
||||
#define SX_SS_OPEN 0x00001 /* Port is open and active. */
|
||||
#define SX_SS_XMIT 0x00002 /* We're transmitting data. */
|
||||
#define SX_SS_INTR 0x00004 /* We're processing an interrupt. */
|
||||
#define SX_SS_CLOSING 0x00008 /* in the middle of an sxclose() */
|
||||
#define SX_SS_WAITWRITE 0x00010
|
||||
#define SX_SS_BLOCKWRITE 0x00020
|
||||
#define SX_SS_DTR_OFF 0x00040 /* DTR held off */
|
||||
#define SX_SS_IFLOW 0x00080 /* Input (RTS) flow control on. */
|
||||
#define SX_SS_OFLOW 0x00100 /* Output (CTS) flow control on. */
|
||||
#define SX_SS_IRCV 0x00200 /* In a receive interrupt. */
|
||||
#define SX_SS_IMODEM 0x00400 /* In a modem-signal interrupt. */
|
||||
#define SX_SS_IRCVEXC 0x00800 /* In a receive-exception interrupt. */
|
||||
#define SX_SS_IXMIT 0x01000 /* In a transmit interrupt. */
|
||||
#define SX_SS_OSTOP 0x02000 /* Stopped by output flow control. */
|
||||
#define SX_SS_ISTOP 0x04000 /* Stopped by input flow control. */
|
||||
#define SX_SS_DTRPIN 0x08000 /* DTR/RTS pin is DTR. */
|
||||
#define SX_SS_DOBRK 0x10000 /* Change break status. */
|
||||
#define SX_SS_BREAK 0x20000 /* Doing break. */
|
||||
|
||||
#define SX_DTRPIN(pp) ((pp)->sp_state & SX_SS_DTRPIN) /* DTR/RTS pin is DTR.*/
|
||||
#define SX_XMITTING(pp) ((pp)->sp_state & SX_SS_XMIT) /* We're transmitting. */
|
||||
#define SX_INTR(pp) ((pp)->sp_state & SX_SS_INTR) /* In an interrupt. */
|
||||
#define SX_IXMIT(pp) ((pp)->sp_state & SX_SS_IXMIT) /* Transmit interrupt. */
|
||||
#define SX_IFLOW(pp) ((pp)->sp_state & SX_SS_IFLOW) /* Input flow control. */
|
||||
#define SX_OFLOW(pp) ((pp)->sp_state & SX_SS_OFLOW) /* Output flow control.*/
|
||||
#define SX_IRCV(pp) ((pp)->sp_state & SX_SS_IRCV) /* Receive interrupt. */
|
||||
#define SX_IMODEM(pp) ((pp)->sp_state & SX_SS_IMODEM) /* Modem state change.*/
|
||||
#define SX_IRCVEXC(pp) ((pp)->sp_state & SX_SS_IRCVEXC) /* Rcv exception. */
|
||||
#define SX_OSTOP(pp) ((pp)->sp_state & SX_SS_OSTOP) /* Output stopped. */
|
||||
#define SX_ISTOP(pp) ((pp)->sp_state & SX_SS_ISTOP) /* Input stopped. */
|
||||
#define SX_DOBRK(pp) ((pp)->sp_state & SX_SS_DOBRK) /* Change break status.*/
|
||||
#define SX_BREAK(pp) ((pp)->sp_state & SX_SS_BREAK) /* Doing break. */
|
||||
|
||||
#define DBG_ENTRY 0x00000001
|
||||
#define DBG_DRAIN 0x00000002
|
||||
#define DBG_OPEN 0x00000004
|
||||
#define DBG_CLOSE 0x00000008
|
||||
/* 0x00000010*/
|
||||
#define DBG_WRITE 0x00000020
|
||||
#define DBG_PARAM 0x00000040
|
||||
#define DBG_INTR 0x00000080
|
||||
#define DBG_IOCTL 0x00000100
|
||||
/* 0x00000200 */
|
||||
/* 0x00000400*/
|
||||
#define DBG_OPTIM 0x00000800
|
||||
#define DBG_START 0x00001000
|
||||
#define DBG_EXIT 0x00002000
|
||||
#define DBG_FAIL 0x00004000
|
||||
#define DBG_STOP 0x00008000
|
||||
#define DBG_AUTOBOOT 0x00010000
|
||||
#define DBG_MODEM 0x00020000
|
||||
#define DBG_MODEM_STATE 0x00040000
|
||||
#define DBG_RECEIVE 0x00080000
|
||||
#define DBG_POLL 0x00100000
|
||||
#define DBG_TRANSMIT 0x00200000
|
||||
#define DBG_RECEIVE_EXC 0x00400000
|
||||
#define DBG_PRINTF 0x80000000
|
||||
#define DBG_ALL 0xffffffff
|
166
sys/dev/sx/sx_pci.c
Normal file
166
sys/dev/sx/sx_pci.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/tty.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/clock.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/sx/cd1865.h>
|
||||
#include <dev/sx/sxvar.h>
|
||||
#include <dev/sx/sx.h>
|
||||
#include <dev/sx/sx_util.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
static int
|
||||
sx_pci_probe(
|
||||
device_t dev)
|
||||
{
|
||||
const char *desc = NULL;
|
||||
|
||||
switch (pci_get_devid(dev)) {
|
||||
case 0x200011cb:
|
||||
if (pci_get_subdevice(dev) == (ushort)0xb008) {
|
||||
desc = "Specialix I/O8+ Multiport Serial Card";
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (desc) {
|
||||
device_set_desc(dev, desc);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
sx_pci_attach(device_t dev)
|
||||
{
|
||||
struct sx_softc *sc;
|
||||
void *ih;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
ih = NULL;
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->sc_io_rid = 0x18;
|
||||
sc->sc_io_res = bus_alloc_resource(dev,
|
||||
SYS_RES_IOPORT,
|
||||
&sc->sc_io_rid,
|
||||
0, ~0, 1,
|
||||
RF_ACTIVE);
|
||||
if (!sc->sc_io_res) {
|
||||
device_printf(dev, "can't map I/O\n");
|
||||
goto fail;
|
||||
}
|
||||
sc->sc_st = rman_get_bustag(sc->sc_io_res);
|
||||
sc->sc_sh = rman_get_bushandle(sc->sc_io_res);
|
||||
|
||||
/*
|
||||
* Now that we have the bus handle, we can make certain that this
|
||||
* is an I/O8+.
|
||||
*/
|
||||
if (sx_probe_io8(dev)) {
|
||||
device_printf(dev, "Oops! Device is not an I/O8+ board!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_io_res);*/
|
||||
/*sc->sc_maddr = rman_get_virtual(sc->sc_io_res);*/
|
||||
|
||||
sc->sc_irq_rid = 0;
|
||||
sc->sc_irq_res = bus_alloc_resource(dev,
|
||||
SYS_RES_IRQ,
|
||||
&sc->sc_irq_rid,
|
||||
0, ~0, 1,
|
||||
RF_ACTIVE | RF_SHAREABLE);
|
||||
if (!sc->sc_irq_res) {
|
||||
device_printf(dev, "Can't map interrupt\n");
|
||||
goto fail;
|
||||
}
|
||||
sc->sc_irq = rman_get_start(sc->sc_irq_res);
|
||||
error = bus_setup_intr(dev,
|
||||
sc->sc_irq_res,
|
||||
INTR_TYPE_TTY,
|
||||
sx_intr,
|
||||
sc, &ih);
|
||||
if (error) {
|
||||
device_printf(dev, "Can't activate interrupt\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = sxattach(dev);
|
||||
if (error)
|
||||
goto fail;
|
||||
return (0); /* success */
|
||||
|
||||
fail:
|
||||
if (error == 0)
|
||||
error = ENXIO;
|
||||
if (sc->sc_irq_res) {
|
||||
if (ih)
|
||||
bus_teardown_intr(dev, sc->sc_irq_res, ih);
|
||||
bus_release_resource(dev,
|
||||
SYS_RES_IRQ,
|
||||
sc->sc_irq_rid,
|
||||
sc->sc_irq_res);
|
||||
sc->sc_irq_res = 0;
|
||||
}
|
||||
if (sc->sc_io_res) {
|
||||
bus_release_resource(dev,
|
||||
SYS_RES_IOPORT,
|
||||
sc->sc_io_rid,
|
||||
sc->sc_io_res);
|
||||
sc->sc_io_res = 0;
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
static device_method_t sx_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, sx_pci_probe),
|
||||
DEVMETHOD(device_attach, sx_pci_attach),
|
||||
/* DEVMETHOD(device_detach, sx_pci_detach),*/
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t sx_pci_driver = {
|
||||
"sx",
|
||||
sx_pci_methods,
|
||||
sizeof(struct sx_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(sx, pci, sx_pci_driver, sx_devclass, 0, 0);
|
260
sys/dev/sx/sx_util.c
Normal file
260
sys/dev/sx/sx_util.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#include "opt_debug_sx.h"
|
||||
|
||||
/* Utility and support routines for the Specialix I/O8+ driver. */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/tty.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/clock.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/sx/cd1865.h>
|
||||
#include <dev/sx/sxvar.h>
|
||||
#include <dev/sx/sx.h>
|
||||
#include <dev/sx/sx_util.h>
|
||||
|
||||
/*
|
||||
* sx_probe_io8()
|
||||
* Probe the board to verify that it is a Specialix I/O8+.
|
||||
*
|
||||
* Description:
|
||||
* This is called by sx_pci_attach() (and possibly in the future by
|
||||
* sx_isa_attach()) to verify that the card we're attaching to is
|
||||
* indeed a Specialix I/O8+. To do this, we check for the Prescaler
|
||||
* Period Register of the CD1865 chip and for the Specialix signature
|
||||
* on the DSR input line of each channel. These lines, along with the
|
||||
* RTS output lines, are wired down in hardware.
|
||||
*/
|
||||
int
|
||||
sx_probe_io8(
|
||||
device_t dev)
|
||||
{
|
||||
struct sx_softc *sc;
|
||||
unsigned char val1, val2;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
/*
|
||||
* Try to write the Prescaler Period Register, then read it back,
|
||||
* twice. If this fails, it's not an I/O8+.
|
||||
*/
|
||||
sx_cd1865_out(sc, CD1865_PPRL, 0x5a);
|
||||
DELAY(1);
|
||||
val1 = sx_cd1865_in(sc, CD1865_PPRL);
|
||||
|
||||
sx_cd1865_out(sc, CD1865_PPRL, 0xa5);
|
||||
DELAY(1);
|
||||
val2 = sx_cd1865_in(sc, CD1865_PPRL);
|
||||
|
||||
if ((val1 != 0x5a) || (val2 != 0xa5))
|
||||
return(1);
|
||||
|
||||
/*
|
||||
* Check the lines that Specialix uses as board identification.
|
||||
* These are the DSR input and the RTS output, which are wired
|
||||
* down.
|
||||
*/
|
||||
val1 = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
sx_cd1865_out(sc, CD1865_CAR, i); /* Select channel. */
|
||||
if (sx_cd1865_in(sc, CD1865_MSVR) & CD1865_MSVR_DSR) /* Set? */
|
||||
val1 |= 1 << i; /* OR it in. */
|
||||
}
|
||||
#ifdef notdef
|
||||
val2 = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
sx_cd1865_out(sc, CD1865_CAR, i); /* Select channel. */
|
||||
if (sx_cd1865_in(sc, CD1865_MSVR) & CD1865_MSVR_RTS) /* Set? */
|
||||
val2 |= 1 << i; /* OR it in. */
|
||||
}
|
||||
/*
|
||||
* They managed to switch the bit order between the docs and
|
||||
* the IO8+ card. The new PCI card now conforms to old docs.
|
||||
* They changed the PCI docs to reflect the situation on the
|
||||
* old card.
|
||||
*/
|
||||
val2 = (bp->flags & SX_BOARD_IS_PCI) ? 0x4d : 0xb2;
|
||||
#endif /* notdef */
|
||||
if (val1 != 0x4d) {
|
||||
if (bootverbose)
|
||||
device_printf(dev,
|
||||
"Specialix I/O8+ ID 0x4d not found (0x%02x).\n",
|
||||
val1);
|
||||
return(1);
|
||||
}
|
||||
return(0); /* Probed successfully. */
|
||||
}
|
||||
|
||||
/*
|
||||
* sx_init_CD1865()
|
||||
* Hard-reset and initialize the I/O8+ CD1865 processor.
|
||||
*
|
||||
* Description:
|
||||
* This routine does a hard reset of the CD1865 chip and waits for it
|
||||
* to complete. (The reset should complete after 500us; we wait 1ms
|
||||
* and fail if we time out.) We then initialize the CD1865 processor.
|
||||
*/
|
||||
int
|
||||
sx_init_cd1865(
|
||||
struct sx_softc *sc,
|
||||
int unit)
|
||||
{
|
||||
int s;
|
||||
unsigned int to;
|
||||
|
||||
s = spltty();
|
||||
disable_intr();
|
||||
sx_cd1865_out(sc, CD1865_GSVR, 0x00); /* Clear the GSVR. */
|
||||
sx_cd1865_wait_CCR(sc, 0); /* Wait for the CCR to clear. */
|
||||
sx_cd1865_out(sc, CD1865_CCR, CD1865_CCR_HARDRESET); /* Reset CD1865. */
|
||||
enable_intr();
|
||||
to = SX_GSVR_TIMEOUT/5;
|
||||
while (to-- > 0) {
|
||||
if (sx_cd1865_in(sc, CD1865_GSVR) == 0xff)
|
||||
break;
|
||||
DELAY(5);
|
||||
}
|
||||
if (to == 0) {
|
||||
splx(s);
|
||||
printf("sx%d: Timeout waiting for reset.\n", unit);
|
||||
return(EIO);
|
||||
}
|
||||
/*
|
||||
* The high five bits of the Global Interrupt Vector Register is
|
||||
* used to identify daisy-chained CD1865 chips. The I/O8+ isn't
|
||||
* daisy chained, but we have to initialize the field anyway.
|
||||
*/
|
||||
sx_cd1865_out(sc, CD1865_GIVR, SX_CD1865_ID);
|
||||
/* Clear the Global Interrupting Channel register. */
|
||||
sx_cd1865_out(sc, CD1865_GICR, 0);
|
||||
/*
|
||||
* Set the Service Match Registers to the appropriate values. See
|
||||
* the cd1865.h include file for more information.
|
||||
*/
|
||||
sx_cd1865_out(sc, CD1865_MSMR, CD1865_ACK_MINT); /* Modem. */
|
||||
sx_cd1865_out(sc, CD1865_TSMR, CD1865_ACK_TINT); /* Transmit. */
|
||||
sx_cd1865_out(sc, CD1865_RSMR, CD1865_ACK_RINT); /* Receive. */
|
||||
/*
|
||||
* Set RegAckEn in the Service Request Configuration Register;
|
||||
* we'll be acknowledging service requests in software, not
|
||||
* hardware.
|
||||
*/
|
||||
sx_cd1865_bis(sc, CD1865_SRCR, CD1865_SRCR_REGACKEN);
|
||||
/*
|
||||
* Set the CD1865 timer tick rate. The value here is the processor
|
||||
* clock rate (in MHz) divided by the rate in ticks per second. See
|
||||
* commentary in sx.h.
|
||||
*/
|
||||
sx_cd1865_out(sc, CD1865_PPRH, SX_CD1865_PRESCALE >> 8);
|
||||
sx_cd1865_out(sc, CD1865_PPRL, SX_CD1865_PRESCALE & 0xff);
|
||||
|
||||
splx(s);
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* Set the IRQ using the RTS lines that run to the PAL on the board....
|
||||
*
|
||||
* This is a placeholder for ISA support, if that's ever implemented. This
|
||||
* should _only_ be called from sx_isa_attach().
|
||||
*/
|
||||
int
|
||||
sx_set_irq(
|
||||
struct sx_softc *sc,
|
||||
int unit,
|
||||
int irq)
|
||||
{
|
||||
register int virq;
|
||||
register int i, j;
|
||||
|
||||
switch (irq) {
|
||||
/* In the same order as in the docs... */
|
||||
case 15:
|
||||
virq = 0;
|
||||
break;
|
||||
case 12:
|
||||
virq = 1;
|
||||
break;
|
||||
case 11:
|
||||
virq = 2;
|
||||
break;
|
||||
case 9:
|
||||
virq = 3;
|
||||
break;
|
||||
default:
|
||||
printf("sx%d: Illegal irq %d.\n", unit, irq);
|
||||
return(0);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
sx_cd1865_out(sc, CD1865_CAR, i); /* Select channel. */
|
||||
j = ((virq >> i) & 0x1) ? MSVR_RTS : 0;
|
||||
sx_cd1865_out(sc, CD1865_MSVRTS, j);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* notyet */
|
||||
|
||||
/*
|
||||
* sx_int_port()
|
||||
* Determine the port that interrupted us.
|
||||
*
|
||||
* Description:
|
||||
* This routine checks the Global Interrupting Channel Register (GICR)
|
||||
* to find the port that caused an interrupt. It returns a pointer to
|
||||
* the sx_port structure of the interrupting port, or NULL if there was
|
||||
* none.
|
||||
*
|
||||
* XXX - check type/validity of interrupt?
|
||||
*/
|
||||
struct sx_port *
|
||||
sx_int_port(
|
||||
struct sx_softc *sc,
|
||||
int unit)
|
||||
{
|
||||
unsigned char chan;
|
||||
struct sx_port *pp;
|
||||
|
||||
chan = (sx_cd1865_in(sc, CD1865_GSCR2|SX_EI) & CD1865_GICR_CHAN_MASK)
|
||||
>> CD1865_GICR_CHAN_SHIFT;
|
||||
DPRINT((NULL, DBG_INTR, "Intr chan %d\n", chan));
|
||||
if (chan < CD1865_NUMCHAN) {
|
||||
pp = sc->sc_ports + (int)chan;
|
||||
return(pp);
|
||||
}
|
||||
printf("sx%d: False interrupt on port %d.\n", unit, chan);
|
||||
return(NULL);
|
||||
}
|
159
sys/dev/sx/sx_util.h
Normal file
159
sys/dev/sx/sx_util.h
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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);
|
83
sys/dev/sx/sxvar.h
Normal file
83
sys/dev/sx/sxvar.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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$
|
||||
*/
|
||||
|
||||
|
||||
int sxattach(device_t dev);
|
||||
void sx_intr(void *);
|
||||
|
||||
extern devclass_t sx_devclass;
|
||||
|
||||
struct sx_softc {
|
||||
struct sx_port *sc_ports; /* port structures for this card */
|
||||
int sc_irq; /* copy of attach irq */
|
||||
struct resource *sc_io_res;
|
||||
struct resource *sc_irq_res;
|
||||
bus_space_tag_t sc_st;
|
||||
bus_space_handle_t sc_sh;
|
||||
int sc_io_rid;
|
||||
int sc_irq_rid;
|
||||
int sc_unit;
|
||||
};
|
||||
|
||||
#ifdef SX_DEBUG
|
||||
/*
|
||||
* debugging stuff
|
||||
*/
|
||||
void sx_dprintf(struct sx_port *pp, int flags, const char *fmt, ...);
|
||||
|
||||
#define DPRINT(x) sx_dprintf x
|
||||
|
||||
#define DBG_ENTRY 0x00000001
|
||||
#define DBG_DRAIN 0x00000002
|
||||
#define DBG_OPEN 0x00000004
|
||||
#define DBG_CLOSE 0x00000008
|
||||
#define DBG_READ 0x00000010
|
||||
#define DBG_WRITE 0x00000020
|
||||
#define DBG_PARAM 0x00000040
|
||||
#define DBG_INTR 0x00000080
|
||||
#define DBG_IOCTL 0x00000100
|
||||
/* 0x00000200 */
|
||||
#define DBG_SELECT 0x00000400
|
||||
#define DBG_OPTIM 0x00000800
|
||||
#define DBG_START 0x00001000
|
||||
#define DBG_EXIT 0x00002000
|
||||
#define DBG_FAIL 0x00004000
|
||||
#define DBG_STOP 0x00008000
|
||||
#define DBG_AUTOBOOT 0x00010000
|
||||
#define DBG_MODEM 0x00020000
|
||||
#define DBG_DOWNLOAD 0x00040000
|
||||
/* 0x00080000*/
|
||||
#define DBG_POLL 0x00100000
|
||||
#define DBG_ALL 0xffffffff
|
||||
|
||||
#else
|
||||
|
||||
#define DPRINT(x) /* void */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user