diff options
author | dg <dg@FreeBSD.org> | 1996-10-13 01:09:24 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1996-10-13 01:09:24 +0000 |
commit | 73f657605d58c52b9c121b52c000db0e320ba90a (patch) | |
tree | b894c4e6514e36c16b25d9778b2dfb1bd1e9e651 /sys | |
parent | 3287a8d4c6e9ac3f4317b0544054ca2a8a248c0d (diff) | |
download | FreeBSD-src-73f657605d58c52b9c121b52c000db0e320ba90a.zip FreeBSD-src-73f657605d58c52b9c121b52c000db0e320ba90a.tar.gz |
Changes to add support for the PCI version of the Cyclades Cyclom-Y
serial adapter, and support for multiple Cyclom controllers.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/dev/cy/cy.c | 295 | ||||
-rw-r--r-- | sys/dev/cy/cy_isa.c | 295 | ||||
-rw-r--r-- | sys/dev/cy/cy_pci.c | 132 | ||||
-rw-r--r-- | sys/dev/cy/cyreg.h | 15 | ||||
-rw-r--r-- | sys/i386/isa/cy.c | 295 | ||||
-rw-r--r-- | sys/i386/isa/cyreg.h | 15 | ||||
-rw-r--r-- | sys/pci/cy_pci.c | 132 | ||||
-rw-r--r-- | sys/pci/cy_pcireg.h | 40 |
9 files changed, 811 insertions, 409 deletions
diff --git a/sys/conf/files b/sys/conf/files index 15cd728..c7c25f3 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -305,6 +305,7 @@ pccard/pccard.c optional crd pccard/pcic.c optional pcic device-driver pci/aic7870.c optional ahc 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_ed_p.c optional ed device-driver pci/if_fxp.c optional fxp device-driver diff --git a/sys/dev/cy/cy.c b/sys/dev/cy/cy.c index 1346042..4634f4b 100644 --- a/sys/dev/cy/cy.c +++ b/sys/dev/cy/cy.c @@ -27,7 +27,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * 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" @@ -141,7 +141,7 @@ /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ #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 RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) @@ -153,7 +153,8 @@ #define CONTROL_LOCK_STATE 0x40 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) #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. @@ -262,6 +263,7 @@ struct com_s { cy_addr cy_iobase; /* base address of this port's cyclom */ cy_addr iobase; /* base address of this port's cd1400 */ + int cy_align; /* index for register alignment */ struct tty *tp; /* cross reference */ @@ -330,8 +332,10 @@ void siopoll __P((void)); #define siommap nommap #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 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 void comhardclose __P((struct com_s *com)); #if 0 @@ -399,6 +403,7 @@ static u_int cy_timeouts; #endif static int cy_nr_cd1400s[NCY]; +static int cy_total_devices; #undef RxFifoThreshold static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); static int cy_chip_offset[] = { @@ -416,16 +421,9 @@ static int sioprobe(dev) struct isa_device *dev; { - int cyu; - u_char firmware_version; cy_addr iobase; - int unit; 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) */ cy_inb(iobase, CY16_RESET); /* XXX? */ @@ -435,22 +433,34 @@ sioprobe(dev) cy_outb(iobase, CY_CLEAR_INTR, 0); 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) { 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 */ for (i = 0; i < 10; i++) { DELAY(50); - if (!cd_inb(iobase, CD1400_CCR)) + if (!cd_inb(iobase, CD1400_CCR, cy_align)) break; } /* clear the GFRCR register */ - cd_outb(iobase, CD1400_GFRCR, 0); + cd_outb(iobase, CD1400_GFRCR, cy_align, 0); /* issue a reset command */ - cd_outb(iobase, CD1400_CCR, + cd_outb(iobase, CD1400_CCR, cy_align, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for the CD1400 to initialize itself */ @@ -458,7 +468,7 @@ sioprobe(dev) DELAY(50); /* retrieve firmware version */ - firmware_version = cd_inb(iobase, CD1400_GFRCR); + firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); if ((firmware_version & 0xf0) == 0x40) break; } @@ -470,38 +480,60 @@ sioprobe(dev) */ if ((firmware_version & 0xf0) != 0x40) break; - ++cy_nr_cd1400s[unit]; } - return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); + return (cyu); } static int sioattach(isdp) - struct isa_device *isdp; + struct isa_device *isdp; { - int cyu; - cy_addr cy_iobase; - dev_t dev; - cy_addr iobase; - int ncyu; - int unit; + int adapter; - unit = isdp->id_unit; - if ((u_int)unit >= NCY) - return (0); - ncyu = cy_nr_cd1400s[unit]; - if (ncyu == 0) + adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); + if (adapter < 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; + return (1); +} - cy_iobase = (cy_addr)isdp->id_maddr; - unit *= CY_MAX_PORTS; +int +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) { 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. */ - cd_outb(iobase, CD1400_PPR, + cd_outb(iobase, CD1400_PPR, cy_align, howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { @@ -522,6 +554,7 @@ sioattach(isdp) com->cy_iobase = cy_iobase; com->iobase = iobase; + com->cy_align = cy_align; /* * 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 */ - cy_outb(cy_iobase, CY_CLEAR_INTR, 0); + cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - return (1); + return (adapter); } static int @@ -664,8 +697,8 @@ open_top: iobase = com->iobase; /* reset this channel */ - cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); - cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); + cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align); /* * Resetting disables the transmitter and receiver as well as @@ -677,7 +710,7 @@ open_top: com->channel_control = 0; /* 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); /* @@ -732,8 +765,8 @@ open_top: (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); disable_intr(); com->prev_modem_status = com->last_modem_status - = cd_inb(iobase, CD1400_MSVR2); - cd_outb(iobase, CD1400_SRER, + = cd_inb(iobase, CD1400_MSVR2, com->cy_align); + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); enable_intr(); @@ -827,7 +860,7 @@ comhardclose(com) com->poll_output = FALSE; #endif 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 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); #endif @@ -837,7 +870,7 @@ comhardclose(com) outb(iobase + com_ier, 0); #else 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(); #endif tp = com->tp; @@ -859,7 +892,7 @@ comhardclose(com) com->channel_control = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | 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) { timeout(siodtrwakeup, com, com->dtr_wait); @@ -948,20 +981,19 @@ void siointr(unit) int unit; { - int baseu; - cy_addr cy_iobase; - int cyu; - cy_addr iobase; - u_char status; + cy_addr cy_iobase, iobase; + int baseu, cyu, cy_align; + u_char status; baseu = unit * CY_MAX_PORTS; cy_iobase = com_addr(baseu)->cy_iobase; + cy_align = com_addr(baseu)->cy_align; /* check each CD1400 in turn */ 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 */ - status = cd_inb(iobase, CD1400_SVRR); + status = cd_inb(iobase, CD1400_SVRR, cy_align); if (status == 0) continue; #ifdef CyDebug @@ -981,13 +1013,13 @@ siointr(unit) #endif #ifdef PollMode - save_rir = cd_inb(iobase, CD1400_RIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_rir = cd_inb(iobase, CD1400_RIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* 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 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) & CD1400_xIVR_CHAN)); @@ -1002,9 +1034,9 @@ siointr(unit) if (serv_type & CD1400_RIVR_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? */ - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifndef SOFT_HOTCHAR if (line_status & CD1400_RDSR_SPECIAL && com->hotchar != 0) @@ -1053,7 +1085,7 @@ siointr(unit) outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, cy_align, com->mcr_image &= ~MCR_RTS); #endif if (line_status & LSR_OE) @@ -1063,7 +1095,7 @@ siointr(unit) } else { int ifree; - count = cd_inb(iobase, CD1400_RDCR); + count = cd_inb(iobase, CD1400_RDCR, cy_align); com->bytes_in += count; ioptr = com->iptr; ifree = com->ibufend - ioptr; @@ -1075,7 +1107,7 @@ siointr(unit) microtime(&com->timestamp); do { recv_data = cd_inb(iobase, - CD1400_RDSR); + CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data @@ -1090,7 +1122,7 @@ siointr(unit) com->delta_error_counts [CE_INTERRUPT_BUF_OVERFLOW] += count; do { - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data == com->hotchar) @@ -1107,12 +1139,12 @@ siointr(unit) outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, cy_align, com->mcr_image &= ~MCR_RTS); #endif com_events += count; do { - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data == com->hotchar) @@ -1129,12 +1161,12 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_RIR, + cd_outb(iobase, CD1400_RIR, cy_align, save_rir & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } if (status & CD1400_SVRR_MDMCH) { @@ -1148,11 +1180,11 @@ cont: #endif #ifdef PollMode - save_mir = cd_inb(iobase, CD1400_MIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_mir = cd_inb(iobase, CD1400_MIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* 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 + (save_mir & CD1400_MIR_CHAN)); @@ -1165,7 +1197,7 @@ cont: & CD1400_xIVR_CHAN)); #endif ++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 (com->do_dcd_timestamp && !(com->last_modem_status & MSR_DCD) @@ -1194,13 +1226,13 @@ cont: | CS_ODEVREADY) && !(com->intr_enable & CD1400_SRER_TXRDY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } else { com->state &= ~CS_ODEVREADY; if (com->intr_enable & CD1400_SRER_TXRDY) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable &= ~CD1400_SRER_TXRDY); } @@ -1210,12 +1242,12 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_MIR, + cd_outb(iobase, CD1400_MIR, cy_align, save_mir & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } if (status & CD1400_SVRR_TXRDY) { @@ -1228,11 +1260,11 @@ cont: #endif #ifdef PollMode - save_tir = cd_inb(iobase, CD1400_TIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_tir = cd_inb(iobase, CD1400_TIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* enter tx service */ - cd_outb(iobase, CD1400_CAR, save_tir); + cd_outb(iobase, CD1400_CAR, cy_align, save_tir); com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS + (save_tir & CD1400_TIR_CHAN)); @@ -1255,7 +1287,7 @@ cont: ocount = CD1400_TX_FIFO_SIZE; com->bytes_out += ocount; do - cd_outb(iobase, CD1400_TDR, *ioptr++); + cd_outb(iobase, CD1400_TDR, cy_align, *ioptr++); while (--ocount != 0); com->obufq.l_head = ioptr; if (ioptr >= com->obufq.l_tail) { @@ -1271,7 +1303,7 @@ cont: } else { /* output just completed */ com->state &= ~CS_BUSY; - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable &= ~CD1400_SRER_TXRDY); } @@ -1285,18 +1317,18 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_TIR, + cd_outb(iobase, CD1400_TIR, cy_align, save_tir & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } } /* 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(); } @@ -1406,7 +1438,7 @@ sioioctl(dev, cmd, data, flag, p) splx(s); 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) { #if 0 case TIOCSBRK: @@ -1544,9 +1576,9 @@ repeat: com->mcr_image |= MCR_RTS); #else iobase = com->iobase, - cd_outb(iobase, CD1400_CAR, + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN), - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image |= MCR_RTS); #endif enable_intr(); @@ -1669,19 +1701,19 @@ comparam(tp, t) com = com_addr(unit); iobase = com->iobase; 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) (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ else (void)commctl(com, TIOCM_DTR, DMBIS); if (idivisor != 0) { - cd_outb(iobase, CD1400_RBPR, idivisor); - cd_outb(iobase, CD1400_RCOR, iprescaler); + cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor); + cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler); } if (odivisor != 0) { - cd_outb(iobase, CD1400_TBPR, odivisor); - cd_outb(iobase, CD1400_TCOR, oprescaler); + cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor); + cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler); } /* @@ -1694,20 +1726,20 @@ comparam(tp, t) | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); if (opt != com->channel_control) { com->channel_control = opt; - cd1400_channel_cmd(iobase, opt); + cd1400_channel_cmd(iobase, opt, com->cy_align); } #ifdef Smarts /* set special chars */ /* XXX if one is _POSIX_VDISABLE, can't use some others */ 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) - 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) - 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) - cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]); #endif /* @@ -1754,14 +1786,14 @@ comparam(tp, t) cor_change = 0; if (opt != com->cor[0]) { 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). */ if (t->c_ispeed == 0) - itimeout = cd_inb(iobase, CD1400_RTPR); + itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align); else { itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; #ifdef SOFT_HOTCHAR @@ -1777,7 +1809,7 @@ comparam(tp, t) itimeout = t->c_cc[VTIME] * 10; if (itimeout > 255) itimeout = 255; - cd_outb(iobase, CD1400_RTPR, itimeout); + cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout); /* * set channel option register 2 - @@ -1796,7 +1828,7 @@ comparam(tp, t) #endif if (opt != com->cor[1]) { 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 if (opt != com->cor[2]) { 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 */ 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 - @@ -1858,7 +1890,7 @@ comparam(tp, t) #else opt |= CD1400_COR4_PFO_EXCEPTION; #endif - cd_outb(iobase, CD1400_COR4, opt); + cd_outb(iobase, CD1400_COR4, com->cy_align, opt); /* * set channel option register 5 - @@ -1875,7 +1907,7 @@ comparam(tp, t) if (t->c_oflag & OCRNL) opt |= CD1400_COR5_OCRNL; #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 @@ -1892,7 +1924,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR1_CTSzd; #endif - cd_outb(iobase, CD1400_MCOR1, opt); + cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt); /* * set modem change option register 2 @@ -1903,7 +1935,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR2_CTSod; #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 @@ -1946,11 +1978,11 @@ comparam(tp, t) #endif if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 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); } else { 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); } @@ -1982,17 +2014,17 @@ comstart(tp) #endif 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) { com->state &= ~CS_TTGO; 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); } else { com->state |= CS_TTGO; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) && !(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); } if (tp->t_state & TS_TBLOCK) { @@ -2000,7 +2032,7 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image &= ~MCR_RTS); #endif } else { @@ -2013,7 +2045,7 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image |= MCR_RTS); #endif } @@ -2048,7 +2080,7 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } @@ -2076,7 +2108,7 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } @@ -2182,18 +2214,18 @@ commctl(com, bits, how) switch (how) { case DMSET: com->mcr_image = mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIS: com->mcr_image = mcr = com->mcr_image | mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIC: com->mcr_image = mcr = com->mcr_image & ~mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; } enable_intr(); @@ -2331,17 +2363,17 @@ disc_optim(tp, t, com) com->hotchar = 0; #ifndef SOFT_HOTCHAR 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; if (com->hotchar != 0) { - cd_outb(iobase, CD1400_SCHR3, com->hotchar); - cd_outb(iobase, CD1400_SCHR4, com->hotchar); + cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar); opt |= CD1400_COR3_SCD34; } 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_CCR_CMDCORCHG | CD1400_CCR_COR3); + CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, com->cy_align); } #endif } @@ -2405,9 +2437,10 @@ comspeed(speed, prescaler_io) } static void -cd1400_channel_cmd(iobase, cmd) +cd1400_channel_cmd(iobase, cmd, cy_align) cy_addr iobase; int cmd; + int cy_align; { /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, 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 */ /* 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) log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", 5 * 8 * 1024); - cd_outb(iobase, CD1400_CCR, cmd); + cd_outb(iobase, CD1400_CCR, cy_align, cmd); } #ifdef CyDebug @@ -2448,7 +2481,7 @@ cystatus(unit) iobase = com->iobase; printf("\n"); 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 cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", com->cor[0], com->cor[1], com->cor[2]); diff --git a/sys/dev/cy/cy_isa.c b/sys/dev/cy/cy_isa.c index 1346042..4634f4b 100644 --- a/sys/dev/cy/cy_isa.c +++ b/sys/dev/cy/cy_isa.c @@ -27,7 +27,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * 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" @@ -141,7 +141,7 @@ /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ #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 RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) @@ -153,7 +153,8 @@ #define CONTROL_LOCK_STATE 0x40 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) #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. @@ -262,6 +263,7 @@ struct com_s { cy_addr cy_iobase; /* base address of this port's cyclom */ cy_addr iobase; /* base address of this port's cd1400 */ + int cy_align; /* index for register alignment */ struct tty *tp; /* cross reference */ @@ -330,8 +332,10 @@ void siopoll __P((void)); #define siommap nommap #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 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 void comhardclose __P((struct com_s *com)); #if 0 @@ -399,6 +403,7 @@ static u_int cy_timeouts; #endif static int cy_nr_cd1400s[NCY]; +static int cy_total_devices; #undef RxFifoThreshold static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); static int cy_chip_offset[] = { @@ -416,16 +421,9 @@ static int sioprobe(dev) struct isa_device *dev; { - int cyu; - u_char firmware_version; cy_addr iobase; - int unit; 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) */ cy_inb(iobase, CY16_RESET); /* XXX? */ @@ -435,22 +433,34 @@ sioprobe(dev) cy_outb(iobase, CY_CLEAR_INTR, 0); 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) { 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 */ for (i = 0; i < 10; i++) { DELAY(50); - if (!cd_inb(iobase, CD1400_CCR)) + if (!cd_inb(iobase, CD1400_CCR, cy_align)) break; } /* clear the GFRCR register */ - cd_outb(iobase, CD1400_GFRCR, 0); + cd_outb(iobase, CD1400_GFRCR, cy_align, 0); /* issue a reset command */ - cd_outb(iobase, CD1400_CCR, + cd_outb(iobase, CD1400_CCR, cy_align, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for the CD1400 to initialize itself */ @@ -458,7 +468,7 @@ sioprobe(dev) DELAY(50); /* retrieve firmware version */ - firmware_version = cd_inb(iobase, CD1400_GFRCR); + firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); if ((firmware_version & 0xf0) == 0x40) break; } @@ -470,38 +480,60 @@ sioprobe(dev) */ if ((firmware_version & 0xf0) != 0x40) break; - ++cy_nr_cd1400s[unit]; } - return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); + return (cyu); } static int sioattach(isdp) - struct isa_device *isdp; + struct isa_device *isdp; { - int cyu; - cy_addr cy_iobase; - dev_t dev; - cy_addr iobase; - int ncyu; - int unit; + int adapter; - unit = isdp->id_unit; - if ((u_int)unit >= NCY) - return (0); - ncyu = cy_nr_cd1400s[unit]; - if (ncyu == 0) + adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); + if (adapter < 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; + return (1); +} - cy_iobase = (cy_addr)isdp->id_maddr; - unit *= CY_MAX_PORTS; +int +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) { 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. */ - cd_outb(iobase, CD1400_PPR, + cd_outb(iobase, CD1400_PPR, cy_align, howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { @@ -522,6 +554,7 @@ sioattach(isdp) com->cy_iobase = cy_iobase; com->iobase = iobase; + com->cy_align = cy_align; /* * 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 */ - cy_outb(cy_iobase, CY_CLEAR_INTR, 0); + cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - return (1); + return (adapter); } static int @@ -664,8 +697,8 @@ open_top: iobase = com->iobase; /* reset this channel */ - cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); - cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); + cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align); /* * Resetting disables the transmitter and receiver as well as @@ -677,7 +710,7 @@ open_top: com->channel_control = 0; /* 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); /* @@ -732,8 +765,8 @@ open_top: (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); disable_intr(); com->prev_modem_status = com->last_modem_status - = cd_inb(iobase, CD1400_MSVR2); - cd_outb(iobase, CD1400_SRER, + = cd_inb(iobase, CD1400_MSVR2, com->cy_align); + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); enable_intr(); @@ -827,7 +860,7 @@ comhardclose(com) com->poll_output = FALSE; #endif 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 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); #endif @@ -837,7 +870,7 @@ comhardclose(com) outb(iobase + com_ier, 0); #else 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(); #endif tp = com->tp; @@ -859,7 +892,7 @@ comhardclose(com) com->channel_control = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | 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) { timeout(siodtrwakeup, com, com->dtr_wait); @@ -948,20 +981,19 @@ void siointr(unit) int unit; { - int baseu; - cy_addr cy_iobase; - int cyu; - cy_addr iobase; - u_char status; + cy_addr cy_iobase, iobase; + int baseu, cyu, cy_align; + u_char status; baseu = unit * CY_MAX_PORTS; cy_iobase = com_addr(baseu)->cy_iobase; + cy_align = com_addr(baseu)->cy_align; /* check each CD1400 in turn */ 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 */ - status = cd_inb(iobase, CD1400_SVRR); + status = cd_inb(iobase, CD1400_SVRR, cy_align); if (status == 0) continue; #ifdef CyDebug @@ -981,13 +1013,13 @@ siointr(unit) #endif #ifdef PollMode - save_rir = cd_inb(iobase, CD1400_RIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_rir = cd_inb(iobase, CD1400_RIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* 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 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) & CD1400_xIVR_CHAN)); @@ -1002,9 +1034,9 @@ siointr(unit) if (serv_type & CD1400_RIVR_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? */ - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifndef SOFT_HOTCHAR if (line_status & CD1400_RDSR_SPECIAL && com->hotchar != 0) @@ -1053,7 +1085,7 @@ siointr(unit) outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, cy_align, com->mcr_image &= ~MCR_RTS); #endif if (line_status & LSR_OE) @@ -1063,7 +1095,7 @@ siointr(unit) } else { int ifree; - count = cd_inb(iobase, CD1400_RDCR); + count = cd_inb(iobase, CD1400_RDCR, cy_align); com->bytes_in += count; ioptr = com->iptr; ifree = com->ibufend - ioptr; @@ -1075,7 +1107,7 @@ siointr(unit) microtime(&com->timestamp); do { recv_data = cd_inb(iobase, - CD1400_RDSR); + CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data @@ -1090,7 +1122,7 @@ siointr(unit) com->delta_error_counts [CE_INTERRUPT_BUF_OVERFLOW] += count; do { - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data == com->hotchar) @@ -1107,12 +1139,12 @@ siointr(unit) outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, cy_align, com->mcr_image &= ~MCR_RTS); #endif com_events += count; do { - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data == com->hotchar) @@ -1129,12 +1161,12 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_RIR, + cd_outb(iobase, CD1400_RIR, cy_align, save_rir & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } if (status & CD1400_SVRR_MDMCH) { @@ -1148,11 +1180,11 @@ cont: #endif #ifdef PollMode - save_mir = cd_inb(iobase, CD1400_MIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_mir = cd_inb(iobase, CD1400_MIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* 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 + (save_mir & CD1400_MIR_CHAN)); @@ -1165,7 +1197,7 @@ cont: & CD1400_xIVR_CHAN)); #endif ++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 (com->do_dcd_timestamp && !(com->last_modem_status & MSR_DCD) @@ -1194,13 +1226,13 @@ cont: | CS_ODEVREADY) && !(com->intr_enable & CD1400_SRER_TXRDY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } else { com->state &= ~CS_ODEVREADY; if (com->intr_enable & CD1400_SRER_TXRDY) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable &= ~CD1400_SRER_TXRDY); } @@ -1210,12 +1242,12 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_MIR, + cd_outb(iobase, CD1400_MIR, cy_align, save_mir & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } if (status & CD1400_SVRR_TXRDY) { @@ -1228,11 +1260,11 @@ cont: #endif #ifdef PollMode - save_tir = cd_inb(iobase, CD1400_TIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_tir = cd_inb(iobase, CD1400_TIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* enter tx service */ - cd_outb(iobase, CD1400_CAR, save_tir); + cd_outb(iobase, CD1400_CAR, cy_align, save_tir); com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS + (save_tir & CD1400_TIR_CHAN)); @@ -1255,7 +1287,7 @@ cont: ocount = CD1400_TX_FIFO_SIZE; com->bytes_out += ocount; do - cd_outb(iobase, CD1400_TDR, *ioptr++); + cd_outb(iobase, CD1400_TDR, cy_align, *ioptr++); while (--ocount != 0); com->obufq.l_head = ioptr; if (ioptr >= com->obufq.l_tail) { @@ -1271,7 +1303,7 @@ cont: } else { /* output just completed */ com->state &= ~CS_BUSY; - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable &= ~CD1400_SRER_TXRDY); } @@ -1285,18 +1317,18 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_TIR, + cd_outb(iobase, CD1400_TIR, cy_align, save_tir & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } } /* 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(); } @@ -1406,7 +1438,7 @@ sioioctl(dev, cmd, data, flag, p) splx(s); 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) { #if 0 case TIOCSBRK: @@ -1544,9 +1576,9 @@ repeat: com->mcr_image |= MCR_RTS); #else iobase = com->iobase, - cd_outb(iobase, CD1400_CAR, + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN), - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image |= MCR_RTS); #endif enable_intr(); @@ -1669,19 +1701,19 @@ comparam(tp, t) com = com_addr(unit); iobase = com->iobase; 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) (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ else (void)commctl(com, TIOCM_DTR, DMBIS); if (idivisor != 0) { - cd_outb(iobase, CD1400_RBPR, idivisor); - cd_outb(iobase, CD1400_RCOR, iprescaler); + cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor); + cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler); } if (odivisor != 0) { - cd_outb(iobase, CD1400_TBPR, odivisor); - cd_outb(iobase, CD1400_TCOR, oprescaler); + cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor); + cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler); } /* @@ -1694,20 +1726,20 @@ comparam(tp, t) | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); if (opt != com->channel_control) { com->channel_control = opt; - cd1400_channel_cmd(iobase, opt); + cd1400_channel_cmd(iobase, opt, com->cy_align); } #ifdef Smarts /* set special chars */ /* XXX if one is _POSIX_VDISABLE, can't use some others */ 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) - 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) - 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) - cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]); #endif /* @@ -1754,14 +1786,14 @@ comparam(tp, t) cor_change = 0; if (opt != com->cor[0]) { 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). */ if (t->c_ispeed == 0) - itimeout = cd_inb(iobase, CD1400_RTPR); + itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align); else { itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; #ifdef SOFT_HOTCHAR @@ -1777,7 +1809,7 @@ comparam(tp, t) itimeout = t->c_cc[VTIME] * 10; if (itimeout > 255) itimeout = 255; - cd_outb(iobase, CD1400_RTPR, itimeout); + cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout); /* * set channel option register 2 - @@ -1796,7 +1828,7 @@ comparam(tp, t) #endif if (opt != com->cor[1]) { 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 if (opt != com->cor[2]) { 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 */ 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 - @@ -1858,7 +1890,7 @@ comparam(tp, t) #else opt |= CD1400_COR4_PFO_EXCEPTION; #endif - cd_outb(iobase, CD1400_COR4, opt); + cd_outb(iobase, CD1400_COR4, com->cy_align, opt); /* * set channel option register 5 - @@ -1875,7 +1907,7 @@ comparam(tp, t) if (t->c_oflag & OCRNL) opt |= CD1400_COR5_OCRNL; #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 @@ -1892,7 +1924,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR1_CTSzd; #endif - cd_outb(iobase, CD1400_MCOR1, opt); + cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt); /* * set modem change option register 2 @@ -1903,7 +1935,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR2_CTSod; #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 @@ -1946,11 +1978,11 @@ comparam(tp, t) #endif if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 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); } else { 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); } @@ -1982,17 +2014,17 @@ comstart(tp) #endif 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) { com->state &= ~CS_TTGO; 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); } else { com->state |= CS_TTGO; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) && !(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); } if (tp->t_state & TS_TBLOCK) { @@ -2000,7 +2032,7 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image &= ~MCR_RTS); #endif } else { @@ -2013,7 +2045,7 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image |= MCR_RTS); #endif } @@ -2048,7 +2080,7 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } @@ -2076,7 +2108,7 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } @@ -2182,18 +2214,18 @@ commctl(com, bits, how) switch (how) { case DMSET: com->mcr_image = mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIS: com->mcr_image = mcr = com->mcr_image | mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIC: com->mcr_image = mcr = com->mcr_image & ~mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; } enable_intr(); @@ -2331,17 +2363,17 @@ disc_optim(tp, t, com) com->hotchar = 0; #ifndef SOFT_HOTCHAR 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; if (com->hotchar != 0) { - cd_outb(iobase, CD1400_SCHR3, com->hotchar); - cd_outb(iobase, CD1400_SCHR4, com->hotchar); + cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar); opt |= CD1400_COR3_SCD34; } 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_CCR_CMDCORCHG | CD1400_CCR_COR3); + CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, com->cy_align); } #endif } @@ -2405,9 +2437,10 @@ comspeed(speed, prescaler_io) } static void -cd1400_channel_cmd(iobase, cmd) +cd1400_channel_cmd(iobase, cmd, cy_align) cy_addr iobase; int cmd; + int cy_align; { /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, 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 */ /* 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) log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", 5 * 8 * 1024); - cd_outb(iobase, CD1400_CCR, cmd); + cd_outb(iobase, CD1400_CCR, cy_align, cmd); } #ifdef CyDebug @@ -2448,7 +2481,7 @@ cystatus(unit) iobase = com->iobase; printf("\n"); 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 cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", com->cor[0], com->cor[1], com->cor[2]); diff --git a/sys/dev/cy/cy_pci.c b/sys/dev/cy/cy_pci.c new file mode 100644 index 0000000..d9bbd72 --- /dev/null +++ b/sys/dev/cy/cy_pci.c @@ -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 */ diff --git a/sys/dev/cy/cyreg.h b/sys/dev/cy/cyreg.h index 1676654..7f3c015 100644 --- a/sys/dev/cy/cyreg.h +++ b/sys/dev/cy/cyreg.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * 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_SVCACKT 0x200 #define CY8_SVCACKM 0x300 -#define CY_CD1400_MEMSIZE 0x400 -#define CY16_RESET 0x1400 -#define CY_CLEAR_INTR 0x1800 /* intr ack address */ +#define CY16_RESET 0x0a00 +#define CY_CLEAR_INTR 0x0c00 /* intr ack address */ #define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ #define CY_CLOCK 25000000 /* baud rate clock */ #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 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))) #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 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))) #endif diff --git a/sys/i386/isa/cy.c b/sys/i386/isa/cy.c index 1346042..4634f4b 100644 --- a/sys/i386/isa/cy.c +++ b/sys/i386/isa/cy.c @@ -27,7 +27,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * 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" @@ -141,7 +141,7 @@ /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ #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 RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) @@ -153,7 +153,8 @@ #define CONTROL_LOCK_STATE 0x40 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) #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. @@ -262,6 +263,7 @@ struct com_s { cy_addr cy_iobase; /* base address of this port's cyclom */ cy_addr iobase; /* base address of this port's cd1400 */ + int cy_align; /* index for register alignment */ struct tty *tp; /* cross reference */ @@ -330,8 +332,10 @@ void siopoll __P((void)); #define siommap nommap #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 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 void comhardclose __P((struct com_s *com)); #if 0 @@ -399,6 +403,7 @@ static u_int cy_timeouts; #endif static int cy_nr_cd1400s[NCY]; +static int cy_total_devices; #undef RxFifoThreshold static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); static int cy_chip_offset[] = { @@ -416,16 +421,9 @@ static int sioprobe(dev) struct isa_device *dev; { - int cyu; - u_char firmware_version; cy_addr iobase; - int unit; 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) */ cy_inb(iobase, CY16_RESET); /* XXX? */ @@ -435,22 +433,34 @@ sioprobe(dev) cy_outb(iobase, CY_CLEAR_INTR, 0); 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) { 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 */ for (i = 0; i < 10; i++) { DELAY(50); - if (!cd_inb(iobase, CD1400_CCR)) + if (!cd_inb(iobase, CD1400_CCR, cy_align)) break; } /* clear the GFRCR register */ - cd_outb(iobase, CD1400_GFRCR, 0); + cd_outb(iobase, CD1400_GFRCR, cy_align, 0); /* issue a reset command */ - cd_outb(iobase, CD1400_CCR, + cd_outb(iobase, CD1400_CCR, cy_align, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for the CD1400 to initialize itself */ @@ -458,7 +468,7 @@ sioprobe(dev) DELAY(50); /* retrieve firmware version */ - firmware_version = cd_inb(iobase, CD1400_GFRCR); + firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); if ((firmware_version & 0xf0) == 0x40) break; } @@ -470,38 +480,60 @@ sioprobe(dev) */ if ((firmware_version & 0xf0) != 0x40) break; - ++cy_nr_cd1400s[unit]; } - return (cy_nr_cd1400s[unit] == 0 ? 0 : -1); + return (cyu); } static int sioattach(isdp) - struct isa_device *isdp; + struct isa_device *isdp; { - int cyu; - cy_addr cy_iobase; - dev_t dev; - cy_addr iobase; - int ncyu; - int unit; + int adapter; - unit = isdp->id_unit; - if ((u_int)unit >= NCY) - return (0); - ncyu = cy_nr_cd1400s[unit]; - if (ncyu == 0) + adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); + if (adapter < 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; + return (1); +} - cy_iobase = (cy_addr)isdp->id_maddr; - unit *= CY_MAX_PORTS; +int +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) { 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. */ - cd_outb(iobase, CD1400_PPR, + cd_outb(iobase, CD1400_PPR, cy_align, howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000)); for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { @@ -522,6 +554,7 @@ sioattach(isdp) com->cy_iobase = cy_iobase; com->iobase = iobase; + com->cy_align = cy_align; /* * 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 */ - cy_outb(cy_iobase, CY_CLEAR_INTR, 0); + cd_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - return (1); + return (adapter); } static int @@ -664,8 +697,8 @@ open_top: iobase = com->iobase; /* reset this channel */ - cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN); - cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET); + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN); + cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET, com->cy_align); /* * Resetting disables the transmitter and receiver as well as @@ -677,7 +710,7 @@ open_top: com->channel_control = 0; /* 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); /* @@ -732,8 +765,8 @@ open_top: (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); disable_intr(); com->prev_modem_status = com->last_modem_status - = cd_inb(iobase, CD1400_MSVR2); - cd_outb(iobase, CD1400_SRER, + = cd_inb(iobase, CD1400_MSVR2, com->cy_align); + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); enable_intr(); @@ -827,7 +860,7 @@ comhardclose(com) com->poll_output = FALSE; #endif 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 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); #endif @@ -837,7 +870,7 @@ comhardclose(com) outb(iobase + com_ier, 0); #else 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(); #endif tp = com->tp; @@ -859,7 +892,7 @@ comhardclose(com) com->channel_control = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN | 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) { timeout(siodtrwakeup, com, com->dtr_wait); @@ -948,20 +981,19 @@ void siointr(unit) int unit; { - int baseu; - cy_addr cy_iobase; - int cyu; - cy_addr iobase; - u_char status; + cy_addr cy_iobase, iobase; + int baseu, cyu, cy_align; + u_char status; baseu = unit * CY_MAX_PORTS; cy_iobase = com_addr(baseu)->cy_iobase; + cy_align = com_addr(baseu)->cy_align; /* check each CD1400 in turn */ 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 */ - status = cd_inb(iobase, CD1400_SVRR); + status = cd_inb(iobase, CD1400_SVRR, cy_align); if (status == 0) continue; #ifdef CyDebug @@ -981,13 +1013,13 @@ siointr(unit) #endif #ifdef PollMode - save_rir = cd_inb(iobase, CD1400_RIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_rir = cd_inb(iobase, CD1400_RIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* 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 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) & CD1400_xIVR_CHAN)); @@ -1002,9 +1034,9 @@ siointr(unit) if (serv_type & CD1400_RIVR_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? */ - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifndef SOFT_HOTCHAR if (line_status & CD1400_RDSR_SPECIAL && com->hotchar != 0) @@ -1053,7 +1085,7 @@ siointr(unit) outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, cy_align, com->mcr_image &= ~MCR_RTS); #endif if (line_status & LSR_OE) @@ -1063,7 +1095,7 @@ siointr(unit) } else { int ifree; - count = cd_inb(iobase, CD1400_RDCR); + count = cd_inb(iobase, CD1400_RDCR, cy_align); com->bytes_in += count; ioptr = com->iptr; ifree = com->ibufend - ioptr; @@ -1075,7 +1107,7 @@ siointr(unit) microtime(&com->timestamp); do { recv_data = cd_inb(iobase, - CD1400_RDSR); + CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data @@ -1090,7 +1122,7 @@ siointr(unit) com->delta_error_counts [CE_INTERRUPT_BUF_OVERFLOW] += count; do { - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data == com->hotchar) @@ -1107,12 +1139,12 @@ siointr(unit) outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, cy_align, com->mcr_image &= ~MCR_RTS); #endif com_events += count; do { - recv_data = cd_inb(iobase, CD1400_RDSR); + recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); #ifdef SOFT_HOTCHAR if (com->hotchar != 0 && recv_data == com->hotchar) @@ -1129,12 +1161,12 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_RIR, + cd_outb(iobase, CD1400_RIR, cy_align, save_rir & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } if (status & CD1400_SVRR_MDMCH) { @@ -1148,11 +1180,11 @@ cont: #endif #ifdef PollMode - save_mir = cd_inb(iobase, CD1400_MIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_mir = cd_inb(iobase, CD1400_MIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* 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 + (save_mir & CD1400_MIR_CHAN)); @@ -1165,7 +1197,7 @@ cont: & CD1400_xIVR_CHAN)); #endif ++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 (com->do_dcd_timestamp && !(com->last_modem_status & MSR_DCD) @@ -1194,13 +1226,13 @@ cont: | CS_ODEVREADY) && !(com->intr_enable & CD1400_SRER_TXRDY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } else { com->state &= ~CS_ODEVREADY; if (com->intr_enable & CD1400_SRER_TXRDY) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable &= ~CD1400_SRER_TXRDY); } @@ -1210,12 +1242,12 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_MIR, + cd_outb(iobase, CD1400_MIR, cy_align, save_mir & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } if (status & CD1400_SVRR_TXRDY) { @@ -1228,11 +1260,11 @@ cont: #endif #ifdef PollMode - save_tir = cd_inb(iobase, CD1400_TIR); - save_car = cd_inb(iobase, CD1400_CAR); + save_tir = cd_inb(iobase, CD1400_TIR, cy_align); + save_car = cd_inb(iobase, CD1400_CAR, cy_align); /* enter tx service */ - cd_outb(iobase, CD1400_CAR, save_tir); + cd_outb(iobase, CD1400_CAR, cy_align, save_tir); com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS + (save_tir & CD1400_TIR_CHAN)); @@ -1255,7 +1287,7 @@ cont: ocount = CD1400_TX_FIFO_SIZE; com->bytes_out += ocount; do - cd_outb(iobase, CD1400_TDR, *ioptr++); + cd_outb(iobase, CD1400_TDR, cy_align, *ioptr++); while (--ocount != 0); com->obufq.l_head = ioptr; if (ioptr >= com->obufq.l_tail) { @@ -1271,7 +1303,7 @@ cont: } else { /* output just completed */ com->state &= ~CS_BUSY; - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, cy_align, com->intr_enable &= ~CD1400_SRER_TXRDY); } @@ -1285,18 +1317,18 @@ cont: /* terminate service context */ #ifdef PollMode - cd_outb(iobase, CD1400_TIR, + cd_outb(iobase, CD1400_TIR, cy_align, save_tir & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); - cd_outb(iobase, CD1400_CAR, save_car); + cd_outb(iobase, CD1400_CAR, cy_align, save_car); #else - cd_outb(iobase, CD1400_EOSRR, 0); + cd_outb(iobase, CD1400_EOSRR, cy_align, 0); #endif } } /* 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(); } @@ -1406,7 +1438,7 @@ sioioctl(dev, cmd, data, flag, p) splx(s); 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) { #if 0 case TIOCSBRK: @@ -1544,9 +1576,9 @@ repeat: com->mcr_image |= MCR_RTS); #else iobase = com->iobase, - cd_outb(iobase, CD1400_CAR, + cd_outb(iobase, CD1400_CAR, com->cy_align, unit & CD1400_CAR_CHAN), - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image |= MCR_RTS); #endif enable_intr(); @@ -1669,19 +1701,19 @@ comparam(tp, t) com = com_addr(unit); iobase = com->iobase; 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) (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ else (void)commctl(com, TIOCM_DTR, DMBIS); if (idivisor != 0) { - cd_outb(iobase, CD1400_RBPR, idivisor); - cd_outb(iobase, CD1400_RCOR, iprescaler); + cd_outb(iobase, CD1400_RBPR, com->cy_align, idivisor); + cd_outb(iobase, CD1400_RCOR, com->cy_align, iprescaler); } if (odivisor != 0) { - cd_outb(iobase, CD1400_TBPR, odivisor); - cd_outb(iobase, CD1400_TCOR, oprescaler); + cd_outb(iobase, CD1400_TBPR, com->cy_align, odivisor); + cd_outb(iobase, CD1400_TCOR, com->cy_align, oprescaler); } /* @@ -1694,20 +1726,20 @@ comparam(tp, t) | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); if (opt != com->channel_control) { com->channel_control = opt; - cd1400_channel_cmd(iobase, opt); + cd1400_channel_cmd(iobase, opt, com->cy_align); } #ifdef Smarts /* set special chars */ /* XXX if one is _POSIX_VDISABLE, can't use some others */ 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) - 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) - 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) - cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, t->c_cc[VSUSP]); #endif /* @@ -1754,14 +1786,14 @@ comparam(tp, t) cor_change = 0; if (opt != com->cor[0]) { 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). */ if (t->c_ispeed == 0) - itimeout = cd_inb(iobase, CD1400_RTPR); + itimeout = cd_inb(iobase, CD1400_RTPR, com->cy_align); else { itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; #ifdef SOFT_HOTCHAR @@ -1777,7 +1809,7 @@ comparam(tp, t) itimeout = t->c_cc[VTIME] * 10; if (itimeout > 255) itimeout = 255; - cd_outb(iobase, CD1400_RTPR, itimeout); + cd_outb(iobase, CD1400_RTPR, com->cy_align, itimeout); /* * set channel option register 2 - @@ -1796,7 +1828,7 @@ comparam(tp, t) #endif if (opt != com->cor[1]) { 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 if (opt != com->cor[2]) { 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 */ 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 - @@ -1858,7 +1890,7 @@ comparam(tp, t) #else opt |= CD1400_COR4_PFO_EXCEPTION; #endif - cd_outb(iobase, CD1400_COR4, opt); + cd_outb(iobase, CD1400_COR4, com->cy_align, opt); /* * set channel option register 5 - @@ -1875,7 +1907,7 @@ comparam(tp, t) if (t->c_oflag & OCRNL) opt |= CD1400_COR5_OCRNL; #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 @@ -1892,7 +1924,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR1_CTSzd; #endif - cd_outb(iobase, CD1400_MCOR1, opt); + cd_outb(iobase, CD1400_MCOR1, com->cy_align, opt); /* * set modem change option register 2 @@ -1903,7 +1935,7 @@ comparam(tp, t) if (cflag & CCTS_OFLOW) opt |= CD1400_MCOR2_CTSod; #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 @@ -1946,11 +1978,11 @@ comparam(tp, t) #endif if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 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); } else { 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); } @@ -1982,17 +2014,17 @@ comstart(tp) #endif 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) { com->state &= ~CS_TTGO; 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); } else { com->state |= CS_TTGO; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) && !(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); } if (tp->t_state & TS_TBLOCK) { @@ -2000,7 +2032,7 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image &= ~MCR_RTS); #endif } else { @@ -2013,7 +2045,7 @@ comstart(tp) #if 0 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); #else - cd_outb(iobase, CD1400_MSVR1, + cd_outb(iobase, CD1400_MSVR1, com->cy_align, com->mcr_image |= MCR_RTS); #endif } @@ -2048,7 +2080,7 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } @@ -2076,7 +2108,7 @@ comstart(tp) com->state |= CS_BUSY; if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - cd_outb(iobase, CD1400_SRER, + cd_outb(iobase, CD1400_SRER, com->cy_align, com->intr_enable |= CD1400_SRER_TXRDY); } @@ -2182,18 +2214,18 @@ commctl(com, bits, how) switch (how) { case DMSET: com->mcr_image = mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIS: com->mcr_image = mcr = com->mcr_image | mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; case DMBIC: com->mcr_image = mcr = com->mcr_image & ~mcr; - cd_outb(iobase, CD1400_MSVR1, mcr); - cd_outb(iobase, CD1400_MSVR2, mcr); + cd_outb(iobase, CD1400_MSVR1, com->cy_align, mcr); + cd_outb(iobase, CD1400_MSVR2, com->cy_align, mcr); break; } enable_intr(); @@ -2331,17 +2363,17 @@ disc_optim(tp, t, com) com->hotchar = 0; #ifndef SOFT_HOTCHAR 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; if (com->hotchar != 0) { - cd_outb(iobase, CD1400_SCHR3, com->hotchar); - cd_outb(iobase, CD1400_SCHR4, com->hotchar); + cd_outb(iobase, CD1400_SCHR3, com->cy_align, com->hotchar); + cd_outb(iobase, CD1400_SCHR4, com->cy_align, com->hotchar); opt |= CD1400_COR3_SCD34; } 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_CCR_CMDCORCHG | CD1400_CCR_COR3); + CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3, com->cy_align); } #endif } @@ -2405,9 +2437,10 @@ comspeed(speed, prescaler_io) } static void -cd1400_channel_cmd(iobase, cmd) +cd1400_channel_cmd(iobase, cmd, cy_align) cy_addr iobase; int cmd; + int cy_align; { /* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed, 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 */ /* 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) log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n", 5 * 8 * 1024); - cd_outb(iobase, CD1400_CCR, cmd); + cd_outb(iobase, CD1400_CCR, cy_align, cmd); } #ifdef CyDebug @@ -2448,7 +2481,7 @@ cystatus(unit) iobase = com->iobase; printf("\n"); 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 cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", com->cor[0], com->cor[1], com->cor[2]); diff --git a/sys/i386/isa/cyreg.h b/sys/i386/isa/cyreg.h index 1676654..7f3c015 100644 --- a/sys/i386/isa/cyreg.h +++ b/sys/i386/isa/cyreg.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * 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_SVCACKT 0x200 #define CY8_SVCACKM 0x300 -#define CY_CD1400_MEMSIZE 0x400 -#define CY16_RESET 0x1400 -#define CY_CLEAR_INTR 0x1800 /* intr ack address */ +#define CY16_RESET 0x0a00 +#define CY_CLEAR_INTR 0x0c00 /* intr ack address */ #define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ #define CY_CLOCK 25000000 /* baud rate clock */ #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 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))) #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 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))) #endif diff --git a/sys/pci/cy_pci.c b/sys/pci/cy_pci.c new file mode 100644 index 0000000..d9bbd72 --- /dev/null +++ b/sys/pci/cy_pci.c @@ -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 */ diff --git a/sys/pci/cy_pcireg.h b/sys/pci/cy_pcireg.h new file mode 100644 index 0000000..412622f --- /dev/null +++ b/sys/pci/cy_pcireg.h @@ -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 |