summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorhvozda <hvozda@cvs.openbsd.org>1996-04-29 14:17:54 +0000
committerhvozda <hvozda@cvs.openbsd.org>1996-04-29 14:17:54 +0000
commit7a9ddc83f934914d39af72bf24b67290a9e5700f (patch)
treed4e40de8eec73b77be31c346455984224213ff31 /sys/dev/ic
parentfdecada6f88b495c1afc81ad3a15c0cedffa2338 (diff)
Pull in John Kohl's [jtk@netbsd.org] most recent (15Apr96) APM and PCMCIA work
(original PCMCIA framework by Stefan Grefen [grefen@convex.com]).
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/com.c312
-rw-r--r--sys/dev/ic/i82365reg.h29
2 files changed, 298 insertions, 43 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 77dd24748f4..5570f7ef424 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com.c,v 1.11 1996/04/21 22:23:15 deraadt Exp $ */
+/* $OpenBSD: com.c,v 1.12 1996/04/29 14:16:15 hvozda Exp $ */
/* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
/*-
@@ -81,6 +81,7 @@
struct com_softc {
struct device sc_dev;
void *sc_ih;
+ bus_chipset_tag_t sc_bc;
struct tty *sc_tty;
int sc_overflows;
@@ -94,7 +95,6 @@ struct com_softc {
int sc_hayespbase;
#endif
- bus_chipset_tag_t sc_bc;
bus_io_handle_t sc_ioh;
bus_io_handle_t sc_hayespioh;
@@ -102,6 +102,9 @@ struct com_softc {
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
#define COM_HW_HAYESP 0x04
+#define COM_HW_ABSENT_PENDING 0x08 /* reattached, awaiting close/reopen */
+#define COM_HW_ABSENT 0x10 /* configure actually failed, or removed */
+#define COM_HW_REATTACH 0x20 /* reattaching */
#define COM_HW_CONSOLE 0x40
u_char sc_swflags;
#define COM_SW_SOFTCAR 0x01
@@ -125,6 +128,8 @@ int comintr __P((void *));
void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
+void com_absent_notify __P((struct com_softc *sc));
+void comstart_pending __P((void *arg));
/*
* XXX the following two cfattach structs should be different, and possibly
@@ -145,12 +150,17 @@ struct cfattach com_commulti_ca = {
};
#endif
+
struct cfdriver com_cd = {
NULL, "com", DV_TTY
};
int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+#ifndef CONSPEED
+#define CONSPEED B9600
+#endif
+
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED; /* XXX why set default? */
#else
@@ -181,49 +191,201 @@ extern int kgdb_debug_init;
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-/*#include "pcmciabus.h"*/
-#if NPCMCIABUS >0
+#if NCOM_PCMCIA
+#include <dev/pcmcia/pcmciavar.h>
+
+int com_pcmcia_match __P((struct device *, void *, void *));
+void com_pcmcia_attach __P((struct device *, struct device *, void *));
+int com_pcmcia_detach __P((struct device *));
+
+struct cfattach com_pcmcia_ca = {
+ sizeof(struct com_softc), com_pcmcia_match, comattach,
+ com_pcmcia_detach
+};
+
+int
+com_pcmcia_mod __P((struct pcmcia_link *pc_link,
+ struct device *self,
+ struct pcmcia_conf *pc_cf,
+ struct cfdata *cf));
+
/* additional setup needed for pcmcia devices */
-#include <dev/pcmcia/pcmciabus.h>
/* modify config entry */
-static int
-commod(pc_link,self,pc_cf,cf)
+int
+com_pcmcia_mod(pc_link, self, pc_cf, cf)
struct pcmcia_link *pc_link;
struct device *self;
struct pcmcia_conf *pc_cf;
struct cfdata *cf;
{
int err;
- struct pcmciadevs *dev=pc_link->device;
+ struct pcmciadevs *dev = pc_link->device;
struct ed_softc *sc = (void *)self;
- if(!(err=pc_link->adapter->bus_link->bus_config(pc_link,self,pc_cf,cf))) {
- pc_cf->memwin=0;
- if(pc_cf->cfgtype==0)
- pc_cf->cfgtype=CFGENTRYID; /* determine from ioaddr */
+ if (!(err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self,
+ pc_cf, cf))) {
+ pc_cf->memwin = 0;
+ if (pc_cf->cfgtype == 0)
+ pc_cf->cfgtype = CFGENTRYID; /* determine from ioaddr */
}
return err;
}
+
+int com_pcmcia_isa_attach __P((struct device *, void *, void *,
+ struct pcmcia_link *));
+int com_pcmcia_remove __P((struct pcmcia_link *, struct device *));
+
static struct pcmcia_com {
struct pcmcia_device pcd;
-} pcmcia_com= {
- "PCMCIA Modem card",commod,NULL,NULL,NULL
+} pcmcia_com = {
+ {"PCMCIA Modem card", com_pcmcia_mod, com_pcmcia_isa_attach,
+ NULL, com_pcmcia_remove}
};
-struct pcmciadevs pcmcia_com_devs[]={
- { "com", 0,
+
+
+struct pcmciadevs pcmcia_com_devs[] = {
+ { "com", 0,
NULL, "*MODEM*", NULL, NULL,
NULL, (void *)&pcmcia_com
},
- { "com", 0,
+ { "com", 0,
NULL, NULL, "*MODEM*", NULL,
NULL, (void *)&pcmcia_com
},
- { "com", 0,
+ { "com", 0,
NULL, NULL, NULL, "*MODEM*",
NULL, (void *)&pcmcia_com
},
{NULL}
};
+#define ncom_pcmcia_devs sizeof(pcmcia_com_devs)/sizeof(pcmcia_com_devs[0])
+
+int
+com_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ return pcmcia_slave_match(parent, match, aux, pcmcia_com_devs,
+ ncom_pcmcia_devs);
+}
+
+int
+com_pcmcia_isa_attach(parent, match, aux, pc_link)
+ struct device *parent;
+ void *match;
+ void *aux;
+ struct pcmcia_link *pc_link;
+{
+ struct isa_attach_args *ia = aux;
+ struct com_softc *sc = match;
+
+ int rval;
+ if (rval = comprobe(parent, sc->sc_dev.dv_cfdata, ia)) {
+ if (ISSET(pc_link->flags, PCMCIA_REATTACH)) {
+#ifdef COM_DEBUG
+ printf("comreattach, hwflags=%x\n", sc->sc_hwflags);
+#endif
+ sc->sc_hwflags = COM_HW_REATTACH |
+ (sc->sc_hwflags & (COM_HW_ABSENT_PENDING|COM_HW_CONSOLE));
+ } else
+ sc->sc_hwflags = 0;
+ }
+ return rval;
+}
+
+
+/*
+ * Called by config_detach attempts, shortly after com_pcmcia_remove
+ * was called.
+ */
+int
+com_pcmcia_detach(self)
+ struct device *self;
+{
+ struct com_softc *sc = (void *)self;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ /* don't let it really be detached, it is still open */
+ return EBUSY;
+ }
+ return 0; /* OK! */
+}
+
+/*
+ * called by pcmcia framework to accept/reject remove attempts.
+ * If we return 0, then the detach will proceed.
+ */
+int
+com_pcmcia_remove(pc_link, self)
+ struct pcmcia_link *pc_link;
+ struct device *self;
+{
+ struct com_softc *sc = (void *)self;
+ struct tty *tp;
+ int s;
+
+ if (!sc->sc_tty)
+ goto ok;
+ tp = sc->sc_tty;
+
+ /* not in use ? if so, return "OK" */
+ if (!ISSET(tp->t_state, TS_ISOPEN) &&
+ !ISSET(tp->t_state, TS_WOPEN)) {
+ ttyfree(sc->sc_tty);
+ sc->sc_tty = NULL;
+ ok:
+ isa_intr_disestablish(sc->sc_bc, sc->sc_ih);
+ sc->sc_ih = NULL;
+ SET(sc->sc_hwflags, COM_HW_ABSENT);
+ return 0; /* OK! */
+ }
+ /*
+ * Not easily removed. Put device into a dead state, clean state
+ * as best we can. notify all waiters.
+ */
+ SET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING);
+#ifdef COM_DEBUG
+ printf("pending detach flags %x\n", sc->sc_hwflags);
+#endif
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+
+ return 0;
+}
+
+#if 0
+void
+com_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_attach_args *paa = aux;
+
+ printf("com_pcmcia_attach %p %p %p\n", parent, self, aux);
+ delay(2000000);
+ if (!pcmcia_configure(parent, self, paa->paa_link)) {
+ struct com_softc *sc = (void *)self;
+ sc->sc_hwflags |= COM_HW_ABSENT;
+ printf(": not attached\n");
+ }
+}
#endif
+#endif
+
+/*
+ * must be called at spltty() or higher.
+ */
+void
+com_absent_notify(sc)
+ struct com_softc *sc;
+{
+ struct tty *tp;
+ if (tp = sc->sc_tty) {
+ CLR(tp->t_state, TS_CARR_ON|TS_BUSY);
+ ttyflush(tp, FREAD|FWRITE);
+ }
+}
int
comspeed(speed)
@@ -351,13 +513,21 @@ comprobe(parent, match, aux)
int iobase, needioh;
int rv = 1;
+#if NCOM_ISA || NCOM_PCMCIA
+#define IS_ISA(parent) \
+ (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
+#elif NCOM_ISA
+#define IS_ISA(parent) \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
+#endif
/*
* XXX should be broken out into functions for isa probe and
* XXX for commulti probe, with a helper function that contains
* XXX most of the interesting stuff.
*/
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
bc = ia->ia_bc;
@@ -393,8 +563,8 @@ comprobe(parent, match, aux)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
-#if NCOM_ISA
- if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (rv && IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
@@ -425,10 +595,16 @@ comattach(parent, self, aux)
* XXX for commulti attach, with a helper function that contains
* XXX most of the interesting stuff.
*/
- sc->sc_hwflags = 0;
+ if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
+ int s;
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ } else
+ sc->sc_hwflags = 0;
sc->sc_swflags = 0;
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
/*
@@ -457,7 +633,7 @@ comattach(parent, self, aux)
irq = IRQUNK;
if (ca->ca_noien)
- sc->sc_hwflags |= COM_HW_NOIEN;
+ SET(sc->sc_hwflags, COM_HW_NOIEN);
} else
#endif
panic("comattach: impossible");
@@ -522,8 +698,8 @@ comattach(parent, self, aux)
bus_io_write_1(bc, ioh, com_mcr, 0);
if (irq != IRQUNK) {
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
@@ -576,7 +752,7 @@ comopen(dev, flag, mode, p)
if (unit >= com_cd.cd_ndevs)
return ENXIO;
sc = com_cd.cd_devs[unit];
- if (!sc)
+ if (!sc || ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING))
return ENXIO;
if (!sc->sc_tty)
@@ -716,19 +892,30 @@ comclose(dev, flag, mode, p)
(*linesw[tp->t_line].l_close)(tp, flag);
s = spltty();
- CLR(sc->sc_lcr, LCR_SBREAK);
- bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
- bus_io_write_1(bc, ioh, com_ier, 0);
- if (ISSET(tp->t_cflag, HUPCL) &&
- !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
- /* XXX perhaps only clear DTR */
- bus_io_write_1(bc, ioh, com_mcr, 0);
+ if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /* can't do any of this stuff .... */
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+ bus_io_write_1(bc, ioh, com_ier, 0);
+ if (ISSET(tp->t_cflag, HUPCL) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+ /* XXX perhaps only clear DTR */
+ bus_io_write_1(bc, ioh, com_mcr, 0);
+ }
}
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
if (--comsopen == 0)
untimeout(compoll, NULL);
splx(s);
ttyclose(tp);
+#ifdef COM_DEBUG
+ /* mark it ready for more use if reattached earlier */
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ printf("comclose pending cleared\n");
+ }
+#endif
+ CLR(sc->sc_hwflags, COM_HW_ABSENT_PENDING);
+
#ifdef notyet /* XXXX */
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
ttyfree(tp);
@@ -747,6 +934,13 @@ comread(dev, uio, flag)
struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@@ -759,6 +953,13 @@ comwrite(dev, uio, flag)
struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
@@ -800,6 +1001,13 @@ comioctl(dev, cmd, data, flag, p)
bus_io_handle_t ioh = sc->sc_ioh;
int error;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return error;
@@ -914,6 +1122,13 @@ comparam(tp, t)
tcflag_t oldcflag;
int s;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
/* check requested parameters */
if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
return EINVAL;
@@ -1042,6 +1257,18 @@ comparam(tp, t)
}
void
+comstart_pending(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int s;
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+}
+
+void
comstart(tp)
struct tty *tp;
{
@@ -1051,6 +1278,16 @@ comstart(tp)
int s;
s = spltty();
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /*
+ * not quite good enough: if caller is ttywait() it will
+ * go to sleep immediately, so hang out a bit and then
+ * prod caller again.
+ */
+ com_absent_notify(sc);
+ timeout(comstart_pending, sc, 1);
+ goto out;
+ }
if (ISSET(tp->t_state, TS_BUSY))
goto out;
if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
@@ -1236,6 +1473,9 @@ comintr(arg)
} iter[32];
#endif
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
+ return 0; /* can't do squat. */
+
#ifdef COM_DEBUG
n = 0;
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
diff --git a/sys/dev/ic/i82365reg.h b/sys/dev/ic/i82365reg.h
index fb05f10c0c2..1f0a8f77858 100644
--- a/sys/dev/ic/i82365reg.h
+++ b/sys/dev/ic/i82365reg.h
@@ -8,7 +8,7 @@
* Support is included for Intel 82365SL PCIC controllers and clones
* thereof.
*
- * $Id: i82365reg.h,v 1.1 1996/01/15 00:08:50 hvozda Exp $
+ * $Id: i82365reg.h,v 1.2 1996/04/29 14:15:58 hvozda Exp $
***********************************************************************/
/*
@@ -30,6 +30,7 @@
*/
#define PCIC_BASE 0x03e0 /* base adddress of pcic register set */
+#define PCIC_NPORTS 2 /* pcic takes 2 ports */
/* First, all the registers */
#define PCIC_ID_REV 0x00 /* Identification and Revision */
@@ -107,6 +108,8 @@
#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */
#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */
#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */
+#define PCIC_146FC6 0x84 /* VL82C146FC6; Both Memory and I/O */
+#define PCIC_146FC7 0x85 /* VL82C146FC7; Both Memory and I/O */
/* For Interface Status register (PCIC_STATUS) */
#define PCIC_VPPV 0x80 /* Vpp_valid */
@@ -128,7 +131,7 @@
/* For the Interrupt and General Control register (PCIC_INT_GEN) */
#define PCIC_INT_MASK 0x0f
#define PCIC_INT_FLAGMASK 0x0f
-#define PCIC_INTR_ENA 0x10
+#define PCIC_INTR_ENA 0x10 /* clr bit means CSC interrupt goes via IRQ */
#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */
#define PCIC_IOCARD 0x20
#define PCIC_MEMCARD 0x00
@@ -136,12 +139,20 @@
#define PCIC_RINGIND 0x80
/* For the Card Status Change register (PCIC_STAT_CHG) */
+#define PCIC_GPICH 0x10 /* General Purpose Input (GPI) Change */
#define PCIC_CDTCH 0x08 /* Card Detect Change */
#define PCIC_RDYCH 0x04 /* Ready Change */
#define PCIC_BATWRN 0x02 /* Battery Warning */
#define PCIC_BATDED 0x01 /* Battery Dead */
#define PCIC_STCH 0x01 /* Status Change */
+/* For the Card Status Change interrupt config register (PCIC_STAT_INT) */
+#define PCIC_CDT_ENA 0x08 /* Card Detect Enable */
+#define PCIC_RDY_ENA 0x04 /* Ready Enable */
+#define PCIC_BATWRN_ENA 0x02 /* Battery Warning */
+#define PCIC_BATDED_ENA 0x01 /* Battery Dead */
+#define PCIC_ST_ENA 0x01 /* Status Change */
+
/* For the Address Window Enable Register (PCIC_ADDRWINE) */
#define PCIC_SM0_EN 0x01 /* Memory Window 0 Enable */
#define PCIC_SM1_EN 0x02 /* Memory Window 1 Enable */
@@ -194,7 +205,7 @@
/* For Card Detect and General Control register (PCIC_CDGC) */
#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */
#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */
-#define PCIC_GPI_EN 0x04 /* GPI Enable */
+#define PCIC_GPI_EN 0x04 /* General Purpose Input (GPI) Enable */
#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */
#define PCIC_CDRES_EN 0x10 /* card detect resume enable */
#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */
@@ -206,12 +217,16 @@ struct pcic_register {
};
struct pcic_regs {
u_short chip_vers;
-#define PCMICA_CHIP_82365_0 1
-#define PCMICA_CHIP_82365_1 2
-#define PCMICA_CHIP_IBM_1 3
-#define PCMICA_CHIP_IBM_2 4
+#define PCMICA_CHIP_82365_0 1
+#define PCMICA_CHIP_82365_1 2
+#define PCMICA_CHIP_IBM_1 3
+#define PCMICA_CHIP_IBM_2 4
+#define PCMICA_CHIP_146FC6 5
+#define PCMICA_CHIP_146FC7 6
u_short cnt;
struct pcic_register reg[128];
};
/* DON'T ADD ANYTHING AFTER THIS #endif */
#endif /* __82365_H__ */
+#ifndef __82365_H__
+#define __82365_H__