Home | History | Annotate | Line # | Download | only in cardbus
com_cardbus.c revision 1.5.2.2
      1  1.5.2.2  bouyer /* $NetBSD: com_cardbus.c,v 1.5.2.2 2000/11/20 11:39:53 bouyer Exp $ */
      2  1.5.2.2  bouyer 
      3  1.5.2.2  bouyer /*
      4  1.5.2.2  bouyer  * Copyright (c) 2000 Johan Danielsson
      5  1.5.2.2  bouyer  * All rights reserved.
      6  1.5.2.2  bouyer  *
      7  1.5.2.2  bouyer  * Redistribution and use in source and binary forms, with or without
      8  1.5.2.2  bouyer  * modification, are permitted provided that the following conditions
      9  1.5.2.2  bouyer  * are met:
     10  1.5.2.2  bouyer  *
     11  1.5.2.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     12  1.5.2.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     13  1.5.2.2  bouyer  *
     14  1.5.2.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.5.2.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     16  1.5.2.2  bouyer  *    documentation and/or other materials provided with the distribution.
     17  1.5.2.2  bouyer  *
     18  1.5.2.2  bouyer  * 3. Neither the name of author nor the names of any contributors may
     19  1.5.2.2  bouyer  *    be used to endorse or promote products derived from this
     20  1.5.2.2  bouyer  *    software without specific prior written permission.
     21  1.5.2.2  bouyer  *
     22  1.5.2.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     23  1.5.2.2  bouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  1.5.2.2  bouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25  1.5.2.2  bouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
     26  1.5.2.2  bouyer  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     27  1.5.2.2  bouyer  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     28  1.5.2.2  bouyer  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     29  1.5.2.2  bouyer  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     30  1.5.2.2  bouyer  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     31  1.5.2.2  bouyer  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     32  1.5.2.2  bouyer  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  1.5.2.2  bouyer  */
     34  1.5.2.2  bouyer 
     35  1.5.2.2  bouyer /* A driver for CardBus based serial devices.
     36  1.5.2.2  bouyer 
     37  1.5.2.2  bouyer    If the CardBus device only has one BAR (that is not also the CIS
     38  1.5.2.2  bouyer    BAR) listed in the CIS, it is assumed to be the one to use. For
     39  1.5.2.2  bouyer    devices with more than one BAR, the list of known devices has to be
     40  1.5.2.2  bouyer    updated below.  */
     41  1.5.2.2  bouyer 
     42  1.5.2.2  bouyer #include <sys/param.h>
     43  1.5.2.2  bouyer #include <sys/systm.h>
     44  1.5.2.2  bouyer #include <sys/tty.h>
     45  1.5.2.2  bouyer #include <sys/device.h>
     46  1.5.2.2  bouyer 
     47  1.5.2.2  bouyer #include <dev/cardbus/cardbusvar.h>
     48  1.5.2.2  bouyer #include <dev/cardbus/cardbusdevs.h>
     49  1.5.2.2  bouyer 
     50  1.5.2.2  bouyer #include <dev/pcmcia/pcmciareg.h>
     51  1.5.2.2  bouyer 
     52  1.5.2.2  bouyer #include <dev/ic/comreg.h>
     53  1.5.2.2  bouyer #include <dev/ic/comvar.h>
     54  1.5.2.2  bouyer 
     55  1.5.2.2  bouyer struct com_cardbus_softc {
     56  1.5.2.2  bouyer 	struct com_softc	cc_com;
     57  1.5.2.2  bouyer 	void			*cc_ih;
     58  1.5.2.2  bouyer 	cardbus_devfunc_t	cc_ct;
     59  1.5.2.2  bouyer 	bus_addr_t		cc_addr;
     60  1.5.2.2  bouyer 	cardbusreg_t		cc_base;
     61  1.5.2.2  bouyer 	bus_size_t		cc_size;
     62  1.5.2.2  bouyer 	cardbusreg_t		cc_csr;
     63  1.5.2.2  bouyer 	int			cc_cben;
     64  1.5.2.2  bouyer 	cardbustag_t		cc_tag;
     65  1.5.2.2  bouyer 	cardbusreg_t		cc_reg;
     66  1.5.2.2  bouyer 	int			cc_type;
     67  1.5.2.2  bouyer };
     68  1.5.2.2  bouyer 
     69  1.5.2.2  bouyer #define DEVNAME(CSC) ((CSC)->cc_com.sc_dev.dv_xname)
     70  1.5.2.2  bouyer 
     71  1.5.2.2  bouyer static int com_cardbus_match (struct device*, struct cfdata*, void*);
     72  1.5.2.2  bouyer static void com_cardbus_attach (struct device*, struct device*, void*);
     73  1.5.2.2  bouyer static int com_cardbus_detach (struct device*, int);
     74  1.5.2.2  bouyer 
     75  1.5.2.2  bouyer static void com_cardbus_setup(struct com_cardbus_softc*);
     76  1.5.2.2  bouyer static int com_cardbus_enable (struct com_softc*);
     77  1.5.2.2  bouyer static void com_cardbus_disable (struct com_softc*);
     78  1.5.2.2  bouyer 
     79  1.5.2.2  bouyer struct cfattach com_cardbus_ca = {
     80  1.5.2.2  bouyer 	sizeof(struct com_cardbus_softc), com_cardbus_match,
     81  1.5.2.2  bouyer 	com_cardbus_attach, com_cardbus_detach, com_activate
     82  1.5.2.2  bouyer };
     83  1.5.2.2  bouyer 
     84  1.5.2.2  bouyer static struct csdev {
     85  1.5.2.2  bouyer 	int		vendor;
     86  1.5.2.2  bouyer 	int		product;
     87  1.5.2.2  bouyer 	cardbusreg_t	reg;
     88  1.5.2.2  bouyer 	int		type;
     89  1.5.2.2  bouyer } csdevs[] = {
     90  1.5.2.2  bouyer 	{ CARDBUS_VENDOR_XIRCOM, CARDBUS_PRODUCT_XIRCOM_MODEM56,
     91  1.5.2.2  bouyer 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO },
     92  1.5.2.2  bouyer 	{ CARDBUS_VENDOR_INTEL, CARDBUS_PRODUCT_INTEL_MODEM56,
     93  1.5.2.2  bouyer 	  CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO }
     94  1.5.2.2  bouyer };
     95  1.5.2.2  bouyer 
     96  1.5.2.2  bouyer static const int ncsdevs = sizeof(csdevs) / sizeof(csdevs[0]);
     97  1.5.2.2  bouyer 
     98  1.5.2.2  bouyer static struct csdev*
     99  1.5.2.2  bouyer find_csdev(struct cardbus_attach_args *ca)
    100  1.5.2.2  bouyer {
    101  1.5.2.2  bouyer 	struct csdev *cp;
    102  1.5.2.2  bouyer 
    103  1.5.2.2  bouyer 	for(cp = csdevs; cp < csdevs + ncsdevs; cp++)
    104  1.5.2.2  bouyer 		if(cp->vendor == CARDBUS_VENDOR(ca->ca_id) &&
    105  1.5.2.2  bouyer 		   cp->product == CARDBUS_PRODUCT(ca->ca_id))
    106  1.5.2.2  bouyer 			return cp;
    107  1.5.2.2  bouyer 	return NULL;
    108  1.5.2.2  bouyer }
    109  1.5.2.2  bouyer 
    110  1.5.2.2  bouyer static int
    111  1.5.2.2  bouyer com_cardbus_match(struct device *parent, struct cfdata *match, void *aux)
    112  1.5.2.2  bouyer {
    113  1.5.2.2  bouyer 	struct cardbus_attach_args *ca = aux;
    114  1.5.2.2  bouyer 
    115  1.5.2.2  bouyer 	/* known devices are ok */
    116  1.5.2.2  bouyer 	if(find_csdev(ca) != NULL)
    117  1.5.2.2  bouyer 	    return 10;
    118  1.5.2.2  bouyer 
    119  1.5.2.2  bouyer 	/* as are serial devices with a known UART */
    120  1.5.2.2  bouyer 	if(ca->ca_cis.funcid == PCMCIA_FUNCTION_SERIAL &&
    121  1.5.2.2  bouyer 	   ca->ca_cis.funce.serial.uart_present != 0 &&
    122  1.5.2.2  bouyer 	   (ca->ca_cis.funce.serial.uart_type == 0 ||	/* 8250 */
    123  1.5.2.2  bouyer 	    ca->ca_cis.funce.serial.uart_type == 1 ||	/* 16450 */
    124  1.5.2.2  bouyer 	    ca->ca_cis.funce.serial.uart_type == 2))	/* 16550 */
    125  1.5.2.2  bouyer 	    return 1;
    126  1.5.2.2  bouyer 
    127  1.5.2.2  bouyer 	return 0;
    128  1.5.2.2  bouyer }
    129  1.5.2.2  bouyer 
    130  1.5.2.2  bouyer static int
    131  1.5.2.2  bouyer gofigure(struct cardbus_attach_args *ca, struct com_cardbus_softc *csc)
    132  1.5.2.2  bouyer {
    133  1.5.2.2  bouyer 	int i, index = -1;
    134  1.5.2.2  bouyer 	cardbusreg_t cis_ptr;
    135  1.5.2.2  bouyer 	struct csdev *cp;
    136  1.5.2.2  bouyer 
    137  1.5.2.2  bouyer 	/* If this device is listed above, use the known values, */
    138  1.5.2.2  bouyer 	cp = find_csdev(ca);
    139  1.5.2.2  bouyer 	if(cp != NULL) {
    140  1.5.2.2  bouyer 		csc->cc_reg = cp->reg;
    141  1.5.2.2  bouyer 		csc->cc_type = cp->type;
    142  1.5.2.2  bouyer 		return 0;
    143  1.5.2.2  bouyer 	}
    144  1.5.2.2  bouyer 
    145  1.5.2.2  bouyer 	cis_ptr = Cardbus_conf_read(csc->cc_ct, csc->cc_tag, CARDBUS_CIS_REG);
    146  1.5.2.2  bouyer 
    147  1.5.2.2  bouyer 	/* otherwise try to deduce which BAR and type to use from CIS.  If
    148  1.5.2.2  bouyer 	   there is only one BAR, it must be the one we should use, if
    149  1.5.2.2  bouyer 	   there are more, we're out of luck.  */
    150  1.5.2.2  bouyer 	for(i = 0; i < 7; i++) {
    151  1.5.2.2  bouyer 		/* ignore zero sized BARs */
    152  1.5.2.2  bouyer 		if(ca->ca_cis.bar[i].size == 0)
    153  1.5.2.2  bouyer 			continue;
    154  1.5.2.2  bouyer 		/* ignore the CIS BAR */
    155  1.5.2.2  bouyer 		if(CARDBUS_CIS_ASI_BAR(cis_ptr) ==
    156  1.5.2.2  bouyer 		   CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
    157  1.5.2.2  bouyer 			continue;
    158  1.5.2.2  bouyer 		if(index != -1)
    159  1.5.2.2  bouyer 			goto multi_bar;
    160  1.5.2.2  bouyer 		index = i;
    161  1.5.2.2  bouyer 	}
    162  1.5.2.2  bouyer 	if(index == -1) {
    163  1.5.2.2  bouyer 		printf(": couldn't find any base address tuple\n");
    164  1.5.2.2  bouyer 		return 1;
    165  1.5.2.2  bouyer 	}
    166  1.5.2.2  bouyer 	csc->cc_reg = CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[index].flags);
    167  1.5.2.2  bouyer 	if ((ca->ca_cis.bar[index].flags & 0x10) == 0)
    168  1.5.2.2  bouyer 		csc->cc_type = CARDBUS_MAPREG_TYPE_MEM;
    169  1.5.2.2  bouyer 	else
    170  1.5.2.2  bouyer 		csc->cc_type = CARDBUS_MAPREG_TYPE_IO;
    171  1.5.2.2  bouyer 	return 0;
    172  1.5.2.2  bouyer 
    173  1.5.2.2  bouyer   multi_bar:
    174  1.5.2.2  bouyer 	printf(": there are more than one possible base\n");
    175  1.5.2.2  bouyer 
    176  1.5.2.2  bouyer 	printf("%s: address for this device, "
    177  1.5.2.2  bouyer 	       "please report the following information\n",
    178  1.5.2.2  bouyer 	       DEVNAME(csc));
    179  1.5.2.2  bouyer 	printf("%s: vendor 0x%x product 0x%x\n", DEVNAME(csc),
    180  1.5.2.2  bouyer 	       CARDBUS_VENDOR(ca->ca_id), CARDBUS_PRODUCT(ca->ca_id));
    181  1.5.2.2  bouyer 	for(i = 0; i < 7; i++) {
    182  1.5.2.2  bouyer 		/* ignore zero sized BARs */
    183  1.5.2.2  bouyer 		if(ca->ca_cis.bar[i].size == 0)
    184  1.5.2.2  bouyer 			continue;
    185  1.5.2.2  bouyer 		/* ignore the CIS BAR */
    186  1.5.2.2  bouyer 		if(CARDBUS_CIS_ASI_BAR(cis_ptr) ==
    187  1.5.2.2  bouyer 		   CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags))
    188  1.5.2.2  bouyer 			continue;
    189  1.5.2.2  bouyer 		printf("%s: base address %x type %s size %x\n",
    190  1.5.2.2  bouyer 		       DEVNAME(csc),
    191  1.5.2.2  bouyer 		       CARDBUS_CIS_ASI_BAR(ca->ca_cis.bar[i].flags),
    192  1.5.2.2  bouyer 		       (ca->ca_cis.bar[i].flags & 0x10) ? "i/o" : "mem",
    193  1.5.2.2  bouyer 		       ca->ca_cis.bar[i].size);
    194  1.5.2.2  bouyer 	}
    195  1.5.2.2  bouyer 	return 1;
    196  1.5.2.2  bouyer }
    197  1.5.2.2  bouyer 
    198  1.5.2.2  bouyer static void
    199  1.5.2.2  bouyer com_cardbus_attach (struct device *parent, struct device *self, void *aux)
    200  1.5.2.2  bouyer {
    201  1.5.2.2  bouyer 	struct com_softc *sc = (struct com_softc*)self;
    202  1.5.2.2  bouyer 	struct com_cardbus_softc *csc = (struct com_cardbus_softc*)self;
    203  1.5.2.2  bouyer 	struct cardbus_attach_args *ca = aux;
    204  1.5.2.2  bouyer 
    205  1.5.2.2  bouyer 	csc->cc_ct = ca->ca_ct;
    206  1.5.2.2  bouyer 	csc->cc_tag = Cardbus_make_tag(csc->cc_ct);
    207  1.5.2.2  bouyer 
    208  1.5.2.2  bouyer 	if(gofigure(ca, csc) != 0)
    209  1.5.2.2  bouyer 		return;
    210  1.5.2.2  bouyer 
    211  1.5.2.2  bouyer 	if(Cardbus_mapreg_map(ca->ca_ct,
    212  1.5.2.2  bouyer 			      csc->cc_reg,
    213  1.5.2.2  bouyer 			      csc->cc_type,
    214  1.5.2.2  bouyer 			      0,
    215  1.5.2.2  bouyer 			      &sc->sc_iot,
    216  1.5.2.2  bouyer 			      &sc->sc_ioh,
    217  1.5.2.2  bouyer 			      &csc->cc_addr,
    218  1.5.2.2  bouyer 			      &csc->cc_size) != 0) {
    219  1.5.2.2  bouyer 		printf("failed to map memory");
    220  1.5.2.2  bouyer 		return;
    221  1.5.2.2  bouyer 	}
    222  1.5.2.2  bouyer 
    223  1.5.2.2  bouyer 	csc->cc_base = csc->cc_addr;
    224  1.5.2.2  bouyer 	csc->cc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
    225  1.5.2.2  bouyer 	if(csc->cc_type == CARDBUS_MAPREG_TYPE_IO) {
    226  1.5.2.2  bouyer 		csc->cc_base |= CARDBUS_MAPREG_TYPE_IO;
    227  1.5.2.2  bouyer 		csc->cc_csr |= CARDBUS_COMMAND_IO_ENABLE;
    228  1.5.2.2  bouyer 		csc->cc_cben = CARDBUS_IO_ENABLE;
    229  1.5.2.2  bouyer 	} else {
    230  1.5.2.2  bouyer 		csc->cc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
    231  1.5.2.2  bouyer 		csc->cc_cben = CARDBUS_MEM_ENABLE;
    232  1.5.2.2  bouyer 	}
    233  1.5.2.2  bouyer 	sc->sc_iobase = csc->cc_addr;
    234  1.5.2.2  bouyer 
    235  1.5.2.2  bouyer 	sc->sc_frequency = COM_FREQ;
    236  1.5.2.2  bouyer 
    237  1.5.2.2  bouyer 	sc->enable = com_cardbus_enable;
    238  1.5.2.2  bouyer 	sc->disable = com_cardbus_disable;
    239  1.5.2.2  bouyer 	sc->enabled = 0;
    240  1.5.2.2  bouyer 
    241  1.5.2.2  bouyer 	if (ca->ca_cis.cis1_info[0] && ca->ca_cis.cis1_info[1]) {
    242  1.5.2.2  bouyer 		printf(": %s %s\n", ca->ca_cis.cis1_info[0],
    243  1.5.2.2  bouyer 		    ca->ca_cis.cis1_info[1]);
    244  1.5.2.2  bouyer 		printf("%s", DEVNAME(csc));
    245  1.5.2.2  bouyer 	}
    246  1.5.2.2  bouyer 
    247  1.5.2.2  bouyer 	com_cardbus_setup(csc);
    248  1.5.2.2  bouyer 
    249  1.5.2.2  bouyer 	com_attach_subr(sc);
    250  1.5.2.2  bouyer 
    251  1.5.2.2  bouyer 	Cardbus_function_disable(csc->cc_ct);
    252  1.5.2.2  bouyer }
    253  1.5.2.2  bouyer 
    254  1.5.2.2  bouyer static void
    255  1.5.2.2  bouyer com_cardbus_setup(struct com_cardbus_softc *csc)
    256  1.5.2.2  bouyer {
    257  1.5.2.2  bouyer         cardbus_devfunc_t ct = csc->cc_ct;
    258  1.5.2.2  bouyer         cardbus_chipset_tag_t cc = ct->ct_cc;
    259  1.5.2.2  bouyer         cardbus_function_tag_t cf = ct->ct_cf;
    260  1.5.2.2  bouyer 	cardbusreg_t reg;
    261  1.5.2.2  bouyer 
    262  1.5.2.2  bouyer 	Cardbus_conf_write(ct, csc->cc_tag, csc->cc_reg, csc->cc_base);
    263  1.5.2.2  bouyer 
    264  1.5.2.2  bouyer 	/* enable accesses on cardbus bridge */
    265  1.5.2.2  bouyer 	(*cf->cardbus_ctrl)(cc, csc->cc_cben);
    266  1.5.2.2  bouyer 	(*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
    267  1.5.2.2  bouyer 
    268  1.5.2.2  bouyer 	/* and the card itself */
    269  1.5.2.2  bouyer 	reg = Cardbus_conf_read(ct, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG);
    270  1.5.2.2  bouyer 	reg &= ~(CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE);
    271  1.5.2.2  bouyer 	reg |= csc->cc_csr;
    272  1.5.2.2  bouyer 	Cardbus_conf_write(ct, csc->cc_tag, CARDBUS_COMMAND_STATUS_REG, reg);
    273  1.5.2.2  bouyer 
    274  1.5.2.2  bouyer         /*
    275  1.5.2.2  bouyer          * Make sure the latency timer is set to some reasonable
    276  1.5.2.2  bouyer          * value.
    277  1.5.2.2  bouyer          */
    278  1.5.2.2  bouyer         reg = cardbus_conf_read(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG);
    279  1.5.2.2  bouyer         if (CARDBUS_LATTIMER(reg) < 0x20) {
    280  1.5.2.2  bouyer                 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
    281  1.5.2.2  bouyer                 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
    282  1.5.2.2  bouyer                 cardbus_conf_write(cc, cf, csc->cc_tag, CARDBUS_BHLC_REG, reg);
    283  1.5.2.2  bouyer         }
    284  1.5.2.2  bouyer }
    285  1.5.2.2  bouyer 
    286  1.5.2.2  bouyer static int
    287  1.5.2.2  bouyer com_cardbus_enable(struct com_softc *sc)
    288  1.5.2.2  bouyer {
    289  1.5.2.2  bouyer 	struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
    290  1.5.2.2  bouyer 	struct cardbus_softc *psc =
    291  1.5.2.2  bouyer 		(struct cardbus_softc *)sc->sc_dev.dv_parent;
    292  1.5.2.2  bouyer 	cardbus_chipset_tag_t cc = psc->sc_cc;
    293  1.5.2.2  bouyer 	cardbus_function_tag_t cf = psc->sc_cf;
    294  1.5.2.2  bouyer 
    295  1.5.2.2  bouyer 	Cardbus_function_enable(csc->cc_ct);
    296  1.5.2.2  bouyer 
    297  1.5.2.2  bouyer 	com_cardbus_setup(csc);
    298  1.5.2.2  bouyer 
    299  1.5.2.2  bouyer 	/* establish the interrupt. */
    300  1.5.2.2  bouyer 	csc->cc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline,
    301  1.5.2.2  bouyer 					    IPL_SERIAL, comintr, sc);
    302  1.5.2.2  bouyer 	if (csc->cc_ih == NULL) {
    303  1.5.2.2  bouyer 		printf("%s: couldn't establish interrupt\n",
    304  1.5.2.2  bouyer 		       DEVNAME(csc));
    305  1.5.2.2  bouyer 		return 1;
    306  1.5.2.2  bouyer 	}
    307  1.5.2.2  bouyer 
    308  1.5.2.2  bouyer 	printf("%s: interrupting at irq %d\n",
    309  1.5.2.2  bouyer 	       DEVNAME(csc), psc->sc_intrline);
    310  1.5.2.2  bouyer 
    311  1.5.2.2  bouyer 	return 0;
    312  1.5.2.2  bouyer }
    313  1.5.2.2  bouyer 
    314  1.5.2.2  bouyer static void
    315  1.5.2.2  bouyer com_cardbus_disable(struct com_softc *sc)
    316  1.5.2.2  bouyer {
    317  1.5.2.2  bouyer 	struct com_cardbus_softc *csc = (struct com_cardbus_softc*)sc;
    318  1.5.2.2  bouyer 	struct cardbus_softc *psc =
    319  1.5.2.2  bouyer 		(struct cardbus_softc *)sc->sc_dev.dv_parent;
    320  1.5.2.2  bouyer 	cardbus_chipset_tag_t cc = psc->sc_cc;
    321  1.5.2.2  bouyer 	cardbus_function_tag_t cf = psc->sc_cf;
    322  1.5.2.2  bouyer 
    323  1.5.2.2  bouyer 	cardbus_intr_disestablish(cc, cf, csc->cc_ih);
    324  1.5.2.2  bouyer 	Cardbus_function_disable(csc->cc_ct);
    325  1.5.2.2  bouyer }
    326  1.5.2.2  bouyer 
    327  1.5.2.2  bouyer static int
    328  1.5.2.2  bouyer com_cardbus_detach(struct device *self, int flags)
    329  1.5.2.2  bouyer {
    330  1.5.2.2  bouyer 	struct com_cardbus_softc *csc = (struct com_cardbus_softc *) self;
    331  1.5.2.2  bouyer 	struct com_softc *sc = (struct com_softc *) self;
    332  1.5.2.2  bouyer 	struct cardbus_softc *psc = (struct cardbus_softc *)self->dv_parent;
    333  1.5.2.2  bouyer 	int error;
    334  1.5.2.2  bouyer 
    335  1.5.2.2  bouyer 	if ((error = com_detach(self, flags)) != 0)
    336  1.5.2.2  bouyer 		return error;
    337  1.5.2.2  bouyer 
    338  1.5.2.2  bouyer 	cardbus_intr_disestablish(psc->sc_cc, psc->sc_cf, csc->cc_ih);
    339  1.5.2.2  bouyer 
    340  1.5.2.2  bouyer 	Cardbus_mapreg_unmap(csc->cc_ct, csc->cc_reg, sc->sc_iot, sc->sc_ioh,
    341  1.5.2.2  bouyer 			     csc->cc_size);
    342  1.5.2.2  bouyer 
    343  1.5.2.2  bouyer 	return 0;
    344  1.5.2.2  bouyer }
    345