Changes to add support for the PCI version of the Cyclades Cyclom-Y

serial adapter, and support for multiple Cyclom controllers.
This commit is contained in:
David Greenman 1996-10-13 01:09:24 +00:00
parent d2322fc6ac
commit 3010cd6550
9 changed files with 811 additions and 409 deletions

View File

@ -305,6 +305,7 @@ pccard/pccard.c optional crd
pccard/pcic.c optional pcic device-driver pccard/pcic.c optional pcic device-driver
pci/aic7870.c optional ahc device-driver pci/aic7870.c optional ahc device-driver
pci/bt9xx.c optional bt device-driver pci/bt9xx.c optional bt device-driver
pci/cy_pci.c optional cy device-driver
pci/if_de.c optional de device-driver pci/if_de.c optional de device-driver
pci/if_ed_p.c optional ed device-driver pci/if_ed_p.c optional ed device-driver
pci/if_fxp.c optional fxp device-driver pci/if_fxp.c optional fxp device-driver

View File

@ -27,7 +27,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: cy.c,v 1.36 1996/10/04 10:33:08 davidg Exp $ * $Id: cy.c,v 1.37 1996/10/04 14:17:32 davidg Exp $
*/ */
#include "cy.h" #include "cy.h"
@ -141,7 +141,7 @@
/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
#define CD1400_xIVR_CHAN_SHIFT 3 #define CD1400_xIVR_CHAN_SHIFT 3
#define CD1400_xIVR_CHAN 0x0F /* XXX reduce to pack Cyclom-8Ys */ #define CD1400_xIVR_CHAN 0x1F /* XXX reduce to pack Cyclom-8Ys */
#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) #define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE)
@ -153,7 +153,8 @@
#define CONTROL_LOCK_STATE 0x40 #define CONTROL_LOCK_STATE 0x40
#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) #define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS + \
(((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
/* /*
* Input buffer watermarks. * Input buffer watermarks.
@ -262,6 +263,7 @@ struct com_s {
cy_addr cy_iobase; /* base address of this port's cyclom */ cy_addr cy_iobase; /* base address of this port's cyclom */
cy_addr iobase; /* base address of this port's cd1400 */ cy_addr iobase; /* base address of this port's cd1400 */
int cy_align; /* index for register alignment */
struct tty *tp; /* cross reference */ struct tty *tp; /* cross reference */
@ -330,8 +332,10 @@ void siopoll __P((void));
#define siommap nommap #define siommap nommap
#define siostrategy nostrategy #define siostrategy nostrategy
int cyattach_common __P((cy_addr cy_iobase, int cy_align));
static int cy_units __P((cy_addr cy_iobase, int cy_align));
static int sioattach __P((struct isa_device *dev)); static int sioattach __P((struct isa_device *dev));
static void cd1400_channel_cmd __P((cy_addr iobase, int cmd)); static void cd1400_channel_cmd __P((cy_addr iobase, int cmd, int cy_align));
static timeout_t siodtrwakeup; static timeout_t siodtrwakeup;
static void comhardclose __P((struct com_s *com)); static void comhardclose __P((struct com_s *com));
#if 0 #if 0
@ -399,6 +403,7 @@ static u_int cy_timeouts;
#endif #endif
static int cy_nr_cd1400s[NCY]; static int cy_nr_cd1400s[NCY];
static int cy_total_devices;
#undef RxFifoThreshold #undef RxFifoThreshold
static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
static int cy_chip_offset[] = { static int cy_chip_offset[] = {
@ -416,16 +421,9 @@ static int
sioprobe(dev) sioprobe(dev)
struct isa_device *dev; struct isa_device *dev;
{ {
int cyu;
u_char firmware_version;
cy_addr iobase; cy_addr iobase;
int unit;
iobase = (cy_addr)dev->id_maddr; iobase = (cy_addr)dev->id_maddr;
unit = dev->id_unit;
if ((u_int)unit >= NCY)
return (0);
cy_nr_cd1400s[unit] = 0;
/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
cy_inb(iobase, CY16_RESET); /* XXX? */ cy_inb(iobase, CY16_RESET); /* XXX? */
@ -435,22 +433,34 @@ sioprobe(dev)
cy_outb(iobase, CY_CLEAR_INTR, 0); cy_outb(iobase, CY_CLEAR_INTR, 0);
DELAY(500); DELAY(500);
return (cy_units(iobase, 0) == 0 ? 0 : -1);
}
static int
cy_units(cy_iobase, cy_align)
cy_addr cy_iobase;
int cy_align;
{
cy_addr iobase;
int cyu;
for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
int i; int i;
u_char firmware_version;
iobase = (cy_addr) (dev->id_maddr + cy_chip_offset[cyu]); iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
/* wait for chip to become ready for new command */ /* wait for chip to become ready for new command */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
DELAY(50); DELAY(50);
if (!cd_inb(iobase, CD1400_CCR)) if (!cd_inb(iobase, CD1400_CCR, cy_align))
break; break;
} }
/* clear the GFRCR register */ /* clear the GFRCR register */
cd_outb(iobase, CD1400_GFRCR, 0); cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
/* issue a reset command */ /* issue a reset command */
cd_outb(iobase, CD1400_CCR, cd_outb(iobase, CD1400_CCR, cy_align,
CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
/* wait for the CD1400 to initialize itself */ /* wait for the CD1400 to initialize itself */
@ -458,7 +468,7 @@ sioprobe(dev)
DELAY(50); DELAY(50);
/* retrieve firmware version */ /* retrieve firmware version */
firmware_version = cd_inb(iobase, CD1400_GFRCR); firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
if ((firmware_version & 0xf0) == 0x40) if ((firmware_version & 0xf0) == 0x40)
break; break;
} }
@ -470,38 +480,60 @@ sioprobe(dev)
*/ */
if ((firmware_version & 0xf0) != 0x40) if ((firmware_version & 0xf0) != 0x40)
break; break;
++cy_nr_cd1400s[unit];
} }
return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); return (cyu);
} }
static int static int
sioattach(isdp) sioattach(isdp)
struct isa_device *isdp; struct isa_device *isdp;
{ {
int cyu; int adapter;
cy_addr cy_iobase;
dev_t dev;
cy_addr iobase;
int ncyu;
int unit;
unit = isdp->id_unit; adapter = cyattach_common((cy_addr) isdp->id_maddr, 0);
if ((u_int)unit >= NCY) if (adapter < 0)
return (0);
ncyu = cy_nr_cd1400s[unit];
if (ncyu == 0)
return (0); return (0);
/*
* XXX
* This kludge is to allow ISA/PCI device specifications in the
* kernel config file to be in any order.
*/
if (isdp->id_unit != adapter) {
printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter);
isdp->id_unit = adapter; /* XXX */
}
isdp->id_ri_flags |= RI_FAST; isdp->id_ri_flags |= RI_FAST;
return (1);
}
cy_iobase = (cy_addr)isdp->id_maddr; int
unit *= CY_MAX_PORTS; cyattach_common(cy_iobase, cy_align)
cy_addr cy_iobase;
int cy_align;
{
int cyu, ncyu, unit, adapter;
dev_t dev;
cy_addr iobase;
adapter = cy_total_devices;
if ((u_int)adapter >= NCY) {
printf("cy%d: can't attach adapter: insufficient cy devices configured\n",
adapter);
return (-1);
}
ncyu = cy_units(cy_iobase, cy_align);
if (ncyu == 0)
return (-1);
cy_nr_cd1400s[adapter] = ncyu;
cy_total_devices++;
unit = adapter * CY_MAX_PORTS;
for (cyu = 0; cyu < ncyu; ++cyu) { for (cyu = 0; cyu < ncyu; ++cyu) {
int cdu; int cdu;
iobase = (cy_addr) (isdp->id_maddr + cy_chip_offset[cyu]); iobase = (cy_addr) (cy_iobase + (cy_chip_offset[cyu] << cy_align));
/* Set up a receive timeout period of than 1+ ms. */ /* Set up a receive timeout period of than 1+ ms. */
cd_outb(iobase, CD1400_PPR, cd_outb(iobase, CD1400_PPR, cy_align,
howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000));
for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
@ -522,6 +554,7 @@ sioattach(isdp)
com->cy_iobase = cy_iobase; com->cy_iobase = cy_iobase;
com->iobase = iobase; com->iobase = iobase;
com->cy_align = cy_align;
/* /*
* We don't use all the flags from <sys/ttydefaults.h> since they * We don't use all the flags from <sys/ttydefaults.h> since they
@ -574,9 +607,9 @@ sioattach(isdp)
} }
/* ensure an edge for the next interrupt */ /* ensure an edge for the next interrupt */
cy_outb(cy_iobase, CY_CLEAR_INTR, 0); cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
return (1); return (adapter);
} }
static int static int
@ -664,8 +697,8 @@ open_top:
iobase = com->iobase; iobase = com->iobase;
/* reset this channel */ /* reset this channel */
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align);
/* /*
* Resetting disables the transmitter and receiver as well as * Resetting disables the transmitter and receiver as well as
@ -677,7 +710,7 @@ open_top:
com->channel_control = 0; com->channel_control = 0;
/* Encode per-board unit in LIVR for access in intr routines. */ /* Encode per-board unit in LIVR for access in intr routines. */
cd_outb(iobase, CD1400_LIVR, cd_outb(iobase, CD1400_LIVR, com->cy_align,
(unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
/* /*
@ -732,8 +765,8 @@ open_top:
(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
disable_intr(); disable_intr();
com->prev_modem_status = com->last_modem_status com->prev_modem_status = com->last_modem_status
= cd_inb(iobase, CD1400_MSVR2); = cd_inb(iobase, CD1400_MSVR2, com->cy_align);
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
= CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
enable_intr(); enable_intr();
@ -827,7 +860,7 @@ comhardclose(com)
com->poll_output = FALSE; com->poll_output = FALSE;
#endif #endif
com->do_timestamp = 0; com->do_timestamp = 0;
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
#if 0 #if 0
outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
#endif #endif
@ -837,7 +870,7 @@ comhardclose(com)
outb(iobase + com_ier, 0); outb(iobase + com_ier, 0);
#else #else
disable_intr(); disable_intr();
cd_outb(iobase, CD1400_SRER, com->intr_enable = 0); cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable = 0);
enable_intr(); enable_intr();
#endif #endif
tp = com->tp; tp = com->tp;
@ -859,7 +892,7 @@ comhardclose(com)
com->channel_control = CD1400_CCR_CMDCHANCTL com->channel_control = CD1400_CCR_CMDCHANCTL
| CD1400_CCR_XMTEN | CD1400_CCR_XMTEN
| CD1400_CCR_RCVDIS; | CD1400_CCR_RCVDIS;
cd1400_channel_cmd(iobase, com->channel_control); cd1400_channel_cmd(iobase, com->channel_control, com->cy_align);
if (com->dtr_wait != 0) { if (com->dtr_wait != 0) {
timeout(siodtrwakeup, com, com->dtr_wait); timeout(siodtrwakeup, com, com->dtr_wait);
@ -948,20 +981,19 @@ void
siointr(unit) siointr(unit)
int unit; int unit;
{ {
int baseu; cy_addr cy_iobase, iobase;
cy_addr cy_iobase; int baseu, cyu, cy_align;
int cyu; u_char status;
cy_addr iobase;
u_char status;
baseu = unit * CY_MAX_PORTS; baseu = unit * CY_MAX_PORTS;
cy_iobase = com_addr(baseu)->cy_iobase; cy_iobase = com_addr(baseu)->cy_iobase;
cy_align = com_addr(baseu)->cy_align;
/* check each CD1400 in turn */ /* check each CD1400 in turn */
for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
iobase = (cy_addr) (cy_iobase + cy_chip_offset[cyu]); iobase = (cy_addr) (cy_iobase + (cy_chip_offset[cyu] << cy_align));
/* poll to see if it has any work */ /* poll to see if it has any work */
status = cd_inb(iobase, CD1400_SVRR); status = cd_inb(iobase, CD1400_SVRR, cy_align);
if (status == 0) if (status == 0)
continue; continue;
#ifdef CyDebug #ifdef CyDebug
@ -981,13 +1013,13 @@ siointr(unit)
#endif #endif
#ifdef PollMode #ifdef PollMode
save_rir = cd_inb(iobase, CD1400_RIR); save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter rx service */ /* enter rx service */
cd_outb(iobase, CD1400_CAR, save_rir); cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
serv_type = cd_inb(iobase, CD1400_RIVR); serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
com = com_addr(baseu com = com_addr(baseu
+ ((serv_type >> CD1400_xIVR_CHAN_SHIFT) + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
& CD1400_xIVR_CHAN)); & CD1400_xIVR_CHAN));
@ -1002,9 +1034,9 @@ siointr(unit)
if (serv_type & CD1400_RIVR_EXCEPTION) { if (serv_type & CD1400_RIVR_EXCEPTION) {
++com->recv_exception; ++com->recv_exception;
line_status = cd_inb(iobase, CD1400_RDSR); line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
/* break/unnattached error bits or real input? */ /* break/unnattached error bits or real input? */
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifndef SOFT_HOTCHAR #ifndef SOFT_HOTCHAR
if (line_status & CD1400_RDSR_SPECIAL if (line_status & CD1400_RDSR_SPECIAL
&& com->hotchar != 0) && com->hotchar != 0)
@ -1053,7 +1085,7 @@ siointr(unit)
outb(com->modem_ctl_port, outb(com->modem_ctl_port,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
if (line_status & LSR_OE) if (line_status & LSR_OE)
@ -1063,7 +1095,7 @@ siointr(unit)
} else { } else {
int ifree; int ifree;
count = cd_inb(iobase, CD1400_RDCR); count = cd_inb(iobase, CD1400_RDCR, cy_align);
com->bytes_in += count; com->bytes_in += count;
ioptr = com->iptr; ioptr = com->iptr;
ifree = com->ibufend - ioptr; ifree = com->ibufend - ioptr;
@ -1075,7 +1107,7 @@ siointr(unit)
microtime(&com->timestamp); microtime(&com->timestamp);
do { do {
recv_data = cd_inb(iobase, recv_data = cd_inb(iobase,
CD1400_RDSR); CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data && recv_data
@ -1090,7 +1122,7 @@ siointr(unit)
com->delta_error_counts com->delta_error_counts
[CE_INTERRUPT_BUF_OVERFLOW] += count; [CE_INTERRUPT_BUF_OVERFLOW] += count;
do { do {
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data == com->hotchar) && recv_data == com->hotchar)
@ -1107,12 +1139,12 @@ siointr(unit)
outb(com->modem_ctl_port, outb(com->modem_ctl_port,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
com_events += count; com_events += count;
do { do {
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data == com->hotchar) && recv_data == com->hotchar)
@ -1129,12 +1161,12 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_RIR, cd_outb(iobase, CD1400_RIR, cy_align,
save_rir save_rir
& ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
if (status & CD1400_SVRR_MDMCH) { if (status & CD1400_SVRR_MDMCH) {
@ -1148,11 +1180,11 @@ cont:
#endif #endif
#ifdef PollMode #ifdef PollMode
save_mir = cd_inb(iobase, CD1400_MIR); save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter modem service */ /* enter modem service */
cd_outb(iobase, CD1400_CAR, save_mir); cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
+ (save_mir & CD1400_MIR_CHAN)); + (save_mir & CD1400_MIR_CHAN));
@ -1165,7 +1197,7 @@ cont:
& CD1400_xIVR_CHAN)); & CD1400_xIVR_CHAN));
#endif #endif
++com->mdm; ++com->mdm;
modem_status = cd_inb(iobase, CD1400_MSVR2); modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
if (modem_status != com->last_modem_status) { if (modem_status != com->last_modem_status) {
if (com->do_dcd_timestamp if (com->do_dcd_timestamp
&& !(com->last_modem_status & MSR_DCD) && !(com->last_modem_status & MSR_DCD)
@ -1194,13 +1226,13 @@ cont:
| CS_ODEVREADY) | CS_ODEVREADY)
&& !(com->intr_enable && !(com->intr_enable
& CD1400_SRER_TXRDY)) & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} else { } else {
com->state &= ~CS_ODEVREADY; com->state &= ~CS_ODEVREADY;
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
&= ~CD1400_SRER_TXRDY); &= ~CD1400_SRER_TXRDY);
} }
@ -1210,12 +1242,12 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_MIR, cd_outb(iobase, CD1400_MIR, cy_align,
save_mir save_mir
& ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
if (status & CD1400_SVRR_TXRDY) { if (status & CD1400_SVRR_TXRDY) {
@ -1228,11 +1260,11 @@ cont:
#endif #endif
#ifdef PollMode #ifdef PollMode
save_tir = cd_inb(iobase, CD1400_TIR); save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter tx service */ /* enter tx service */
cd_outb(iobase, CD1400_CAR, save_tir); cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
com = com_addr(baseu com = com_addr(baseu
+ cyu * CD1400_NO_OF_CHANNELS + cyu * CD1400_NO_OF_CHANNELS
+ (save_tir & CD1400_TIR_CHAN)); + (save_tir & CD1400_TIR_CHAN));
@ -1255,7 +1287,7 @@ cont:
ocount = CD1400_TX_FIFO_SIZE; ocount = CD1400_TX_FIFO_SIZE;
com->bytes_out += ocount; com->bytes_out += ocount;
do do
cd_outb(iobase, CD1400_TDR, *ioptr++); cd_outb(iobase, CD1400_TDR, cy_align, *ioptr++);
while (--ocount != 0); while (--ocount != 0);
com->obufq.l_head = ioptr; com->obufq.l_head = ioptr;
if (ioptr >= com->obufq.l_tail) { if (ioptr >= com->obufq.l_tail) {
@ -1271,7 +1303,7 @@ cont:
} else { } else {
/* output just completed */ /* output just completed */
com->state &= ~CS_BUSY; com->state &= ~CS_BUSY;
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
&= ~CD1400_SRER_TXRDY); &= ~CD1400_SRER_TXRDY);
} }
@ -1285,18 +1317,18 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_TIR, cd_outb(iobase, CD1400_TIR, cy_align,
save_tir save_tir
& ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
} }
/* ensure an edge for the next interrupt */ /* ensure an edge for the next interrupt */
cy_outb(cy_iobase, CY_CLEAR_INTR, 0); cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
schedsofttty(); schedsofttty();
} }
@ -1406,7 +1438,7 @@ sioioctl(dev, cmd, data, flag, p)
splx(s); splx(s);
return (error); return (error);
} }
cd_outb(iobase, CD1400_CAR, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN);
switch (cmd) { switch (cmd) {
#if 0 #if 0
case TIOCSBRK: case TIOCSBRK:
@ -1544,9 +1576,9 @@ repeat:
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#else #else
iobase = com->iobase, iobase = com->iobase,
cd_outb(iobase, CD1400_CAR, cd_outb(iobase, CD1400_CAR, com->cy_align,
unit & CD1400_CAR_CHAN), unit & CD1400_CAR_CHAN),
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#endif #endif
enable_intr(); enable_intr();
@ -1669,19 +1701,19 @@ comparam(tp, t)
com = com_addr(unit); com = com_addr(unit);
iobase = com->iobase; iobase = com->iobase;
s = spltty(); s = spltty();
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
if (odivisor == 0) if (odivisor == 0)
(void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
else else
(void)commctl(com, TIOCM_DTR, DMBIS); (void)commctl(com, TIOCM_DTR, DMBIS);
if (idivisor != 0) { if (idivisor != 0) {
cd_outb(iobase, CD1400_RBPR, idivisor); cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor);
cd_outb(iobase, CD1400_RCOR, iprescaler); cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler);
} }
if (odivisor != 0) { if (odivisor != 0) {
cd_outb(iobase, CD1400_TBPR, odivisor); cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor);
cd_outb(iobase, CD1400_TCOR, oprescaler); cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler);
} }
/* /*
@ -1694,20 +1726,20 @@ comparam(tp, t)
| (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
if (opt != com->channel_control) { if (opt != com->channel_control) {
com->channel_control = opt; com->channel_control = opt;
cd1400_channel_cmd(iobase, opt); cd1400_channel_cmd(iobase, opt, com->cy_align);
} }
#ifdef Smarts #ifdef Smarts
/* set special chars */ /* set special chars */
/* XXX if one is _POSIX_VDISABLE, can't use some others */ /* XXX if one is _POSIX_VDISABLE, can't use some others */
if (t->c_cc[VSTOP] != _POSIX_VDISABLE) if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR1, t->c_cc[VSTOP]); cd_outb(iobase, CD1400_SCHR1, com->cy_align, t->c_cc[VSTOP]);
if (t->c_cc[VSTART] != _POSIX_VDISABLE) if (t->c_cc[VSTART] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR2, t->c_cc[VSTART]); cd_outb(iobase, CD1400_SCHR2, com->cy_align, t->c_cc[VSTART]);
if (t->c_cc[VINTR] != _POSIX_VDISABLE) if (t->c_cc[VINTR] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR3, t->c_cc[VINTR]); cd_outb(iobase, CD1400_SCHR3, com->cy_align, t->c_cc[VINTR]);
if (t->c_cc[VSUSP] != _POSIX_VDISABLE) if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]);
#endif #endif
/* /*
@ -1754,14 +1786,14 @@ comparam(tp, t)
cor_change = 0; cor_change = 0;
if (opt != com->cor[0]) { if (opt != com->cor[0]) {
cor_change |= CD1400_CCR_COR1; cor_change |= CD1400_CCR_COR1;
cd_outb(iobase, CD1400_COR1, com->cor[0] = opt); cd_outb(iobase, CD1400_COR1, com->cy_align, com->cor[0] = opt);
} }
/* /*
* Set receive time-out period, normally to max(one char time, 5 ms). * Set receive time-out period, normally to max(one char time, 5 ms).
*/ */
if (t->c_ispeed == 0) if (t->c_ispeed == 0)
itimeout = cd_inb(iobase, CD1400_RTPR); itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align);
else { else {
itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
@ -1777,7 +1809,7 @@ comparam(tp, t)
itimeout = t->c_cc[VTIME] * 10; itimeout = t->c_cc[VTIME] * 10;
if (itimeout > 255) if (itimeout > 255)
itimeout = 255; itimeout = 255;
cd_outb(iobase, CD1400_RTPR, itimeout); cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout);
/* /*
* set channel option register 2 - * set channel option register 2 -
@ -1796,7 +1828,7 @@ comparam(tp, t)
#endif #endif
if (opt != com->cor[1]) { if (opt != com->cor[1]) {
cor_change |= CD1400_CCR_COR2; cor_change |= CD1400_CCR_COR2;
cd_outb(iobase, CD1400_COR2, com->cor[1] = opt); cd_outb(iobase, CD1400_COR2, com->cy_align, com->cor[1] = opt);
} }
/* /*
@ -1814,12 +1846,12 @@ comparam(tp, t)
#endif #endif
if (opt != com->cor[2]) { if (opt != com->cor[2]) {
cor_change |= CD1400_CCR_COR3; cor_change |= CD1400_CCR_COR3;
cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt);
} }
/* notify the CD1400 if COR1-3 have changed */ /* notify the CD1400 if COR1-3 have changed */
if (cor_change) if (cor_change)
cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change); cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change, com->cy_align);
/* /*
* set channel option register 4 - * set channel option register 4 -
@ -1858,7 +1890,7 @@ comparam(tp, t)
#else #else
opt |= CD1400_COR4_PFO_EXCEPTION; opt |= CD1400_COR4_PFO_EXCEPTION;
#endif #endif
cd_outb(iobase, CD1400_COR4, opt); cd_outb(iobase, CD1400_COR4, com->cy_align, opt);
/* /*
* set channel option register 5 - * set channel option register 5 -
@ -1875,7 +1907,7 @@ comparam(tp, t)
if (t->c_oflag & OCRNL) if (t->c_oflag & OCRNL)
opt |= CD1400_COR5_OCRNL; opt |= CD1400_COR5_OCRNL;
#endif #endif
cd_outb(iobase, CD1400_COR5, opt); cd_outb(iobase, CD1400_COR5, com->cy_align, opt);
/* /*
* XXX we probably alway want to track carrier changes, so that * XXX we probably alway want to track carrier changes, so that
@ -1892,7 +1924,7 @@ comparam(tp, t)
if (cflag & CCTS_OFLOW) if (cflag & CCTS_OFLOW)
opt |= CD1400_MCOR1_CTSzd; opt |= CD1400_MCOR1_CTSzd;
#endif #endif
cd_outb(iobase, CD1400_MCOR1, opt); cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt);
/* /*
* set modem change option register 2 * set modem change option register 2
@ -1903,7 +1935,7 @@ comparam(tp, t)
if (cflag & CCTS_OFLOW) if (cflag & CCTS_OFLOW)
opt |= CD1400_MCOR2_CTSod; opt |= CD1400_MCOR2_CTSod;
#endif #endif
cd_outb(iobase, CD1400_MCOR2, opt); cd_outb(iobase, CD1400_MCOR2, com->cy_align, opt);
/* /*
* XXX should have done this long ago, but there is too much state * XXX should have done this long ago, but there is too much state
@ -1946,11 +1978,11 @@ comparam(tp, t)
#endif #endif
if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
if (!(com->intr_enable & CD1400_SRER_TXRDY)) if (!(com->intr_enable & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable |= CD1400_SRER_TXRDY); com->intr_enable |= CD1400_SRER_TXRDY);
} else { } else {
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable &= ~CD1400_SRER_TXRDY); com->intr_enable &= ~CD1400_SRER_TXRDY);
} }
@ -1982,17 +2014,17 @@ comstart(tp)
#endif #endif
disable_intr(); disable_intr();
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
if (tp->t_state & TS_TTSTOP) { if (tp->t_state & TS_TTSTOP) {
com->state &= ~CS_TTGO; com->state &= ~CS_TTGO;
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable &= ~CD1400_SRER_TXRDY); com->intr_enable &= ~CD1400_SRER_TXRDY);
} else { } else {
com->state |= CS_TTGO; com->state |= CS_TTGO;
if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
&& !(com->intr_enable & CD1400_SRER_TXRDY)) && !(com->intr_enable & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable |= CD1400_SRER_TXRDY); com->intr_enable |= CD1400_SRER_TXRDY);
} }
if (tp->t_state & TS_TBLOCK) { if (tp->t_state & TS_TBLOCK) {
@ -2000,7 +2032,7 @@ comstart(tp)
#if 0 #if 0
outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
} else { } else {
@ -2013,7 +2045,7 @@ comstart(tp)
#if 0 #if 0
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#endif #endif
} }
@ -2048,7 +2080,7 @@ comstart(tp)
com->state |= CS_BUSY; com->state |= CS_BUSY;
if (com->state >= (CS_BUSY | CS_TTGO if (com->state >= (CS_BUSY | CS_TTGO
| CS_ODEVREADY)) | CS_ODEVREADY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} }
@ -2076,7 +2108,7 @@ comstart(tp)
com->state |= CS_BUSY; com->state |= CS_BUSY;
if (com->state >= (CS_BUSY | CS_TTGO if (com->state >= (CS_BUSY | CS_TTGO
| CS_ODEVREADY)) | CS_ODEVREADY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} }
@ -2182,18 +2214,18 @@ commctl(com, bits, how)
switch (how) { switch (how) {
case DMSET: case DMSET:
com->mcr_image = mcr; com->mcr_image = mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
case DMBIS: case DMBIS:
com->mcr_image = mcr = com->mcr_image | mcr; com->mcr_image = mcr = com->mcr_image | mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
case DMBIC: case DMBIC:
com->mcr_image = mcr = com->mcr_image & ~mcr; com->mcr_image = mcr = com->mcr_image & ~mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
} }
enable_intr(); enable_intr();
@ -2331,17 +2363,17 @@ disc_optim(tp, t, com)
com->hotchar = 0; com->hotchar = 0;
#ifndef SOFT_HOTCHAR #ifndef SOFT_HOTCHAR
iobase = com->iobase; iobase = com->iobase;
cd_outb(iobase, CD1400_CAR, com->unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, com->unit & CD1400_CAR_CHAN);
opt = com->cor[2] & ~CD1400_COR3_SCD34; opt = com->cor[2] & ~CD1400_COR3_SCD34;
if (com->hotchar != 0) { if (com->hotchar != 0) {
cd_outb(iobase, CD1400_SCHR3, com->hotchar); cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar);
cd_outb(iobase, CD1400_SCHR4, com->hotchar); cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar);
opt |= CD1400_COR3_SCD34; opt |= CD1400_COR3_SCD34;
} }
if (opt != com->cor[2]) { if (opt != com->cor[2]) {
cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt);
cd1400_channel_cmd(com->iobase, cd1400_channel_cmd(com->iobase,
CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, com->cy_align);
} }
#endif #endif
} }
@ -2405,9 +2437,10 @@ comspeed(speed, prescaler_io)
} }
static void static void
cd1400_channel_cmd(iobase, cmd) cd1400_channel_cmd(iobase, cmd, cy_align)
cy_addr iobase; cy_addr iobase;
int cmd; int cmd;
int cy_align;
{ {
/* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed,
as the card is probed every round? Replaced delaycount with 8k. as the card is probed every round? Replaced delaycount with 8k.
@ -2417,14 +2450,14 @@ cd1400_channel_cmd(iobase, cmd)
u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */
/* wait for processing of previous command to complete */ /* wait for processing of previous command to complete */
while (cd_inb(iobase, CD1400_CCR) && maxwait--) while (cd_inb(iobase, CD1400_CCR, cy_align) && maxwait--)
; ;
if (!maxwait) if (!maxwait)
log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n",
5 * 8 * 1024); 5 * 8 * 1024);
cd_outb(iobase, CD1400_CCR, cmd); cd_outb(iobase, CD1400_CCR, cy_align, cmd);
} }
#ifdef CyDebug #ifdef CyDebug
@ -2448,7 +2481,7 @@ cystatus(unit)
iobase = com->iobase; iobase = com->iobase;
printf("\n"); printf("\n");
printf("cd1400 base address:\\tt%p\n", iobase); printf("cd1400 base address:\\tt%p\n", iobase);
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
printf("saved channel_control:\t\t0x%02x\n", com->channel_control); printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
com->cor[0], com->cor[1], com->cor[2]); com->cor[0], com->cor[1], com->cor[2]);

