Make pcmcia cards detach properly.

Notify userland of attaching/detaching cards.
This partly fixes PR 15951.
This commit is contained in:
martin 2002-03-25 12:07:33 +00:00
parent e242265100
commit a994533d0a
8 changed files with 121 additions and 38 deletions

View File

@ -27,14 +27,14 @@
* i4b_isac.c - i4b siemens isdn chipset driver ISAC handler
* ---------------------------------------------------------
*
* $Id: isac.c,v 1.4 2002/03/24 20:35:45 martin Exp $
* $Id: isac.c,v 1.5 2002/03/25 12:07:33 martin Exp $
*
* last edit-date: [Fri Jan 5 11:36:10 2001]
*
*---------------------------------------------------------------------------*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: isac.c,v 1.4 2002/03/24 20:35:45 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: isac.c,v 1.5 2002/03/25 12:07:33 martin Exp $");
#ifdef __FreeBSD__
#include "opt_i4b.h"
@ -92,7 +92,7 @@ static void isic_isac_ind_hdlr(register struct isic_softc *sc, int ind);
/*---------------------------------------------------------------------------*
* ISAC interrupt service routine
*---------------------------------------------------------------------------*/
void
int
isic_isac_irq(struct isic_softc *sc, int ista)
{
register u_char c = 0;
@ -100,7 +100,12 @@ isic_isac_irq(struct isic_softc *sc, int ista)
if(ista & ISAC_ISTA_EXI) /* extended interrupt */
{
c |= isic_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
u_int8_t exirstat = ISAC_READ(I_EXIR);
if ((ista & ~ISAC_IMASK) && exirstat == 0xff) {
/* bogus - might be a detaching pcmcia card */
return (1);
}
c |= isic_isac_exir_hdlr(sc, exirstat);
}
if(ista & ISAC_ISTA_RME) /* receive message end */
@ -150,7 +155,7 @@ isic_isac_irq(struct isic_softc *sc, int ista)
ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
ISACCMDRWRDELAY();
return;
return (0);
}
rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
@ -320,6 +325,8 @@ isic_isac_irq(struct isic_softc *sc, int ista)
ISAC_WRITE(I_CMDR, c);
ISACCMDRWRDELAY();
}
return (0);
}
/*---------------------------------------------------------------------------*

View File

@ -27,14 +27,14 @@
* i4b_isic.c - global isic stuff
* ==============================
*
* $Id: isic.c,v 1.4 2002/03/24 20:35:46 martin Exp $
* $Id: isic.c,v 1.5 2002/03/25 12:07:33 martin Exp $
*
* last edit-date: [Fri Jan 5 11:36:10 2001]
*
*---------------------------------------------------------------------------*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: isic.c,v 1.4 2002/03/24 20:35:46 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: isic.c,v 1.5 2002/03/25 12:07:33 martin Exp $");
#include <sys/param.h>
#include <sys/ioccom.h>
@ -132,7 +132,8 @@ isicintr(void *arg)
if(isac_irq_stat)
{
isic_isac_irq(sc, isac_irq_stat); /* isac handler */
if (isic_isac_irq(sc, isac_irq_stat)) /* isac handler */
break; /* bad IRQ */
was_isac_irq = 1;
}
}
@ -192,7 +193,8 @@ isicintr(void *arg)
if(ipac_irq_stat & IPAC_ISTA_EXD)
{
/* force ISAC interrupt handling */
isic_isac_irq(sc, ISAC_ISTA_EXI);
if (isic_isac_irq(sc, ISAC_ISTA_EXI))
break; /* bad IRQ */
was_ipac_irq = 1;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: isic_l1.h,v 1.4 2002/03/24 20:35:47 martin Exp $ */
/* $NetBSD: isic_l1.h,v 1.5 2002/03/25 12:07:33 martin Exp $ */
/*
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
@ -206,7 +206,7 @@ struct isic_softc
int sc_init_tries; /* no of out tries to access S0 */
int sc_maddr; /* some stupid ISA cards need this */
u_char sc_isac_mask; /* ISAC IRQ mask */
#define ISAC_IMASK (sc->sc_isac_mask)
@ -340,7 +340,7 @@ extern void isic_hscx_cmd __P(( struct isic_softc *sc, int h_chan, unsigned char
extern void isic_hscx_waitxfw __P(( struct isic_softc *sc, int h_chan ));
extern void isic_init_linktab __P((struct isic_softc *sc));
extern int isic_isac_init __P((struct isic_softc *sc));
extern void isic_isac_irq __P((struct isic_softc *sc, int r));
extern int isic_isac_irq __P((struct isic_softc *sc, int r));
extern void isic_isac_l1_cmd __P((struct isic_softc *sc, int command));
extern void isic_next_state __P((struct isic_softc *sc, int event));
extern char * isic_printstate __P((struct isic_softc *sc));

View File

@ -33,7 +33,7 @@
* isic_pcmcia.c - pcmcia bus frontend for i4b_isic driver
* -------------------------------------------------------
*
* $Id: isic_pcmcia.c,v 1.6 2002/03/24 20:35:54 martin Exp $
* $Id: isic_pcmcia.c,v 1.7 2002/03/25 12:07:33 martin Exp $
*
* last edit-date: [Fri Jan 5 11:39:32 2001]
*
@ -42,7 +42,7 @@
*---------------------------------------------------------------------------*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: isic_pcmcia.c,v 1.6 2002/03/24 20:35:54 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: isic_pcmcia.c,v 1.7 2002/03/25 12:07:33 martin Exp $");
#include <sys/param.h>
#include <sys/errno.h>
@ -94,9 +94,11 @@ static int isic_pcmcia_match __P((struct device *, struct cfdata *, void *));
static void isic_pcmcia_attach __P((struct device *, struct device *, void *));
static const struct isic_pcmcia_card_entry * find_matching_card __P((struct pcmcia_attach_args *pa));
static int isic_pcmcia_isdn_attach __P((struct isic_softc *sc, const char*));
static int isic_pcmcia_detach(struct device *self, int flags);
struct cfattach isic_pcmcia_ca = {
sizeof(struct pcmcia_isic_softc), isic_pcmcia_match, isic_pcmcia_attach
sizeof(struct pcmcia_isic_softc), isic_pcmcia_match,
isic_pcmcia_attach, isic_pcmcia_detach
};
struct isic_pcmcia_card_entry {
@ -244,6 +246,22 @@ isic_pcmcia_attach(parent, self, aux)
splx(s);
}
static int
isic_pcmcia_detach(self, flags)
struct device *self;
int flags;
{
struct pcmcia_isic_softc *psc = (struct pcmcia_isic_softc *)self;
pcmcia_function_disable(psc->sc_pf);
pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
isic_detach_bri(&psc->sc_isic);
return (0);
}
/*---------------------------------------------------------------------------*
* card independend attach for pcmicia cards
*---------------------------------------------------------------------------*/

View File

@ -27,7 +27,7 @@
* i4b_ioctl.h - messages kernel <--> userland
* -------------------------------------------
*
* $Id: i4b_ioctl.h,v 1.5 2002/03/24 20:35:57 martin Exp $
* $Id: i4b_ioctl.h,v 1.6 2002/03/25 12:07:34 martin Exp $
*
* $FreeBSD$
*
@ -211,6 +211,7 @@ typedef struct {
#define MSG_IFSTATE_CHANGED_IND 'o'
#define MSG_DIALOUTNUMBER_IND 'p'
#define MSG_PACKET_IND 'q'
#define MSG_CONTR_EV_IND 'r'
int cdid; /* call descriptor id */
} msg_hdr_t;
@ -411,6 +412,17 @@ typedef struct {
int numactive; /* number of active connections */
} msg_pdeact_ind_t;
/*---------------------------------------------------------------------------*
* connect indication
* indicates incoming connection
*---------------------------------------------------------------------------*/
typedef struct {
msg_hdr_t header; /* common header */
int controller; /* controller number */
int event;
#define CTRL_EV_IND_DETACH 0
#define CTRL_EV_IND_ATTACH 1
} msg_ctrl_ev_ind_t;
/*===========================================================================*
*===========================================================================*

View File

@ -1,4 +1,4 @@
/* $NetBSD: i4b_l2.c,v 1.7 2002/03/24 20:35:58 martin Exp $ */
/* $NetBSD: i4b_l2.c,v 1.8 2002/03/25 12:07:34 martin Exp $ */
/*
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
@ -29,7 +29,7 @@
* i4b_l2.c - ISDN layer 2 (Q.921)
* -------------------------------
*
* $Id: i4b_l2.c,v 1.7 2002/03/24 20:35:58 martin Exp $
* $Id: i4b_l2.c,v 1.8 2002/03/25 12:07:34 martin Exp $
*
* $FreeBSD$
*
@ -38,7 +38,7 @@
*---------------------------------------------------------------------------*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: i4b_l2.c,v 1.7 2002/03/24 20:35:58 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: i4b_l2.c,v 1.8 2002/03/25 12:07:34 martin Exp $");
#ifdef __FreeBSD__
#include "i4bq921.h"
@ -226,6 +226,9 @@ isdn_layer2_status_ind(l2_softc_t *l2sc, int status, int parm)
switch(status)
{
case STI_ATTACH:
if (parm == 0) /* detach */
break;
l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN;
l2sc->ua_frame = NULL;
memset(&l2sc->stat, 0, sizeof(lapdstat_t));

View File

@ -27,7 +27,7 @@
* i4b_l3l4.h - layer 3 / layer 4 interface
* ------------------------------------------
*
* $Id: i4b_l3l4.h,v 1.7 2002/03/24 20:36:00 martin Exp $
* $Id: i4b_l3l4.h,v 1.8 2002/03/25 12:07:34 martin Exp $
*
* $FreeBSD$
*
@ -242,7 +242,7 @@ struct isdn_l3_driver_functions {
* is just one of those BRIs)
*---------------------------------------------------------------------------*/
struct isdn_l3_driver {
SIMPLEQ_ENTRY(isdn_l3_driver) l3drvq;
SLIST_ENTRY(isdn_l3_driver) l3drvq;
void* l1_token; /* softc of hardware driver, actually
* this is the l2_softc (!!) for
* passive cards, and something else

View File

@ -27,7 +27,7 @@
* i4b_l4.c - kernel interface to userland
* -----------------------------------------
*
* $Id: i4b_l4.c,v 1.12 2002/03/24 20:36:00 martin Exp $
* $Id: i4b_l4.c,v 1.13 2002/03/25 12:07:34 martin Exp $
*
* $FreeBSD$
*
@ -36,7 +36,7 @@
*---------------------------------------------------------------------------*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: i4b_l4.c,v 1.12 2002/03/24 20:36:00 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: i4b_l4.c,v 1.13 2002/03/25 12:07:34 martin Exp $");
#include "isdn.h"
#include "irip.h"
@ -74,13 +74,15 @@ __KERNEL_RCSID(0, "$NetBSD: i4b_l4.c,v 1.12 2002/03/24 20:36:00 martin Exp $");
#include <netisdn/i4b_l3.h>
#include <netisdn/i4b_l4.h>
static void i4b_l4_contr_ev_ind(int controller, int attach);
unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
/*
* BRIs (in userland sometimes called "controllers", but one controller
* may have multiple BRIs, for example daic QUAD cards attach four BRIs).
*/
static SIMPLEQ_HEAD(, isdn_l3_driver) bri_list = SIMPLEQ_HEAD_INITIALIZER(bri_list);
static SLIST_HEAD(, isdn_l3_driver) bri_list = SLIST_HEAD_INITIALIZER(bri_list);
static int next_bri = 0;
/*
@ -90,12 +92,13 @@ struct isdn_l3_driver *
isdn_attach_bri(const char *devname, const char *cardname,
void *l1_token, const struct isdn_l3_driver_functions *l3driver)
{
int s = splnet();
int l, bri = next_bri++;
struct isdn_l3_driver *new_ctrl;
new_ctrl = malloc(sizeof(*new_ctrl), M_DEVBUF, 0);
memset(new_ctrl, 0, sizeof *new_ctrl);
SIMPLEQ_INSERT_HEAD(&bri_list, new_ctrl, l3drvq);
SLIST_INSERT_HEAD(&bri_list, new_ctrl, l3drvq);
new_ctrl->bri = bri;
l = strlen(devname);
new_ctrl->devname = malloc(l+1, M_DEVBUF, 0);
@ -112,6 +115,9 @@ isdn_attach_bri(const char *devname, const char *cardname,
new_ctrl->bch_state[1] = BCH_ST_FREE;
printf("BRI %d at %s\n", bri, devname);
i4b_l4_contr_ev_ind(bri, 1);
splx(s);
return new_ctrl;
}
@ -122,8 +128,23 @@ isdn_attach_bri(const char *devname, const char *cardname,
int
isdn_detach_bri(const struct isdn_l3_driver *l3drv)
{
/* XXX - not yet implemented*/
printf("BRI %d detached\n", l3drv->bri);
struct isdn_l3_driver *sc;
int s = splnet();
int bri = l3drv->bri;
int max;
i4b_l4_contr_ev_ind(bri, 0);
SLIST_REMOVE(&bri_list, l3drv, isdn_l3_driver, l3drvq);
max = -1;
SLIST_FOREACH(sc, &bri_list, l3drvq)
if (sc->bri > max)
max = sc->bri;
next_bri = max+1;
splx(s);
printf("BRI %d detached\n", bri);
return 1;
}
@ -132,7 +153,7 @@ isdn_find_l3_by_bri(int bri)
{
struct isdn_l3_driver *sc;
SIMPLEQ_FOREACH(sc, &bri_list, l3drvq)
SLIST_FOREACH(sc, &bri_list, l3drvq)
if (sc->bri == bri)
return sc;
return NULL;
@ -144,7 +165,7 @@ int isdn_count_bri(int *mbri)
int count = 0;
int maxbri = -1;
SIMPLEQ_FOREACH(sc, &bri_list, l3drvq) {
SLIST_FOREACH(sc, &bri_list, l3drvq) {
count++;
if (sc->bri > maxbri)
maxbri = sc->bri;
@ -181,7 +202,7 @@ i4b_l4_daemon_attached(void)
struct isdn_l3_driver *d;
int x = splnet();
SIMPLEQ_FOREACH(d, &bri_list, l3drvq)
SLIST_FOREACH(d, &bri_list, l3drvq)
{
d->l3driver->N_MGMT_COMMAND(d->bri, CMR_DOPEN, 0);
}
@ -197,7 +218,7 @@ i4b_l4_daemon_detached(void)
struct isdn_l3_driver *d;
int x = splnet();
SIMPLEQ_FOREACH(d, &bri_list, l3drvq)
SLIST_FOREACH(d, &bri_list, l3drvq)
{
d->l3driver->N_MGMT_COMMAND(d->bri, CMR_DCLOSE, 0);
}
@ -220,14 +241,14 @@ static time_t i4b_get_idletime(call_desc_t *cd);
static int next_l4_driver_id = 0;
struct l4_driver_desc {
SIMPLEQ_ENTRY(l4_driver_desc) l4drvq;
SLIST_ENTRY(l4_driver_desc) l4drvq;
char name[L4DRIVER_NAME_SIZ];
int driver_id;
const struct isdn_l4_driver_functions *driver;
int units;
};
static SIMPLEQ_HEAD(, l4_driver_desc) l4_driver_registry
= SIMPLEQ_HEAD_INITIALIZER(l4_driver_registry);
static SLIST_HEAD(, l4_driver_desc) l4_driver_registry
= SLIST_HEAD_INITIALIZER(l4_driver_registry);
int isdn_l4_driver_attach(const char *name, int units, const struct isdn_l4_driver_functions *driver)
{
@ -240,7 +261,7 @@ int isdn_l4_driver_attach(const char *name, int units, const struct isdn_l4_driv
new_driver->driver_id = next_l4_driver_id++;
new_driver->driver = driver;
new_driver->units = units;
SIMPLEQ_INSERT_HEAD(&l4_driver_registry, new_driver, l4drvq);
SLIST_INSERT_HEAD(&l4_driver_registry, new_driver, l4drvq);
return new_driver->driver_id;
}
@ -253,7 +274,7 @@ int isdn_l4_driver_detatch(const char *name)
const struct isdn_l4_driver_functions *isdn_l4_find_driver(const char *name, int unit)
{
struct l4_driver_desc * d;
SIMPLEQ_FOREACH(d, &l4_driver_registry, l4drvq)
SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
if (strcmp(d->name, name) == 0) {
return d->driver;
}
@ -263,7 +284,7 @@ const struct isdn_l4_driver_functions *isdn_l4_find_driver(const char *name, int
int isdn_l4_find_driverid(const char *name)
{
struct l4_driver_desc * d;
SIMPLEQ_FOREACH(d, &l4_driver_registry, l4drvq)
SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
if (strcmp(d->name, name) == 0) {
return d->driver_id;
}
@ -273,7 +294,7 @@ int isdn_l4_find_driverid(const char *name)
const struct isdn_l4_driver_functions *isdn_l4_get_driver(int driver_id, int unit)
{
struct l4_driver_desc * d;
SIMPLEQ_FOREACH(d, &l4_driver_registry, l4drvq)
SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
if (d->driver_id == driver_id) {
return d->driver;
}
@ -760,6 +781,26 @@ i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
}
}
/*---------------------------------------------------------------------------*
* send MSG_CONTR_EV_IND message to userland
*---------------------------------------------------------------------------*/
static void
i4b_l4_contr_ev_ind(int controller, int attach)
{
struct mbuf *m;
if((m = i4b_Dgetmbuf(sizeof(msg_ctrl_ev_ind_t))) != NULL)
{
msg_ctrl_ev_ind_t *ev = (msg_ctrl_ev_ind_t *)m->m_data;
ev->header.type = MSG_CONTR_EV_IND;
ev->header.cdid = -1;
ev->controller = controller;
ev->event = attach;
i4bputqueue(m);
}
}
/*---------------------------------------------------------------------------*
* link a driver(unit) to a B-channel(controller,unit,channel)
*---------------------------------------------------------------------------*/