1 /* $NetBSD: slhci_pcmcia.c,v 1.5 2009/05/12 13:18:04 cegger Exp $ */
3 * Not (c) 2007 Matthew Orgass
4 * This file is public domain, meaning anyone can make any use of part or all
5 * of this file including copying into other works without credit. Any use,
6 * modified or not, is solely the responsibility of the user. If this file is
7 * part of a collection then use in the collection is governed by the terms of
11 /* Glue for RATOC USB HOST CF+ Card (SL811HS chip) */
13 #include <sys/cdefs.h>
14 __KERNEL_RCSID(0, "$NetBSD: slhci_pcmcia.c,v 1.5 2009/05/12 13:18:04 cegger Exp $");
16 #include <sys/param.h>
17 #include <sys/device.h>
18 #include <sys/queue.h>
20 #include <sys/systm.h>
21 #include <sys/errno.h>
24 #include <dev/pcmcia/pcmciareg.h>
25 #include <dev/pcmcia/pcmciavar.h>
26 #include <dev/pcmcia/pcmciadevs.h>
28 #include <dev/usb/usb.h>
29 #include <dev/usb/usb_port.h>
30 #include <dev/usb/usbdi.h>
31 #include <dev/usb/usbdivar.h>
33 #include <dev/ic/sl811hsvar.h>
35 struct slhci_pcmcia_softc
{
36 struct slhci_softc sc_slhci
;
38 struct pcmcia_function
*sc_pf
;
41 #define PFL_ENABLED (0x1)
45 int slhci_pcmcia_probe(device_t
, cfdata_t
, void *);
46 void slhci_pcmcia_attach(device_t
, device_t
, void *);
47 int slhci_pcmcia_detach(device_t
, int);
48 int slhci_pcmcia_validate_config(struct pcmcia_config_entry
*);
49 int slhci_pcmcia_enable(struct slhci_pcmcia_softc
*, int);
51 CFATTACH_DECL_NEW(slhci_pcmcia
, sizeof(struct slhci_pcmcia_softc
),
52 slhci_pcmcia_probe
, slhci_pcmcia_attach
, slhci_pcmcia_detach
,
55 /* Ratoc has two PCMCIA products with id 1.
56 * Ratoc has a firmware update that modifies the CIS. The new CIS may
57 * need a new entry. */
58 static const struct pcmcia_product slhci_pcmcia_products
[] = {
59 { PCMCIA_VENDOR_RATOC
, PCMCIA_PRODUCT_RATOC_REX_CFU1
,
60 PCMCIA_CIS_RATOC_REX_CFU1
},
62 static const size_t slhci_pcmcia_nproducts
=
63 sizeof(slhci_pcmcia_products
) / sizeof(slhci_pcmcia_products
[0]);
66 slhci_pcmcia_probe(device_t parent
, cfdata_t match
, void *aux
)
68 struct pcmcia_attach_args
*pa
= aux
;
70 if (pcmcia_product_lookup(pa
, slhci_pcmcia_products
,
71 slhci_pcmcia_nproducts
, sizeof(slhci_pcmcia_products
[0]), NULL
))
78 slhci_pcmcia_validate_config(struct pcmcia_config_entry
*cfe
)
80 if (cfe
->num_iospace
!= 1 || cfe
->num_memspace
!= 0)
86 slhci_pcmcia_attach(device_t parent
, device_t self
, void *aux
)
88 struct slhci_pcmcia_softc
*psc
= device_private(self
);
89 struct pcmcia_attach_args
*pa
= aux
;
90 struct pcmcia_function
*pf
= pa
->pf
;
92 psc
->sc_slhci
.sc_dev
= self
;
97 slhci_pcmcia_enable(psc
, 1);
103 slhci_pcmcia_detach(device_t self
, int flags
)
105 struct slhci_pcmcia_softc
*psc
= device_private(self
);
107 slhci_pcmcia_enable(psc
, 0);
109 return slhci_detach(&psc
->sc_slhci
, flags
);
113 slhci_pcmcia_enable(struct slhci_pcmcia_softc
*psc
, int enable
)
115 struct pcmcia_function
*pf
;
116 struct pcmcia_io_handle
*pioh
;
117 struct slhci_softc
*sc
;
124 if (psc
->sc_flags
& PFL_ENABLED
)
127 error
= pcmcia_function_configure(pf
,
128 slhci_pcmcia_validate_config
);
130 printf("%s: configure failed, error=%d\n",
135 pioh
= &pf
->cfe
->iospace
[0].handle
;
137 /* The data port is repeated three times; using a stride of
138 * 2 prevents read/write errors on a Clio C-1000 hpcmips
141 slhci_preinit(sc
, NULL
, pioh
->iot
, pioh
->ioh
, 100, 2);
143 psc
->sc_ih
= pcmcia_intr_establish(pf
, IPL_HARDUSB
,
146 if (psc
->sc_ih
== NULL
) {
147 printf("%s: unable to establish interrupt\n",
152 if (pcmcia_function_enable(pf
)) {
153 printf("%s: function enable failed\n", SC_NAME(sc
));
157 if (slhci_attach(sc
)) {
158 printf("%s: slhci_attach failed\n", SC_NAME(sc
));
162 psc
->sc_flags
|= PFL_ENABLED
;
165 if (!(psc
->sc_flags
& PFL_ENABLED
))
167 psc
->sc_flags
&= ~PFL_ENABLED
;
169 pcmcia_function_disable(pf
);
171 pcmcia_intr_disestablish(psc
->sc_pf
, psc
->sc_ih
);
173 pcmcia_function_unconfigure(pf
);