View File

@ -27,7 +27,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: cy.c,v 1.36 1996/10/04 10:33:08 davidg Exp $ * $Id: cy.c,v 1.37 1996/10/04 14:17:32 davidg Exp $
*/ */
#include "cy.h" #include "cy.h"
@ -141,7 +141,7 @@
/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
#define CD1400_xIVR_CHAN_SHIFT 3 #define CD1400_xIVR_CHAN_SHIFT 3
#define CD1400_xIVR_CHAN 0x0F /* XXX reduce to pack Cyclom-8Ys */ #define CD1400_xIVR_CHAN 0x1F /* XXX reduce to pack Cyclom-8Ys */
#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) #define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE)
@ -153,7 +153,8 @@
#define CONTROL_LOCK_STATE 0x40 #define CONTROL_LOCK_STATE 0x40
#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) #define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS + \
(((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
/* /*
* Input buffer watermarks. * Input buffer watermarks.
@ -262,6 +263,7 @@ struct com_s {
cy_addr cy_iobase; /* base address of this port's cyclom */ cy_addr cy_iobase; /* base address of this port's cyclom */
cy_addr iobase; /* base address of this port's cd1400 */ cy_addr iobase; /* base address of this port's cd1400 */
int cy_align; /* index for register alignment */
struct tty *tp; /* cross reference */ struct tty *tp; /* cross reference */
@ -330,8 +332,10 @@ void siopoll __P((void));
#define siommap nommap #define siommap nommap
#define siostrategy nostrategy #define siostrategy nostrategy
int cyattach_common __P((cy_addr cy_iobase, int cy_align));
static int cy_units __P((cy_addr cy_iobase, int cy_align));
static int sioattach __P((struct isa_device *dev)); static int sioattach __P((struct isa_device *dev));
static void cd1400_channel_cmd __P((cy_addr iobase, int cmd)); static void cd1400_channel_cmd __P((cy_addr iobase, int cmd, int cy_align));
static timeout_t siodtrwakeup; static timeout_t siodtrwakeup;
static void comhardclose __P((struct com_s *com)); static void comhardclose __P((struct com_s *com));
#if 0 #if 0
@ -399,6 +403,7 @@ static u_int cy_timeouts;
#endif #endif
static int cy_nr_cd1400s[NCY]; static int cy_nr_cd1400s[NCY];
static int cy_total_devices;
#undef RxFifoThreshold #undef RxFifoThreshold
static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
static int cy_chip_offset[] = { static int cy_chip_offset[] = {
@ -416,16 +421,9 @@ static int
sioprobe(dev) sioprobe(dev)
struct isa_device *dev; struct isa_device *dev;
{ {
int cyu;
u_char firmware_version;
cy_addr iobase; cy_addr iobase;
int unit;
iobase = (cy_addr)dev->id_maddr; iobase = (cy_addr)dev->id_maddr;
unit = dev->id_unit;
if ((u_int)unit >= NCY)
return (0);
cy_nr_cd1400s[unit] = 0;
/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
cy_inb(iobase, CY16_RESET); /* XXX? */ cy_inb(iobase, CY16_RESET); /* XXX? */
@ -435,22 +433,34 @@ sioprobe(dev)
cy_outb(iobase, CY_CLEAR_INTR, 0); cy_outb(iobase, CY_CLEAR_INTR, 0);
DELAY(500); DELAY(500);
return (cy_units(iobase, 0) == 0 ? 0 : -1);
}
static int
cy_units(cy_iobase, cy_align)
cy_addr cy_iobase;
int cy_align;
{
cy_addr iobase;
int cyu;
for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
int i; int i;
u_char firmware_version;
iobase = (cy_addr) (dev->id_maddr + cy_chip_offset[cyu]); iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
/* wait for chip to become ready for new command */ /* wait for chip to become ready for new command */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
DELAY(50); DELAY(50);
if (!cd_inb(iobase, CD1400_CCR)) if (!cd_inb(iobase, CD1400_CCR, cy_align))
break; break;
} }
/* clear the GFRCR register */ /* clear the GFRCR register */
cd_outb(iobase, CD1400_GFRCR, 0); cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
/* issue a reset command */ /* issue a reset command */
cd_outb(iobase, CD1400_CCR, cd_outb(iobase, CD1400_CCR, cy_align,
CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
/* wait for the CD1400 to initialize itself */ /* wait for the CD1400 to initialize itself */
@ -458,7 +468,7 @@ sioprobe(dev)
DELAY(50); DELAY(50);
/* retrieve firmware version */ /* retrieve firmware version */
firmware_version = cd_inb(iobase, CD1400_GFRCR); firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
if ((firmware_version & 0xf0) == 0x40) if ((firmware_version & 0xf0) == 0x40)
break; break;
} }
@ -470,38 +480,60 @@ sioprobe(dev)
*/ */
if ((firmware_version & 0xf0) != 0x40) if ((firmware_version & 0xf0) != 0x40)
break; break;
++cy_nr_cd1400s[unit];
} }
return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); return (cyu);
} }
static int static int
sioattach(isdp) sioattach(isdp)
struct isa_device *isdp; struct isa_device *isdp;
{ {
int cyu; int adapter;
cy_addr cy_iobase;
dev_t dev;
cy_addr iobase;
int ncyu;
int unit;
unit = isdp->id_unit; adapter = cyattach_common((cy_addr) isdp->id_maddr, 0);
if ((u_int)unit >= NCY) if (adapter < 0)
return (0);
ncyu = cy_nr_cd1400s[unit];
if (ncyu == 0)
return (0); return (0);
/*
* XXX
* This kludge is to allow ISA/PCI device specifications in the
* kernel config file to be in any order.
*/
if (isdp->id_unit != adapter) {
printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter);
isdp->id_unit = adapter; /* XXX */
}
isdp->id_ri_flags |= RI_FAST; isdp->id_ri_flags |= RI_FAST;
return (1);
}
cy_iobase = (cy_addr)isdp->id_maddr; int
unit *= CY_MAX_PORTS; cyattach_common(cy_iobase, cy_align)
cy_addr cy_iobase;
int cy_align;
{
int cyu, ncyu, unit, adapter;
dev_t dev;
cy_addr iobase;
adapter = cy_total_devices;
if ((u_int)adapter >= NCY) {
printf("cy%d: can't attach adapter: insufficient cy devices configured\n",
adapter);
return (-1);
}
ncyu = cy_units(cy_iobase, cy_align);
if (ncyu == 0)
return (-1);
cy_nr_cd1400s[adapter] = ncyu;
cy_total_devices++;
unit = adapter * CY_MAX_PORTS;
for (cyu = 0; cyu < ncyu; ++cyu) { for (cyu = 0; cyu < ncyu; ++cyu) {
int cdu; int cdu;
iobase = (cy_addr) (isdp->id_maddr + cy_chip_offset[cyu]); iobase = (cy_addr) (cy_iobase + (cy_chip_offset[cyu] << cy_align));
/* Set up a receive timeout period of than 1+ ms. */ /* Set up a receive timeout period of than 1+ ms. */
cd_outb(iobase, CD1400_PPR, cd_outb(iobase, CD1400_PPR, cy_align,
howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000));
for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
@ -522,6 +554,7 @@ sioattach(isdp)
com->cy_iobase = cy_iobase; com->cy_iobase = cy_iobase;
com->iobase = iobase; com->iobase = iobase;
com->cy_align = cy_align;
/* /*
* We don't use all the flags from <sys/ttydefaults.h> since they * We don't use all the flags from <sys/ttydefaults.h> since they
@ -574,9 +607,9 @@ sioattach(isdp)
} }
/* ensure an edge for the next interrupt */ /* ensure an edge for the next interrupt */
cy_outb(cy_iobase, CY_CLEAR_INTR, 0); cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
return (1); return (adapter);
} }
static int static int
@ -664,8 +697,8 @@ open_top:
iobase = com->iobase; iobase = com->iobase;
/* reset this channel */ /* reset this channel */
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align);
/* /*
* Resetting disables the transmitter and receiver as well as * Resetting disables the transmitter and receiver as well as
@ -677,7 +710,7 @@ open_top:
com->channel_control = 0; com->channel_control = 0;
/* Encode per-board unit in LIVR for access in intr routines. */ /* Encode per-board unit in LIVR for access in intr routines. */
cd_outb(iobase, CD1400_LIVR, cd_outb(iobase, CD1400_LIVR, com->cy_align,
(unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
/* /*
@ -732,8 +765,8 @@ open_top:
(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
disable_intr(); disable_intr();
com->prev_modem_status = com->last_modem_status com->prev_modem_status = com->last_modem_status
= cd_inb(iobase, CD1400_MSVR2); = cd_inb(iobase, CD1400_MSVR2, com->cy_align);
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
= CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
enable_intr(); enable_intr();
@ -827,7 +860,7 @@ comhardclose(com)
com->poll_output = FALSE; com->poll_output = FALSE;
#endif #endif
com->do_timestamp = 0; com->do_timestamp = 0;
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
#if 0 #if 0
outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
#endif #endif
@ -837,7 +870,7 @@ comhardclose(com)
outb(iobase + com_ier, 0); outb(iobase + com_ier, 0);
#else #else
disable_intr(); disable_intr();
cd_outb(iobase, CD1400_SRER, com->intr_enable = 0); cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable = 0);
enable_intr(); enable_intr();
#endif #endif
tp = com->tp; tp = com->tp;
@ -859,7 +892,7 @@ comhardclose(com)
com->channel_control = CD1400_CCR_CMDCHANCTL com->channel_control = CD1400_CCR_CMDCHANCTL
| CD1400_CCR_XMTEN | CD1400_CCR_XMTEN
| CD1400_CCR_RCVDIS; | CD1400_CCR_RCVDIS;
cd1400_channel_cmd(iobase, com->channel_control); cd1400_channel_cmd(iobase, com->channel_control, com->cy_align);
if (com->dtr_wait != 0) { if (com->dtr_wait != 0) {
timeout(siodtrwakeup, com, com->dtr_wait); timeout(siodtrwakeup, com, com->dtr_wait);
@ -948,20 +981,19 @@ void
siointr(unit) siointr(unit)
int unit; int unit;
{ {
int baseu; cy_addr cy_iobase, iobase;
cy_addr cy_iobase; int baseu, cyu, cy_align;
int cyu; u_char status;
cy_addr iobase;
u_char status;
baseu = unit * CY_MAX_PORTS; baseu = unit * CY_MAX_PORTS;
cy_iobase = com_addr(baseu)->cy_iobase; cy_iobase = com_addr(baseu)->cy_iobase;
cy_align = com_addr(baseu)->cy_align;
/* check each CD1400 in turn */ /* check each CD1400 in turn */
for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
iobase = (cy_addr) (cy_iobase + cy_chip_offset[cyu]); iobase = (cy_addr) (cy_iobase + (cy_chip_offset[cyu] << cy_align));
/* poll to see if it has any work */ /* poll to see if it has any work */
status = cd_inb(iobase, CD1400_SVRR); status = cd_inb(iobase, CD1400_SVRR, cy_align);
if (status == 0) if (status == 0)
continue; continue;
#ifdef CyDebug #ifdef CyDebug
@ -981,13 +1013,13 @@ siointr(unit)
#endif #endif
#ifdef PollMode #ifdef PollMode
save_rir = cd_inb(iobase, CD1400_RIR); save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter rx service */ /* enter rx service */
cd_outb(iobase, CD1400_CAR, save_rir); cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
serv_type = cd_inb(iobase, CD1400_RIVR); serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
com = com_addr(baseu com = com_addr(baseu
+ ((serv_type >> CD1400_xIVR_CHAN_SHIFT) + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
& CD1400_xIVR_CHAN)); & CD1400_xIVR_CHAN));
@ -1002,9 +1034,9 @@ siointr(unit)
if (serv_type & CD1400_RIVR_EXCEPTION) { if (serv_type & CD1400_RIVR_EXCEPTION) {
++com->recv_exception; ++com->recv_exception;
line_status = cd_inb(iobase, CD1400_RDSR); line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
/* break/unnattached error bits or real input? */ /* break/unnattached error bits or real input? */
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifndef SOFT_HOTCHAR #ifndef SOFT_HOTCHAR
if (line_status & CD1400_RDSR_SPECIAL if (line_status & CD1400_RDSR_SPECIAL
&& com->hotchar != 0) && com->hotchar != 0)
@ -1053,7 +1085,7 @@ siointr(unit)
outb(com->modem_ctl_port, outb(com->modem_ctl_port,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
if (line_status & LSR_OE) if (line_status & LSR_OE)
@ -1063,7 +1095,7 @@ siointr(unit)
} else { } else {
int ifree; int ifree;
count = cd_inb(iobase, CD1400_RDCR); count = cd_inb(iobase, CD1400_RDCR, cy_align);
com->bytes_in += count; com->bytes_in += count;
ioptr = com->iptr; ioptr = com->iptr;
ifree = com->ibufend - ioptr; ifree = com->ibufend - ioptr;
@ -1075,7 +1107,7 @@ siointr(unit)
microtime(&com->timestamp); microtime(&com->timestamp);
do { do {
recv_data = cd_inb(iobase, recv_data = cd_inb(iobase,
CD1400_RDSR); CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data && recv_data
@ -1090,7 +1122,7 @@ siointr(unit)
com->delta_error_counts com->delta_error_counts
[CE_INTERRUPT_BUF_OVERFLOW] += count; [CE_INTERRUPT_BUF_OVERFLOW] += count;
do { do {
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data == com->hotchar) && recv_data == com->hotchar)
@ -1107,12 +1139,12 @@ siointr(unit)
outb(com->modem_ctl_port, outb(com->modem_ctl_port,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
com_events += count; com_events += count;
do { do {
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data == com->hotchar) && recv_data == com->hotchar)
@ -1129,12 +1161,12 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_RIR, cd_outb(iobase, CD1400_RIR, cy_align,
save_rir save_rir
& ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
if (status & CD1400_SVRR_MDMCH) { if (status & CD1400_SVRR_MDMCH) {
@ -1148,11 +1180,11 @@ cont:
#endif #endif
#ifdef PollMode #ifdef PollMode
save_mir = cd_inb(iobase, CD1400_MIR); save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter modem service */ /* enter modem service */
cd_outb(iobase, CD1400_CAR, save_mir); cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
+ (save_mir & CD1400_MIR_CHAN)); + (save_mir & CD1400_MIR_CHAN));
@ -1165,7 +1197,7 @@ cont:
& CD1400_xIVR_CHAN)); & CD1400_xIVR_CHAN));
#endif #endif
++com->mdm; ++com->mdm;
modem_status = cd_inb(iobase, CD1400_MSVR2); modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
if (modem_status != com->last_modem_status) { if (modem_status != com->last_modem_status) {
if (com->do_dcd_timestamp if (com->do_dcd_timestamp
&& !(com->last_modem_status & MSR_DCD) && !(com->last_modem_status & MSR_DCD)
@ -1194,13 +1226,13 @@ cont:
| CS_ODEVREADY) | CS_ODEVREADY)
&& !(com->intr_enable && !(com->intr_enable
& CD1400_SRER_TXRDY)) & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} else { } else {
com->state &= ~CS_ODEVREADY; com->state &= ~CS_ODEVREADY;
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
&= ~CD1400_SRER_TXRDY); &= ~CD1400_SRER_TXRDY);
} }
@ -1210,12 +1242,12 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_MIR, cd_outb(iobase, CD1400_MIR, cy_align,
save_mir save_mir
& ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
if (status & CD1400_SVRR_TXRDY) { if (status & CD1400_SVRR_TXRDY) {
@ -1228,11 +1260,11 @@ cont:
#endif #endif
#ifdef PollMode #ifdef PollMode
save_tir = cd_inb(iobase, CD1400_TIR); save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter tx service */ /* enter tx service */
cd_outb(iobase, CD1400_CAR, save_tir); cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
com = com_addr(baseu com = com_addr(baseu
+ cyu * CD1400_NO_OF_CHANNELS + cyu * CD1400_NO_OF_CHANNELS
+ (save_tir & CD1400_TIR_CHAN)); + (save_tir & CD1400_TIR_CHAN));
@ -1255,7 +1287,7 @@ cont:
ocount = CD1400_TX_FIFO_SIZE; ocount = CD1400_TX_FIFO_SIZE;
com->bytes_out += ocount; com->bytes_out += ocount;
do do
cd_outb(iobase, CD1400_TDR, *ioptr++); cd_outb(iobase, CD1400_TDR, cy_align, *ioptr++);
while (--ocount != 0); while (--ocount != 0);
com->obufq.l_head = ioptr; com->obufq.l_head = ioptr;
if (ioptr >= com->obufq.l_tail) { if (ioptr >= com->obufq.l_tail) {
@ -1271,7 +1303,7 @@ cont:
} else { } else {
/* output just completed */ /* output just completed */
com->state &= ~CS_BUSY; com->state &= ~CS_BUSY;
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
&= ~CD1400_SRER_TXRDY); &= ~CD1400_SRER_TXRDY);
} }
@ -1285,18 +1317,18 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_TIR, cd_outb(iobase, CD1400_TIR, cy_align,
save_tir save_tir
& ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
} }
/* ensure an edge for the next interrupt */ /* ensure an edge for the next interrupt */
cy_outb(cy_iobase, CY_CLEAR_INTR, 0); cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
schedsofttty(); schedsofttty();
} }
@ -1406,7 +1438,7 @@ sioioctl(dev, cmd, data, flag, p)
splx(s); splx(s);
return (error); return (error);
} }
cd_outb(iobase, CD1400_CAR, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN);
switch (cmd) { switch (cmd) {
#if 0 #if 0
case TIOCSBRK: case TIOCSBRK:
@ -1544,9 +1576,9 @@ repeat:
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#else #else
iobase = com->iobase, iobase = com->iobase,
cd_outb(iobase, CD1400_CAR, cd_outb(iobase, CD1400_CAR, com->cy_align,
unit & CD1400_CAR_CHAN), unit & CD1400_CAR_CHAN),
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#endif #endif
enable_intr(); enable_intr();
@ -1669,19 +1701,19 @@ comparam(tp, t)
com = com_addr(unit); com = com_addr(unit);
iobase = com->iobase; iobase = com->iobase;
s = spltty(); s = spltty();
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
if (odivisor == 0) if (odivisor == 0)
(void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
else else
(void)commctl(com, TIOCM_DTR, DMBIS); (void)commctl(com, TIOCM_DTR, DMBIS);
if (idivisor != 0) { if (idivisor != 0) {
cd_outb(iobase, CD1400_RBPR, idivisor); cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor);
cd_outb(iobase, CD1400_RCOR, iprescaler); cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler);
} }
if (odivisor != 0) { if (odivisor != 0) {
cd_outb(iobase, CD1400_TBPR, odivisor); cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor);
cd_outb(iobase, CD1400_TCOR, oprescaler); cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler);
} }
/* /*
@ -1694,20 +1726,20 @@ comparam(tp, t)
| (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
if (opt != com->channel_control) { if (opt != com->channel_control) {
com->channel_control = opt; com->channel_control = opt;
cd1400_channel_cmd(iobase, opt); cd1400_channel_cmd(iobase, opt, com->cy_align);
} }
#ifdef Smarts #ifdef Smarts
/* set special chars */ /* set special chars */
/* XXX if one is _POSIX_VDISABLE, can't use some others */ /* XXX if one is _POSIX_VDISABLE, can't use some others */
if (t->c_cc[VSTOP] != _POSIX_VDISABLE) if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR1, t->c_cc[VSTOP]); cd_outb(iobase, CD1400_SCHR1, com->cy_align, t->c_cc[VSTOP]);
if (t->c_cc[VSTART] != _POSIX_VDISABLE) if (t->c_cc[VSTART] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR2, t->c_cc[VSTART]); cd_outb(iobase, CD1400_SCHR2, com->cy_align, t->c_cc[VSTART]);
if (t->c_cc[VINTR] != _POSIX_VDISABLE) if (t->c_cc[VINTR] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR3, t->c_cc[VINTR]); cd_outb(iobase, CD1400_SCHR3, com->cy_align, t->c_cc[VINTR]);
if (t->c_cc[VSUSP] != _POSIX_VDISABLE) if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]);
#endif #endif
/* /*
@ -1754,14 +1786,14 @@ comparam(tp, t)
cor_change = 0; cor_change = 0;
if (opt != com->cor[0]) { if (opt != com->cor[0]) {
cor_change |= CD1400_CCR_COR1; cor_change |= CD1400_CCR_COR1;
cd_outb(iobase, CD1400_COR1, com->cor[0] = opt); cd_outb(iobase, CD1400_COR1, com->cy_align, com->cor[0] = opt);
} }
/* /*
* Set receive time-out period, normally to max(one char time, 5 ms). * Set receive time-out period, normally to max(one char time, 5 ms).
*/ */
if (t->c_ispeed == 0) if (t->c_ispeed == 0)
itimeout = cd_inb(iobase, CD1400_RTPR); itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align);
else { else {
itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
@ -1777,7 +1809,7 @@ comparam(tp, t)
itimeout = t->c_cc[VTIME] * 10; itimeout = t->c_cc[VTIME] * 10;
if (itimeout > 255) if (itimeout > 255)
itimeout = 255; itimeout = 255;
cd_outb(iobase, CD1400_RTPR, itimeout); cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout);
/* /*
* set channel option register 2 - * set channel option register 2 -
@ -1796,7 +1828,7 @@ comparam(tp, t)
#endif #endif
if (opt != com->cor[1]) { if (opt != com->cor[1]) {
cor_change |= CD1400_CCR_COR2; cor_change |= CD1400_CCR_COR2;
cd_outb(iobase, CD1400_COR2, com->cor[1] = opt); cd_outb(iobase, CD1400_COR2, com->cy_align, com->cor[1] = opt);
} }
/* /*
@ -1814,12 +1846,12 @@ comparam(tp, t)
#endif #endif
if (opt != com->cor[2]) { if (opt != com->cor[2]) {
cor_change |= CD1400_CCR_COR3; cor_change |= CD1400_CCR_COR3;
cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt);
} }
/* notify the CD1400 if COR1-3 have changed */ /* notify the CD1400 if COR1-3 have changed */
if (cor_change) if (cor_change)
cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change); cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change, com->cy_align);
/* /*
* set channel option register 4 - * set channel option register 4 -
@ -1858,7 +1890,7 @@ comparam(tp, t)
#else #else
opt |= CD1400_COR4_PFO_EXCEPTION; opt |= CD1400_COR4_PFO_EXCEPTION;
#endif #endif
cd_outb(iobase, CD1400_COR4, opt); cd_outb(iobase, CD1400_COR4, com->cy_align, opt);
/* /*
* set channel option register 5 - * set channel option register 5 -
@ -1875,7 +1907,7 @@ comparam(tp, t)
if (t->c_oflag & OCRNL) if (t->c_oflag & OCRNL)
opt |= CD1400_COR5_OCRNL; opt |= CD1400_COR5_OCRNL;
#endif #endif
cd_outb(iobase, CD1400_COR5, opt); cd_outb(iobase, CD1400_COR5, com->cy_align, opt);
/* /*
* XXX we probably alway want to track carrier changes, so that * XXX we probably alway want to track carrier changes, so that
@ -1892,7 +1924,7 @@ comparam(tp, t)
if (cflag & CCTS_OFLOW) if (cflag & CCTS_OFLOW)
opt |= CD1400_MCOR1_CTSzd; opt |= CD1400_MCOR1_CTSzd;
#endif #endif
cd_outb(iobase, CD1400_MCOR1, opt); cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt);
/* /*
* set modem change option register 2 * set modem change option register 2
@ -1903,7 +1935,7 @@ comparam(tp, t)
if (cflag & CCTS_OFLOW) if (cflag & CCTS_OFLOW)
opt |= CD1400_MCOR2_CTSod; opt |= CD1400_MCOR2_CTSod;
#endif #endif
cd_outb(iobase, CD1400_MCOR2, opt); cd_outb(iobase, CD1400_MCOR2, com->cy_align, opt);
/* /*
* XXX should have done this long ago, but there is too much state * XXX should have done this long ago, but there is too much state
@ -1946,11 +1978,11 @@ comparam(tp, t)
#endif #endif
if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
if (!(com->intr_enable & CD1400_SRER_TXRDY)) if (!(com->intr_enable & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable |= CD1400_SRER_TXRDY); com->intr_enable |= CD1400_SRER_TXRDY);
} else { } else {
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable &= ~CD1400_SRER_TXRDY); com->intr_enable &= ~CD1400_SRER_TXRDY);
} }
@ -1982,17 +2014,17 @@ comstart(tp)
#endif #endif
disable_intr(); disable_intr();
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
if (tp->t_state & TS_TTSTOP) { if (tp->t_state & TS_TTSTOP) {
com->state &= ~CS_TTGO; com->state &= ~CS_TTGO;
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable &= ~CD1400_SRER_TXRDY); com->intr_enable &= ~CD1400_SRER_TXRDY);
} else { } else {
com->state |= CS_TTGO; com->state |= CS_TTGO;
if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
&& !(com->intr_enable & CD1400_SRER_TXRDY)) && !(com->intr_enable & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable |= CD1400_SRER_TXRDY); com->intr_enable |= CD1400_SRER_TXRDY);
} }
if (tp->t_state & TS_TBLOCK) { if (tp->t_state & TS_TBLOCK) {
@ -2000,7 +2032,7 @@ comstart(tp)
#if 0 #if 0
outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
} else { } else {
@ -2013,7 +2045,7 @@ comstart(tp)
#if 0 #if 0
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#endif #endif
} }
@ -2048,7 +2080,7 @@ comstart(tp)
com->state |= CS_BUSY; com->state |= CS_BUSY;
if (com->state >= (CS_BUSY | CS_TTGO if (com->state >= (CS_BUSY | CS_TTGO
| CS_ODEVREADY)) | CS_ODEVREADY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} }
@ -2076,7 +2108,7 @@ comstart(tp)
com->state |= CS_BUSY; com->state |= CS_BUSY;
if (com->state >= (CS_BUSY | CS_TTGO if (com->state >= (CS_BUSY | CS_TTGO
| CS_ODEVREADY)) | CS_ODEVREADY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} }
@ -2182,18 +2214,18 @@ commctl(com, bits, how)
switch (how) { switch (how) {
case DMSET: case DMSET:
com->mcr_image = mcr; com->mcr_image = mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
case DMBIS: case DMBIS:
com->mcr_image = mcr = com->mcr_image | mcr; com->mcr_image = mcr = com->mcr_image | mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
case DMBIC: case DMBIC:
com->mcr_image = mcr = com->mcr_image & ~mcr; com->mcr_image = mcr = com->mcr_image & ~mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
} }
enable_intr(); enable_intr();
@ -2331,17 +2363,17 @@ disc_optim(tp, t, com)
com->hotchar = 0; com->hotchar = 0;
#ifndef SOFT_HOTCHAR #ifndef SOFT_HOTCHAR
iobase = com->iobase; iobase = com->iobase;
cd_outb(iobase, CD1400_CAR, com->unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, com->unit & CD1400_CAR_CHAN);
opt = com->cor[2] & ~CD1400_COR3_SCD34; opt = com->cor[2] & ~CD1400_COR3_SCD34;
if (com->hotchar != 0) { if (com->hotchar != 0) {
cd_outb(iobase, CD1400_SCHR3, com->hotchar); cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar);
cd_outb(iobase, CD1400_SCHR4, com->hotchar); cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar);
opt |= CD1400_COR3_SCD34; opt |= CD1400_COR3_SCD34;
} }
if (opt != com->cor[2]) { if (opt != com->cor[2]) {
cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt);
cd1400_channel_cmd(com->iobase, cd1400_channel_cmd(com->iobase,
CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, com->cy_align);
} }
#endif #endif
} }
@ -2405,9 +2437,10 @@ comspeed(speed, prescaler_io)
} }
static void static void
cd1400_channel_cmd(iobase, cmd) cd1400_channel_cmd(iobase, cmd, cy_align)
cy_addr iobase; cy_addr iobase;
int cmd; int cmd;
int cy_align;
{ {
/* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed,
as the card is probed every round? Replaced delaycount with 8k. as the card is probed every round? Replaced delaycount with 8k.
@ -2417,14 +2450,14 @@ cd1400_channel_cmd(iobase, cmd)
u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */
/* wait for processing of previous command to complete */ /* wait for processing of previous command to complete */
while (cd_inb(iobase, CD1400_CCR) && maxwait--) while (cd_inb(iobase, CD1400_CCR, cy_align) && maxwait--)
; ;
if (!maxwait) if (!maxwait)
log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n",
5 * 8 * 1024); 5 * 8 * 1024);
cd_outb(iobase, CD1400_CCR, cmd); cd_outb(iobase, CD1400_CCR, cy_align, cmd);
} }
#ifdef CyDebug #ifdef CyDebug
@ -2448,7 +2481,7 @@ cystatus(unit)
iobase = com->iobase; iobase = com->iobase;
printf("\n"); printf("\n");
printf("cd1400 base address:\\tt%p\n", iobase); printf("cd1400 base address:\\tt%p\n", iobase);
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
printf("saved channel_control:\t\t0x%02x\n", com->channel_control); printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
com->cor[0], com->cor[1], com->cor[2]); com->cor[0], com->cor[1], com->cor[2]);

132
sys/dev/cy/cy_pci.c Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 1996, David Greenman
* All rights reserved.
*
* 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
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
/*
* Cyclades Y PCI serial interface driver
*/
#include <pci.h>
#if NPCI > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <pci/pcivar.h>
#include <pci/cy_pcireg.h>
static char *cy_probe __P((pcici_t, pcidi_t));
static void cy_attach __P((pcici_t, int));
extern int cyattach_common(void *, int); /* Not exactly correct */
extern void cyintr(int);
static u_long cy_count;
static struct pci_device cy_device = {
"cy",
cy_probe,
cy_attach,
&cy_count,
NULL
};
DATA_SET(pcidevice_set, cy_device);
static char *
cy_probe(config_id, device_id)
pcici_t config_id;
pcidi_t device_id;
{
if ((device_id & 0xffff) == CY_VENDORID_CYCLADES &&
((device_id >> 16) == CY_DEVICEID_CYCLOM_Y_1 ||
(device_id >> 16) == CY_DEVICEID_CYCLOM_Y_2))
return ("Cyclades Cyclom-Y Serial Adapter");
return NULL;
}
static void
cy_attach(config_id, unit)
pcici_t config_id;
int unit;
{
vm_offset_t paddr;
void *vaddr;
u_int32_t ioport;
int adapter;
ioport = (u_int32_t) pci_conf_read(config_id, CY_PCI_BASE_ADDR1) & ~0x3;
paddr = pci_conf_read(config_id, CY_PCI_BASE_ADDR2) & ~0xf;
#if 0
if (!pci_map_mem(config_id, CY_PCI_BASE_ADDR2, &vaddr, &paddr)) {
printf("cy%d: couldn't map shared memory\n", unit);
return;
};
#endif
vaddr = pmap_mapdev(paddr, 0x4000);
adapter = cyattach_common(vaddr, 1);
if (adapter < 0) {
/*
* No ports found. Release resources and punt.
*/
printf("cy%d: no ports found!", unit);
goto fail;
}
/*
* Allocate our interrupt.
* XXX Using the ISA interrupt handler directly is a bit of a violation
* since it doesn't actually take the same argument. For PCI, the
* argument is a void * token, but for ISA it is a unit. Since
* there is no overlap in PCI/ISA unit numbers for this driver, and
* since the ISA driver must handle the interrupt anyway, we use
* the unit number as the token even for PCI.
*/
if (!pci_map_int(config_id, (pci_inthand_t *)cyintr, (void *)adapter, &tty_imask)) {
printf("cy%d: couldn't map interrupt\n", unit);
goto fail;
}
/*
* Enable the "local" interrupt input to generate a
* PCI interrupt.
*/
outw(ioport + CY_PLX_ICS, inw(CY_PLX_ICS) |
CY_PLX_ICS_IENABLE | CY_PLX_ICS_LOCAL_IENABLE);
return;
fail:
/* XXX should release any allocated virtual memory */
return;
}
#endif /* NPCI > 0 */

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: cyreg.h,v 1.1 1995/07/05 12:15:51 bde Exp $ * $Id: cyreg.h,v 1.2 1996/10/04 10:33:13 davidg Exp $
*/ */
/* /*
@ -36,22 +36,21 @@
#define CY8_SVCACKR 0x100 #define CY8_SVCACKR 0x100
#define CY8_SVCACKT 0x200 #define CY8_SVCACKT 0x200
#define CY8_SVCACKM 0x300 #define CY8_SVCACKM 0x300
#define CY_CD1400_MEMSIZE 0x400 #define CY16_RESET 0x0a00
#define CY16_RESET 0x1400 #define CY_CLEAR_INTR 0x0c00 /* intr ack address */
#define CY_CLEAR_INTR 0x1800 /* intr ack address */
#define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ #define CY_MAX_CD1400s 8 /* for Cyclom-32Y */
#define CY_CLOCK 25000000 /* baud rate clock */ #define CY_CLOCK 25000000 /* baud rate clock */
#ifdef CyDebug #ifdef CyDebug
#define cd_inb(iobase, reg) (++cd_inbs, *((iobase) + 2 * (reg))) #define cd_inb(iobase, reg, cy_align) (++cd_inbs, *((iobase) + ((reg)*2 << (cy_align))))
#define cy_inb(iobase, reg) (++cy_inbs, *((iobase) + (reg))) #define cy_inb(iobase, reg) (++cy_inbs, *((iobase) + (reg)))
#define cd_outb(iobase, reg, val) (++cd_outbs, (void)(*((iobase) + 2 * (reg)) = (val))) #define cd_outb(iobase, reg, cy_align, val) (++cd_outbs, (void)(*((iobase) + ((reg)*2 << (cy_align))) = (val)))
#define cy_outb(iobase, reg, val) (++cy_outbs, (void)(*((iobase) + (reg)) = (val))) #define cy_outb(iobase, reg, val) (++cy_outbs, (void)(*((iobase) + (reg)) = (val)))
#else #else
#define cd_inb(iobase, reg) (*((iobase) + 2 * (reg))) #define cd_inb(iobase, reg, cy_align) (*((iobase) + ((reg)*2 << (cy_align))))
#define cy_inb(iobase, reg) (*((iobase) + (reg))) #define cy_inb(iobase, reg) (*((iobase) + (reg)))
#define cd_outb(iobase, reg, val) ((void)(*((iobase) + 2 * (reg)) = (val))) #define cd_outb(iobase, reg, cy_align, val) ((void)(*((iobase) + ((reg)*2 << (cy_align))) = (val)))
#define cy_outb(iobase, reg, val) ((void)(*((iobase) + (reg)) = (val))) #define cy_outb(iobase, reg, val) ((void)(*((iobase) + (reg)) = (val)))
#endif #endif

View File

@ -27,7 +27,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: cy.c,v 1.36 1996/10/04 10:33:08 davidg Exp $ * $Id: cy.c,v 1.37 1996/10/04 14:17:32 davidg Exp $
*/ */
#include "cy.h" #include "cy.h"
@ -141,7 +141,7 @@
/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
#define CD1400_xIVR_CHAN_SHIFT 3 #define CD1400_xIVR_CHAN_SHIFT 3
#define CD1400_xIVR_CHAN 0x0F /* XXX reduce to pack Cyclom-8Ys */ #define CD1400_xIVR_CHAN 0x1F /* XXX reduce to pack Cyclom-8Ys */
#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) #define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE)
@ -153,7 +153,8 @@
#define CONTROL_LOCK_STATE 0x40 #define CONTROL_LOCK_STATE 0x40
#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) #define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS + \
(((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
/* /*
* Input buffer watermarks. * Input buffer watermarks.
@ -262,6 +263,7 @@ struct com_s {
cy_addr cy_iobase; /* base address of this port's cyclom */ cy_addr cy_iobase; /* base address of this port's cyclom */
cy_addr iobase; /* base address of this port's cd1400 */ cy_addr iobase; /* base address of this port's cd1400 */
int cy_align; /* index for register alignment */
struct tty *tp; /* cross reference */ struct tty *tp; /* cross reference */
@ -330,8 +332,10 @@ void siopoll __P((void));
#define siommap nommap #define siommap nommap
#define siostrategy nostrategy #define siostrategy nostrategy
int cyattach_common __P((cy_addr cy_iobase, int cy_align));
static int cy_units __P((cy_addr cy_iobase, int cy_align));
static int sioattach __P((struct isa_device *dev)); static int sioattach __P((struct isa_device *dev));
static void cd1400_channel_cmd __P((cy_addr iobase, int cmd)); static void cd1400_channel_cmd __P((cy_addr iobase, int cmd, int cy_align));
static timeout_t siodtrwakeup; static timeout_t siodtrwakeup;
static void comhardclose __P((struct com_s *com)); static void comhardclose __P((struct com_s *com));
#if 0 #if 0
@ -399,6 +403,7 @@ static u_int cy_timeouts;
#endif #endif
static int cy_nr_cd1400s[NCY]; static int cy_nr_cd1400s[NCY];
static int cy_total_devices;
#undef RxFifoThreshold #undef RxFifoThreshold
static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
static int cy_chip_offset[] = { static int cy_chip_offset[] = {
@ -416,16 +421,9 @@ static int
sioprobe(dev) sioprobe(dev)
struct isa_device *dev; struct isa_device *dev;
{ {
int cyu;
u_char firmware_version;
cy_addr iobase; cy_addr iobase;
int unit;
iobase = (cy_addr)dev->id_maddr; iobase = (cy_addr)dev->id_maddr;
unit = dev->id_unit;
if ((u_int)unit >= NCY)
return (0);
cy_nr_cd1400s[unit] = 0;
/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
cy_inb(iobase, CY16_RESET); /* XXX? */ cy_inb(iobase, CY16_RESET); /* XXX? */
@ -435,22 +433,34 @@ sioprobe(dev)
cy_outb(iobase, CY_CLEAR_INTR, 0); cy_outb(iobase, CY_CLEAR_INTR, 0);
DELAY(500); DELAY(500);
return (cy_units(iobase, 0) == 0 ? 0 : -1);
}
static int
cy_units(cy_iobase, cy_align)
cy_addr cy_iobase;
int cy_align;
{
cy_addr iobase;
int cyu;
for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
int i; int i;
u_char firmware_version;
iobase = (cy_addr) (dev->id_maddr + cy_chip_offset[cyu]); iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
/* wait for chip to become ready for new command */ /* wait for chip to become ready for new command */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
DELAY(50); DELAY(50);
if (!cd_inb(iobase, CD1400_CCR)) if (!cd_inb(iobase, CD1400_CCR, cy_align))
break; break;
} }
/* clear the GFRCR register */ /* clear the GFRCR register */
cd_outb(iobase, CD1400_GFRCR, 0); cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
/* issue a reset command */ /* issue a reset command */
cd_outb(iobase, CD1400_CCR, cd_outb(iobase, CD1400_CCR, cy_align,
CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
/* wait for the CD1400 to initialize itself */ /* wait for the CD1400 to initialize itself */
@ -458,7 +468,7 @@ sioprobe(dev)
DELAY(50); DELAY(50);
/* retrieve firmware version */ /* retrieve firmware version */
firmware_version = cd_inb(iobase, CD1400_GFRCR); firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
if ((firmware_version & 0xf0) == 0x40) if ((firmware_version & 0xf0) == 0x40)
break; break;
} }
@ -470,38 +480,60 @@ sioprobe(dev)
*/ */
if ((firmware_version & 0xf0) != 0x40) if ((firmware_version & 0xf0) != 0x40)
break; break;
++cy_nr_cd1400s[unit];
} }
return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); return (cyu);
} }
static int static int
sioattach(isdp) sioattach(isdp)
struct isa_device *isdp; struct isa_device *isdp;
{ {
int cyu; int adapter;
cy_addr cy_iobase;
dev_t dev;
cy_addr iobase;
int ncyu;
int unit;
unit = isdp->id_unit; adapter = cyattach_common((cy_addr) isdp->id_maddr, 0);
if ((u_int)unit >= NCY) if (adapter < 0)
return (0);
ncyu = cy_nr_cd1400s[unit];
if (ncyu == 0)
return (0); return (0);
/*
* XXX
* This kludge is to allow ISA/PCI device specifications in the
* kernel config file to be in any order.
*/
if (isdp->id_unit != adapter) {
printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter);
isdp->id_unit = adapter; /* XXX */
}
isdp->id_ri_flags |= RI_FAST; isdp->id_ri_flags |= RI_FAST;
return (1);
}
cy_iobase = (cy_addr)isdp->id_maddr; int
unit *= CY_MAX_PORTS; cyattach_common(cy_iobase, cy_align)
cy_addr cy_iobase;
int cy_align;
{
int cyu, ncyu, unit, adapter;
dev_t dev;
cy_addr iobase;
adapter = cy_total_devices;
if ((u_int)adapter >= NCY) {
printf("cy%d: can't attach adapter: insufficient cy devices configured\n",
adapter);
return (-1);
}
ncyu = cy_units(cy_iobase, cy_align);
if (ncyu == 0)
return (-1);
cy_nr_cd1400s[adapter] = ncyu;
cy_total_devices++;
unit = adapter * CY_MAX_PORTS;
for (cyu = 0; cyu < ncyu; ++cyu) { for (cyu = 0; cyu < ncyu; ++cyu) {
int cdu; int cdu;
iobase = (cy_addr) (isdp->id_maddr + cy_chip_offset[cyu]); iobase = (cy_addr) (cy_iobase + (cy_chip_offset[cyu] << cy_align));
/* Set up a receive timeout period of than 1+ ms. */ /* Set up a receive timeout period of than 1+ ms. */
cd_outb(iobase, CD1400_PPR, cd_outb(iobase, CD1400_PPR, cy_align,
howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000));
for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
@ -522,6 +554,7 @@ sioattach(isdp)
com->cy_iobase = cy_iobase; com->cy_iobase = cy_iobase;
com->iobase = iobase; com->iobase = iobase;
com->cy_align = cy_align;
/* /*
* We don't use all the flags from <sys/ttydefaults.h> since they * We don't use all the flags from <sys/ttydefaults.h> since they
@ -574,9 +607,9 @@ sioattach(isdp)
} }
/* ensure an edge for the next interrupt */ /* ensure an edge for the next interrupt */
cy_outb(cy_iobase, CY_CLEAR_INTR, 0); cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
return (1); return (adapter);
} }
static int static int
@ -664,8 +697,8 @@ open_top:
iobase = com->iobase; iobase = com->iobase;
/* reset this channel */ /* reset this channel */
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align);
/* /*
* Resetting disables the transmitter and receiver as well as * Resetting disables the transmitter and receiver as well as
@ -677,7 +710,7 @@ open_top:
com->channel_control = 0; com->channel_control = 0;
/* Encode per-board unit in LIVR for access in intr routines. */ /* Encode per-board unit in LIVR for access in intr routines. */
cd_outb(iobase, CD1400_LIVR, cd_outb(iobase, CD1400_LIVR, com->cy_align,
(unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
/* /*
@ -732,8 +765,8 @@ open_top:
(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
disable_intr(); disable_intr();
com->prev_modem_status = com->last_modem_status com->prev_modem_status = com->last_modem_status
= cd_inb(iobase, CD1400_MSVR2); = cd_inb(iobase, CD1400_MSVR2, com->cy_align);
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
= CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
enable_intr(); enable_intr();
@ -827,7 +860,7 @@ comhardclose(com)
com->poll_output = FALSE; com->poll_output = FALSE;
#endif #endif
com->do_timestamp = 0; com->do_timestamp = 0;
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
#if 0 #if 0
outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
#endif #endif
@ -837,7 +870,7 @@ comhardclose(com)
outb(iobase + com_ier, 0); outb(iobase + com_ier, 0);
#else #else
disable_intr(); disable_intr();
cd_outb(iobase, CD1400_SRER, com->intr_enable = 0); cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable = 0);
enable_intr(); enable_intr();
#endif #endif
tp = com->tp; tp = com->tp;
@ -859,7 +892,7 @@ comhardclose(com)
com->channel_control = CD1400_CCR_CMDCHANCTL com->channel_control = CD1400_CCR_CMDCHANCTL
| CD1400_CCR_XMTEN | CD1400_CCR_XMTEN
| CD1400_CCR_RCVDIS; | CD1400_CCR_RCVDIS;
cd1400_channel_cmd(iobase, com->channel_control); cd1400_channel_cmd(iobase, com->channel_control, com->cy_align);
if (com->dtr_wait != 0) { if (com->dtr_wait != 0) {
timeout(siodtrwakeup, com, com->dtr_wait); timeout(siodtrwakeup, com, com->dtr_wait);
@ -948,20 +981,19 @@ void
siointr(unit) siointr(unit)
int unit; int unit;
{ {
int baseu; cy_addr cy_iobase, iobase;
cy_addr cy_iobase; int baseu, cyu, cy_align;
int cyu; u_char status;
cy_addr iobase;
u_char status;
baseu = unit * CY_MAX_PORTS; baseu = unit * CY_MAX_PORTS;
cy_iobase = com_addr(baseu)->cy_iobase; cy_iobase = com_addr(baseu)->cy_iobase;
cy_align = com_addr(baseu)->cy_align;
/* check each CD1400 in turn */ /* check each CD1400 in turn */
for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
iobase = (cy_addr) (cy_iobase + cy_chip_offset[cyu]); iobase = (cy_addr) (cy_iobase + (cy_chip_offset[cyu] << cy_align));
/* poll to see if it has any work */ /* poll to see if it has any work */
status = cd_inb(iobase, CD1400_SVRR); status = cd_inb(iobase, CD1400_SVRR, cy_align);
if (status == 0) if (status == 0)
continue; continue;
#ifdef CyDebug #ifdef CyDebug
@ -981,13 +1013,13 @@ siointr(unit)
#endif #endif
#ifdef PollMode #ifdef PollMode
save_rir = cd_inb(iobase, CD1400_RIR); save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter rx service */ /* enter rx service */
cd_outb(iobase, CD1400_CAR, save_rir); cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
serv_type = cd_inb(iobase, CD1400_RIVR); serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
com = com_addr(baseu com = com_addr(baseu
+ ((serv_type >> CD1400_xIVR_CHAN_SHIFT) + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
& CD1400_xIVR_CHAN)); & CD1400_xIVR_CHAN));
@ -1002,9 +1034,9 @@ siointr(unit)
if (serv_type & CD1400_RIVR_EXCEPTION) { if (serv_type & CD1400_RIVR_EXCEPTION) {
++com->recv_exception; ++com->recv_exception;
line_status = cd_inb(iobase, CD1400_RDSR); line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
/* break/unnattached error bits or real input? */ /* break/unnattached error bits or real input? */
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifndef SOFT_HOTCHAR #ifndef SOFT_HOTCHAR
if (line_status & CD1400_RDSR_SPECIAL if (line_status & CD1400_RDSR_SPECIAL
&& com->hotchar != 0) && com->hotchar != 0)
@ -1053,7 +1085,7 @@ siointr(unit)
outb(com->modem_ctl_port, outb(com->modem_ctl_port,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
if (line_status & LSR_OE) if (line_status & LSR_OE)
@ -1063,7 +1095,7 @@ siointr(unit)
} else { } else {
int ifree; int ifree;
count = cd_inb(iobase, CD1400_RDCR); count = cd_inb(iobase, CD1400_RDCR, cy_align);
com->bytes_in += count; com->bytes_in += count;
ioptr = com->iptr; ioptr = com->iptr;
ifree = com->ibufend - ioptr; ifree = com->ibufend - ioptr;
@ -1075,7 +1107,7 @@ siointr(unit)
microtime(&com->timestamp); microtime(&com->timestamp);
do { do {
recv_data = cd_inb(iobase, recv_data = cd_inb(iobase,
CD1400_RDSR); CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data && recv_data
@ -1090,7 +1122,7 @@ siointr(unit)
com->delta_error_counts com->delta_error_counts
[CE_INTERRUPT_BUF_OVERFLOW] += count; [CE_INTERRUPT_BUF_OVERFLOW] += count;
do { do {
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data == com->hotchar) && recv_data == com->hotchar)
@ -1107,12 +1139,12 @@ siointr(unit)
outb(com->modem_ctl_port, outb(com->modem_ctl_port,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
com_events += count; com_events += count;
do { do {
recv_data = cd_inb(iobase, CD1400_RDSR); recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
if (com->hotchar != 0 if (com->hotchar != 0
&& recv_data == com->hotchar) && recv_data == com->hotchar)
@ -1129,12 +1161,12 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_RIR, cd_outb(iobase, CD1400_RIR, cy_align,
save_rir save_rir
& ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
if (status & CD1400_SVRR_MDMCH) { if (status & CD1400_SVRR_MDMCH) {
@ -1148,11 +1180,11 @@ cont:
#endif #endif
#ifdef PollMode #ifdef PollMode
save_mir = cd_inb(iobase, CD1400_MIR); save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter modem service */ /* enter modem service */
cd_outb(iobase, CD1400_CAR, save_mir); cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
+ (save_mir & CD1400_MIR_CHAN)); + (save_mir & CD1400_MIR_CHAN));
@ -1165,7 +1197,7 @@ cont:
& CD1400_xIVR_CHAN)); & CD1400_xIVR_CHAN));
#endif #endif
++com->mdm; ++com->mdm;
modem_status = cd_inb(iobase, CD1400_MSVR2); modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
if (modem_status != com->last_modem_status) { if (modem_status != com->last_modem_status) {
if (com->do_dcd_timestamp if (com->do_dcd_timestamp
&& !(com->last_modem_status & MSR_DCD) && !(com->last_modem_status & MSR_DCD)
@ -1194,13 +1226,13 @@ cont:
| CS_ODEVREADY) | CS_ODEVREADY)
&& !(com->intr_enable && !(com->intr_enable
& CD1400_SRER_TXRDY)) & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} else { } else {
com->state &= ~CS_ODEVREADY; com->state &= ~CS_ODEVREADY;
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
&= ~CD1400_SRER_TXRDY); &= ~CD1400_SRER_TXRDY);
} }
@ -1210,12 +1242,12 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_MIR, cd_outb(iobase, CD1400_MIR, cy_align,
save_mir save_mir
& ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
if (status & CD1400_SVRR_TXRDY) { if (status & CD1400_SVRR_TXRDY) {
@ -1228,11 +1260,11 @@ cont:
#endif #endif
#ifdef PollMode #ifdef PollMode
save_tir = cd_inb(iobase, CD1400_TIR); save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
save_car = cd_inb(iobase, CD1400_CAR); save_car = cd_inb(iobase, CD1400_CAR, cy_align);
/* enter tx service */ /* enter tx service */
cd_outb(iobase, CD1400_CAR, save_tir); cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
com = com_addr(baseu com = com_addr(baseu
+ cyu * CD1400_NO_OF_CHANNELS + cyu * CD1400_NO_OF_CHANNELS
+ (save_tir & CD1400_TIR_CHAN)); + (save_tir & CD1400_TIR_CHAN));
@ -1255,7 +1287,7 @@ cont:
ocount = CD1400_TX_FIFO_SIZE; ocount = CD1400_TX_FIFO_SIZE;
com->bytes_out += ocount; com->bytes_out += ocount;
do do
cd_outb(iobase, CD1400_TDR, *ioptr++); cd_outb(iobase, CD1400_TDR, cy_align, *ioptr++);
while (--ocount != 0); while (--ocount != 0);
com->obufq.l_head = ioptr; com->obufq.l_head = ioptr;
if (ioptr >= com->obufq.l_tail) { if (ioptr >= com->obufq.l_tail) {
@ -1271,7 +1303,7 @@ cont:
} else { } else {
/* output just completed */ /* output just completed */
com->state &= ~CS_BUSY; com->state &= ~CS_BUSY;
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, cy_align,
com->intr_enable com->intr_enable
&= ~CD1400_SRER_TXRDY); &= ~CD1400_SRER_TXRDY);
} }
@ -1285,18 +1317,18 @@ cont:
/* terminate service context */ /* terminate service context */
#ifdef PollMode #ifdef PollMode
cd_outb(iobase, CD1400_TIR, cd_outb(iobase, CD1400_TIR, cy_align,
save_tir save_tir
& ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
cd_outb(iobase, CD1400_CAR, save_car); cd_outb(iobase, CD1400_CAR, cy_align, save_car);
#else #else
cd_outb(iobase, CD1400_EOSRR, 0); cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
#endif #endif
} }
} }
/* ensure an edge for the next interrupt */ /* ensure an edge for the next interrupt */
cy_outb(cy_iobase, CY_CLEAR_INTR, 0); cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
schedsofttty(); schedsofttty();
} }
@ -1406,7 +1438,7 @@ sioioctl(dev, cmd, data, flag, p)
splx(s); splx(s);
return (error); return (error);
} }
cd_outb(iobase, CD1400_CAR, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN);
switch (cmd) { switch (cmd) {
#if 0 #if 0
case TIOCSBRK: case TIOCSBRK:
@ -1544,9 +1576,9 @@ repeat:
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#else #else
iobase = com->iobase, iobase = com->iobase,
cd_outb(iobase, CD1400_CAR, cd_outb(iobase, CD1400_CAR, com->cy_align,
unit & CD1400_CAR_CHAN), unit & CD1400_CAR_CHAN),
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#endif #endif
enable_intr(); enable_intr();
@ -1669,19 +1701,19 @@ comparam(tp, t)
com = com_addr(unit); com = com_addr(unit);
iobase = com->iobase; iobase = com->iobase;
s = spltty(); s = spltty();
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
if (odivisor == 0) if (odivisor == 0)
(void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
else else
(void)commctl(com, TIOCM_DTR, DMBIS); (void)commctl(com, TIOCM_DTR, DMBIS);
if (idivisor != 0) { if (idivisor != 0) {
cd_outb(iobase, CD1400_RBPR, idivisor); cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor);
cd_outb(iobase, CD1400_RCOR, iprescaler); cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler);
} }
if (odivisor != 0) { if (odivisor != 0) {
cd_outb(iobase, CD1400_TBPR, odivisor); cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor);
cd_outb(iobase, CD1400_TCOR, oprescaler); cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler);
} }
/* /*
@ -1694,20 +1726,20 @@ comparam(tp, t)
| (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
if (opt != com->channel_control) { if (opt != com->channel_control) {
com->channel_control = opt; com->channel_control = opt;
cd1400_channel_cmd(iobase, opt); cd1400_channel_cmd(iobase, opt, com->cy_align);
} }
#ifdef Smarts #ifdef Smarts
/* set special chars */ /* set special chars */
/* XXX if one is _POSIX_VDISABLE, can't use some others */ /* XXX if one is _POSIX_VDISABLE, can't use some others */
if (t->c_cc[VSTOP] != _POSIX_VDISABLE) if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR1, t->c_cc[VSTOP]); cd_outb(iobase, CD1400_SCHR1, com->cy_align, t->c_cc[VSTOP]);
if (t->c_cc[VSTART] != _POSIX_VDISABLE) if (t->c_cc[VSTART] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR2, t->c_cc[VSTART]); cd_outb(iobase, CD1400_SCHR2, com->cy_align, t->c_cc[VSTART]);
if (t->c_cc[VINTR] != _POSIX_VDISABLE) if (t->c_cc[VINTR] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR3, t->c_cc[VINTR]); cd_outb(iobase, CD1400_SCHR3, com->cy_align, t->c_cc[VINTR]);
if (t->c_cc[VSUSP] != _POSIX_VDISABLE) if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]);
#endif #endif
/* /*
@ -1754,14 +1786,14 @@ comparam(tp, t)
cor_change = 0; cor_change = 0;
if (opt != com->cor[0]) { if (opt != com->cor[0]) {
cor_change |= CD1400_CCR_COR1; cor_change |= CD1400_CCR_COR1;
cd_outb(iobase, CD1400_COR1, com->cor[0] = opt); cd_outb(iobase, CD1400_COR1, com->cy_align, com->cor[0] = opt);
} }
/* /*
* Set receive time-out period, normally to max(one char time, 5 ms). * Set receive time-out period, normally to max(one char time, 5 ms).
*/ */
if (t->c_ispeed == 0) if (t->c_ispeed == 0)
itimeout = cd_inb(iobase, CD1400_RTPR); itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align);
else { else {
itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
#ifdef SOFT_HOTCHAR #ifdef SOFT_HOTCHAR
@ -1777,7 +1809,7 @@ comparam(tp, t)
itimeout = t->c_cc[VTIME] * 10; itimeout = t->c_cc[VTIME] * 10;
if (itimeout > 255) if (itimeout > 255)
itimeout = 255; itimeout = 255;
cd_outb(iobase, CD1400_RTPR, itimeout); cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout);
/* /*
* set channel option register 2 - * set channel option register 2 -
@ -1796,7 +1828,7 @@ comparam(tp, t)
#endif #endif
if (opt != com->cor[1]) { if (opt != com->cor[1]) {
cor_change |= CD1400_CCR_COR2; cor_change |= CD1400_CCR_COR2;
cd_outb(iobase, CD1400_COR2, com->cor[1] = opt); cd_outb(iobase, CD1400_COR2, com->cy_align, com->cor[1] = opt);
} }
/* /*
@ -1814,12 +1846,12 @@ comparam(tp, t)
#endif #endif
if (opt != com->cor[2]) { if (opt != com->cor[2]) {
cor_change |= CD1400_CCR_COR3; cor_change |= CD1400_CCR_COR3;
cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt);
} }
/* notify the CD1400 if COR1-3 have changed */ /* notify the CD1400 if COR1-3 have changed */
if (cor_change) if (cor_change)
cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change); cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change, com->cy_align);
/* /*
* set channel option register 4 - * set channel option register 4 -
@ -1858,7 +1890,7 @@ comparam(tp, t)
#else #else
opt |= CD1400_COR4_PFO_EXCEPTION; opt |= CD1400_COR4_PFO_EXCEPTION;
#endif #endif
cd_outb(iobase, CD1400_COR4, opt); cd_outb(iobase, CD1400_COR4, com->cy_align, opt);
/* /*
* set channel option register 5 - * set channel option register 5 -
@ -1875,7 +1907,7 @@ comparam(tp, t)
if (t->c_oflag & OCRNL) if (t->c_oflag & OCRNL)
opt |= CD1400_COR5_OCRNL; opt |= CD1400_COR5_OCRNL;
#endif #endif
cd_outb(iobase, CD1400_COR5, opt); cd_outb(iobase, CD1400_COR5, com->cy_align, opt);
/* /*
* XXX we probably alway want to track carrier changes, so that * XXX we probably alway want to track carrier changes, so that
@ -1892,7 +1924,7 @@ comparam(tp, t)
if (cflag & CCTS_OFLOW) if (cflag & CCTS_OFLOW)
opt |= CD1400_MCOR1_CTSzd; opt |= CD1400_MCOR1_CTSzd;
#endif #endif
cd_outb(iobase, CD1400_MCOR1, opt); cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt);
/* /*
* set modem change option register 2 * set modem change option register 2
@ -1903,7 +1935,7 @@ comparam(tp, t)
if (cflag & CCTS_OFLOW) if (cflag & CCTS_OFLOW)
opt |= CD1400_MCOR2_CTSod; opt |= CD1400_MCOR2_CTSod;
#endif #endif
cd_outb(iobase, CD1400_MCOR2, opt); cd_outb(iobase, CD1400_MCOR2, com->cy_align, opt);
/* /*
* XXX should have done this long ago, but there is too much state * XXX should have done this long ago, but there is too much state
@ -1946,11 +1978,11 @@ comparam(tp, t)
#endif #endif
if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
if (!(com->intr_enable & CD1400_SRER_TXRDY)) if (!(com->intr_enable & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable |= CD1400_SRER_TXRDY); com->intr_enable |= CD1400_SRER_TXRDY);
} else { } else {
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable &= ~CD1400_SRER_TXRDY); com->intr_enable &= ~CD1400_SRER_TXRDY);
} }
@ -1982,17 +2014,17 @@ comstart(tp)
#endif #endif
disable_intr(); disable_intr();
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
if (tp->t_state & TS_TTSTOP) { if (tp->t_state & TS_TTSTOP) {
com->state &= ~CS_TTGO; com->state &= ~CS_TTGO;
if (com->intr_enable & CD1400_SRER_TXRDY) if (com->intr_enable & CD1400_SRER_TXRDY)
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable &= ~CD1400_SRER_TXRDY); com->intr_enable &= ~CD1400_SRER_TXRDY);
} else { } else {
com->state |= CS_TTGO; com->state |= CS_TTGO;
if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
&& !(com->intr_enable & CD1400_SRER_TXRDY)) && !(com->intr_enable & CD1400_SRER_TXRDY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable |= CD1400_SRER_TXRDY); com->intr_enable |= CD1400_SRER_TXRDY);
} }
if (tp->t_state & TS_TBLOCK) { if (tp->t_state & TS_TBLOCK) {
@ -2000,7 +2032,7 @@ comstart(tp)
#if 0 #if 0
outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image &= ~MCR_RTS); com->mcr_image &= ~MCR_RTS);
#endif #endif
} else { } else {
@ -2013,7 +2045,7 @@ comstart(tp)
#if 0 #if 0
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
#else #else
cd_outb(iobase, CD1400_MSVR1, cd_outb(iobase, CD1400_MSVR1, com->cy_align,
com->mcr_image |= MCR_RTS); com->mcr_image |= MCR_RTS);
#endif #endif
} }
@ -2048,7 +2080,7 @@ comstart(tp)
com->state |= CS_BUSY; com->state |= CS_BUSY;
if (com->state >= (CS_BUSY | CS_TTGO if (com->state >= (CS_BUSY | CS_TTGO
| CS_ODEVREADY)) | CS_ODEVREADY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} }
@ -2076,7 +2108,7 @@ comstart(tp)
com->state |= CS_BUSY; com->state |= CS_BUSY;
if (com->state >= (CS_BUSY | CS_TTGO if (com->state >= (CS_BUSY | CS_TTGO
| CS_ODEVREADY)) | CS_ODEVREADY))
cd_outb(iobase, CD1400_SRER, cd_outb(iobase, CD1400_SRER, com->cy_align,
com->intr_enable com->intr_enable
|= CD1400_SRER_TXRDY); |= CD1400_SRER_TXRDY);
} }
@ -2182,18 +2214,18 @@ commctl(com, bits, how)
switch (how) { switch (how) {
case DMSET: case DMSET:
com->mcr_image = mcr; com->mcr_image = mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
case DMBIS: case DMBIS:
com->mcr_image = mcr = com->mcr_image | mcr; com->mcr_image = mcr = com->mcr_image | mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
case DMBIC: case DMBIC:
com->mcr_image = mcr = com->mcr_image & ~mcr; com->mcr_image = mcr = com->mcr_image & ~mcr;
cd_outb(iobase, CD1400_MSVR1, mcr); cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr);
cd_outb(iobase, CD1400_MSVR2, mcr); cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr);
break; break;
} }
enable_intr(); enable_intr();
@ -2331,17 +2363,17 @@ disc_optim(tp, t, com)
com->hotchar = 0; com->hotchar = 0;
#ifndef SOFT_HOTCHAR #ifndef SOFT_HOTCHAR
iobase = com->iobase; iobase = com->iobase;
cd_outb(iobase, CD1400_CAR, com->unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, com->unit & CD1400_CAR_CHAN);
opt = com->cor[2] & ~CD1400_COR3_SCD34; opt = com->cor[2] & ~CD1400_COR3_SCD34;
if (com->hotchar != 0) { if (com->hotchar != 0) {
cd_outb(iobase, CD1400_SCHR3, com->hotchar); cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar);
cd_outb(iobase, CD1400_SCHR4, com->hotchar); cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar);
opt |= CD1400_COR3_SCD34; opt |= CD1400_COR3_SCD34;
} }
if (opt != com->cor[2]) { if (opt != com->cor[2]) {
cd_outb(iobase, CD1400_COR3, com->cor[2] = opt); cd_outb(iobase, CD1400_COR3, com->cy_align, com->cor[2] = opt);
cd1400_channel_cmd(com->iobase, cd1400_channel_cmd(com->iobase,
CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, com->cy_align);
} }
#endif #endif
} }
@ -2405,9 +2437,10 @@ comspeed(speed, prescaler_io)
} }
static void static void
cd1400_channel_cmd(iobase, cmd) cd1400_channel_cmd(iobase, cmd, cy_align)
cy_addr iobase; cy_addr iobase;
int cmd; int cmd;
int cy_align;
{ {
/* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed,
as the card is probed every round? Replaced delaycount with 8k. as the card is probed every round? Replaced delaycount with 8k.
@ -2417,14 +2450,14 @@ cd1400_channel_cmd(iobase, cmd)
u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */ u_int maxwait = 5 * 8 * 1024; /* approx. 5 ms */
/* wait for processing of previous command to complete */ /* wait for processing of previous command to complete */
while (cd_inb(iobase, CD1400_CCR) && maxwait--) while (cd_inb(iobase, CD1400_CCR, cy_align) && maxwait--)
; ;
if (!maxwait) if (!maxwait)
log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n",
5 * 8 * 1024); 5 * 8 * 1024);
cd_outb(iobase, CD1400_CCR, cmd); cd_outb(iobase, CD1400_CCR, cy_align, cmd);
} }
#ifdef CyDebug #ifdef CyDebug
@ -2448,7 +2481,7 @@ cystatus(unit)
iobase = com->iobase; iobase = com->iobase;
printf("\n"); printf("\n");
printf("cd1400 base address:\\tt%p\n", iobase); printf("cd1400 base address:\\tt%p\n", iobase);
cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN);
printf("saved channel_control:\t\t0x%02x\n", com->channel_control); printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
com->cor[0], com->cor[1], com->cor[2]); com->cor[0], com->cor[1], com->cor[2]);

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: cyreg.h,v 1.1 1995/07/05 12:15:51 bde Exp $ * $Id: cyreg.h,v 1.2 1996/10/04 10:33:13 davidg Exp $
*/ */
/* /*
@ -36,22 +36,21 @@
#define CY8_SVCACKR 0x100 #define CY8_SVCACKR 0x100
#define CY8_SVCACKT 0x200 #define CY8_SVCACKT 0x200
#define CY8_SVCACKM 0x300 #define CY8_SVCACKM 0x300
#define CY_CD1400_MEMSIZE 0x400 #define CY16_RESET 0x0a00
#define CY16_RESET 0x1400 #define CY_CLEAR_INTR 0x0c00 /* intr ack address */
#define CY_CLEAR_INTR 0x1800 /* intr ack address */
#define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ #define CY_MAX_CD1400s 8 /* for Cyclom-32Y */
#define CY_CLOCK 25000000 /* baud rate clock */ #define CY_CLOCK 25000000 /* baud rate clock */
#ifdef CyDebug #ifdef CyDebug
#define cd_inb(iobase, reg) (++cd_inbs, *((iobase) + 2 * (reg))) #define cd_inb(iobase, reg, cy_align) (++cd_inbs, *((iobase) + ((reg)*2 << (cy_align))))
#define cy_inb(iobase, reg) (++cy_inbs, *((iobase) + (reg))) #define cy_inb(iobase, reg) (++cy_inbs, *((iobase) + (reg)))
#define cd_outb(iobase, reg, val) (++cd_outbs, (void)(*((iobase) + 2 * (reg)) = (val))) #define cd_outb(iobase, reg, cy_align, val) (++cd_outbs, (void)(*((iobase) + ((reg)*2 << (cy_align))) = (val)))
#define cy_outb(iobase, reg, val) (++cy_outbs, (void)(*((iobase) + (reg)) = (val))) #define cy_outb(iobase, reg, val) (++cy_outbs, (void)(*((iobase) + (reg)) = (val)))
#else #else
#define cd_inb(iobase, reg) (*((iobase) + 2 * (reg))) #define cd_inb(iobase, reg, cy_align) (*((iobase) + ((reg)*2 << (cy_align))))
#define cy_inb(iobase, reg) (*((iobase) + (reg))) #define cy_inb(iobase, reg) (*((iobase) + (reg)))
#define cd_outb(iobase, reg, val) ((void)(*((iobase) + 2 * (reg)) = (val))) #define cd_outb(iobase, reg, cy_align, val) ((void)(*((iobase) + ((reg)*2 << (cy_align))) = (val)))
#define cy_outb(iobase, reg, val) ((void)(*((iobase) + (reg)) = (val))) #define cy_outb(iobase, reg, val) ((void)(*((iobase) + (reg)) = (val)))
#endif #endif

132
sys/pci/cy_pci.c Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 1996, David Greenman
* All rights reserved.
*
* 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
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
/*
* Cyclades Y PCI serial interface driver
*/
#include <pci.h>
#if NPCI > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <pci/pcivar.h>
#include <pci/cy_pcireg.h>
static char *cy_probe __P((pcici_t, pcidi_t));
static void cy_attach __P((pcici_t, int));
extern int cyattach_common(void *, int); /* Not exactly correct */
extern void cyintr(int);
static u_long cy_count;
static struct pci_device cy_device = {
"cy",
cy_probe,
cy_attach,
&cy_count,
NULL
};
DATA_SET(pcidevice_set, cy_device);
static char *
cy_probe(config_id, device_id)
pcici_t config_id;
pcidi_t device_id;
{
if ((device_id & 0xffff) == CY_VENDORID_CYCLADES &&
((device_id >> 16) == CY_DEVICEID_CYCLOM_Y_1 ||
(device_id >> 16) == CY_DEVICEID_CYCLOM_Y_2))
return ("Cyclades Cyclom-Y Serial Adapter");
return NULL;
}
static void
cy_attach(config_id, unit)
pcici_t config_id;
int unit;
{
vm_offset_t paddr;
void *vaddr;
u_int32_t ioport;
int adapter;
ioport = (u_int32_t) pci_conf_read(config_id, CY_PCI_BASE_ADDR1) & ~0x3;
paddr = pci_conf_read(config_id, CY_PCI_BASE_ADDR2) & ~0xf;
#if 0
if (!pci_map_mem(config_id, CY_PCI_BASE_ADDR2, &vaddr, &paddr)) {
printf("cy%d: couldn't map shared memory\n", unit);
return;
};
#endif
vaddr = pmap_mapdev(paddr, 0x4000);
adapter = cyattach_common(vaddr, 1);
if (adapter < 0) {
/*
* No ports found. Release resources and punt.
*/
printf("cy%d: no ports found!", unit);
goto fail;
}
/*
* Allocate our interrupt.
* XXX Using the ISA interrupt handler directly is a bit of a violation
* since it doesn't actually take the same argument. For PCI, the
* argument is a void * token, but for ISA it is a unit. Since
* there is no overlap in PCI/ISA unit numbers for this driver, and
* since the ISA driver must handle the interrupt anyway, we use
* the unit number as the token even for PCI.
*/
if (!pci_map_int(config_id, (pci_inthand_t *)cyintr, (void *)adapter, &tty_imask)) {
printf("cy%d: couldn't map interrupt\n", unit);
goto fail;
}
/*
* Enable the "local" interrupt input to generate a
* PCI interrupt.
*/
outw(ioport + CY_PLX_ICS, inw(CY_PLX_ICS) |
CY_PLX_ICS_IENABLE | CY_PLX_ICS_LOCAL_IENABLE);
return;
fail:
/* XXX should release any allocated virtual memory */
return;
}
#endif /* NPCI > 0 */

40
sys/pci/cy_pcireg.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 1996, David Greenman
* All rights reserved.
*
* 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
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#define CY_VENDORID_CYCLADES 0x120e
#define CY_DEVICEID_CYCLOM_Y_1 0x100
#define CY_DEVICEID_CYCLOM_Y_2 0x101
#define CY_PCI_BASE_ADDR0 0x10
#define CY_PCI_BASE_ADDR1 0x14
#define CY_PCI_BASE_ADDR2 0x18
#define CY_PLX_ICS 0x68
#define CY_PLX_ICS_IENABLE 0x100
#define CY_PLX_ICS_LOCAL_IENABLE 0x800