xref: /dragonfly/sys/bus/pccard/pccardvar.h (revision 06ddf0c8f75c4f9c2bddedbd752e207681e8173c)
1 /*        $NetBSD: pcmciavar.h,v 1.12 2000/02/08 12:51:31 enami Exp $ */
2 /* $FreeBSD: src/sys/dev/pccard/pccardvar.h,v 1.54 2005/07/13 15:00:59 imp Exp $ */
3 
4 /*-
5  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *        This product includes software developed by Marc Horowitz.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * PCCARD_API_LEVEL.  When set to 5, we provide a 5.x compatable API
35  * for driver writers that have to share their code between 5.x and 6.x.
36  * The 5.x compatibility interfaces will be unsupported in 7.0, at which
37  * point we'll only support 6 and newer, etc.
38  */
39 #ifndef PCCARD_API_LEVEL
40 #define PCCARD_API_LEVEL 5
41 #elif PCCARD_API_LEVEL < 5
42 #error "pccard API less than 5 unsupported"
43 #endif
44 
45 /*
46  * Contains information about mapped/allocated i/o spaces.
47  */
48 struct pccard_io_handle {
49           bus_space_tag_t iot;                    /* bus space tag (from chipset) */
50           bus_space_handle_t ioh;                 /* mapped space handle */
51           bus_addr_t      addr;                   /* resulting address in bus space */
52           bus_size_t      size;                   /* size of i/o space */
53           int             flags;                  /* misc. information */
54           int                 width;
55 };
56 
57 #define   PCCARD_IO_ALLOCATED 0x01      /* i/o space was allocated */
58 
59 /*
60  * Contains information about allocated memory space.
61  */
62 struct pccard_mem_handle {
63           bus_space_tag_t memt;                   /* bus space tag (from chipset) */
64           bus_space_handle_t memh;      /* mapped space handle */
65           bus_addr_t      addr;                   /* resulting address in bus space */
66           bus_size_t      size;                   /* size of mem space */
67           bus_size_t      realsize;     /* how much we really allocated */
68           bus_addr_t          cardaddr; /* Absolute address on card */
69           int                 kind;
70 };
71 
72 /* pccard itself */
73 
74 #define PCCARD_CFE_MWAIT_REQUIRED       0x0001
75 #define PCCARD_CFE_RDYBSY_ACTIVE        0x0002
76 #define PCCARD_CFE_WP_ACTIVE            0x0004
77 #define PCCARD_CFE_BVD_ACTIVE           0x0008
78 #define PCCARD_CFE_IO8                            0x0010
79 #define PCCARD_CFE_IO16                           0x0020
80 #define PCCARD_CFE_IRQSHARE             0x0040
81 #define PCCARD_CFE_IRQPULSE             0x0080
82 #define PCCARD_CFE_IRQLEVEL             0x0100
83 #define PCCARD_CFE_POWERDOWN            0x0200
84 #define PCCARD_CFE_READONLY             0x0400
85 #define PCCARD_CFE_AUDIO                0x0800
86 
87 struct pccard_config_entry {
88           int                 number;
89           uint32_t  flags;
90           int                 iftype;
91           int                 num_iospace;
92 
93           /*
94            * The card will only decode this mask in any case, so we can
95            * do dynamic allocation with this in mind, in case the suggestions
96            * below are no good.
97            */
98           u_long              iomask;
99           struct {
100                     u_long    length;
101                     u_long    start;
102           } iospace[4];                 /* XXX this could be as high as 16 */
103           uint16_t  irqmask;
104           int                 num_memspace;
105           struct {
106                     u_long    length;
107                     u_long    cardaddr;
108                     u_long    hostaddr;
109           } memspace[2];                /* XXX this could be as high as 8 */
110           int                 maxtwins;
111           STAILQ_ENTRY(pccard_config_entry) cfe_list;
112 };
113 
114 struct pccard_funce_disk {
115           int pfd_interface;
116 };
117 
118 struct pccard_funce_lan {
119           int pfl_nidlen;
120           uint8_t pfl_nid[8];
121 };
122 
123 union pccard_funce {
124           struct pccard_funce_disk pfv_disk;
125           struct pccard_funce_lan pfv_lan;
126 };
127 
128 struct pccard_function {
129           /* read off the card */
130           int                 number;
131           int                 function;
132           int                 last_config_index;
133           uint32_t  ccr_base; /* Offset with card's memory */
134           uint32_t  ccr_mask;
135           struct resource *ccr_res;
136           int                 ccr_rid;
137           STAILQ_HEAD(, pccard_config_entry) cfe_head;
138           STAILQ_ENTRY(pccard_function) pf_list;
139           /* run-time state */
140           struct pccard_softc *sc;
141           struct pccard_config_entry *cfe;
142           struct pccard_mem_handle pf_pcmh;
143           device_t  dev;
144 #define   pf_ccrt             pf_pcmh.memt
145 #define   pf_ccrh             pf_pcmh.memh
146 #define   pf_ccr_realsize     pf_pcmh.realsize
147           uint32_t  pf_ccr_offset;      /* Offset from ccr_base of CIS */
148           int                 pf_ccr_window;
149           bus_addr_t          pf_mfc_iobase;
150           bus_addr_t          pf_mfc_iomax;
151           int                 pf_flags;
152           driver_intr_t       *intr_handler;
153           void                *intr_handler_arg;
154           void                *intr_handler_cookie;
155 
156           union pccard_funce pf_funce; /* CISTPL_FUNCE */
157 #define pf_funce_disk_interface pf_funce.pfv_disk.pfd_interface
158 #define pf_funce_lan_nid pf_funce.pfv_lan.pfl_nid
159 #define pf_funce_lan_nidlen pf_funce.pfv_lan.pfl_nidlen
160 };
161 
162 /* pf_flags */
163 #define   PFF_ENABLED         0x0001              /* function is enabled */
164 
165 struct pccard_card {
166           int                 cis1_major;
167           int                 cis1_minor;
168           /* XXX waste of space? */
169           char                cis1_info_buf[256];
170           char                *cis1_info[4];
171           /*
172            * Use int32_t for manufacturer and product so that they can
173            * hold the id value found in card CIS and special value that
174            * indicates no id was found.
175            */
176           int32_t             manufacturer;
177 #define   PCMCIA_VENDOR_INVALID         -1
178           int32_t             product;
179 #define   PCMCIA_PRODUCT_INVALID                  -1
180           int16_t             prodext;
181           uint16_t  error;
182 #define   PCMCIA_CIS_INVALID            { NULL, NULL, NULL, NULL }
183           STAILQ_HEAD(, pccard_function) pf_head;
184 };
185 
186 #define   PCCARD_WIDTH_AUTO   0
187 #define   PCCARD_WIDTH_IO8    1
188 #define   PCCARD_WIDTH_IO16   2
189 
190 /* More later? */
191 struct pccard_ivar {
192           struct resource_list resources;
193           struct pccard_function *pf;
194 };
195 
196 struct pccard_softc {
197           device_t            dev;
198           /* this stuff is for the socket */
199 
200           /* this stuff is for the card */
201           struct pccard_card card;
202           int                 sc_enabled_count;   /* num functions enabled */
203 };
204 
205 struct pccard_cis_quirk {
206           int32_t manufacturer;
207           int32_t product;
208           char *cis1_info[4];
209           struct pccard_function *pf;
210           struct pccard_config_entry *cfe;
211 };
212 
213 struct pccard_tuple {
214           unsigned int        code;
215           unsigned int        length;
216           u_long              mult;
217           bus_addr_t          ptr;
218           bus_space_tag_t     memt;
219           bus_space_handle_t memh;
220 };
221 
222 typedef int (*pccard_scan_t)(const struct pccard_tuple *, void *);
223 
224 struct pccard_product {
225           const char          *pp_name;           /* NULL if end of table */
226 #define PCCARD_VENDOR_ANY (0xffffffff)
227           uint32_t  pp_vendor;
228 #define PCCARD_PRODUCT_ANY (0xffffffff)
229           uint32_t  pp_product;
230           const char          *pp_cis[4];
231 };
232 
233 typedef int (*pccard_product_match_fn) (device_t dev,
234     const struct pccard_product *ent, int vpfmatch);
235 
236 #include "card_if.h"
237 
238 /*
239  * make this inline so that we don't have to worry about dangling references
240  * to it in the modules or the code.
241  */
242 static __inline const struct pccard_product *
pccard_product_lookup(device_t dev,const struct pccard_product * tab,size_t ent_size,pccard_product_match_fn matchfn)243 pccard_product_lookup(device_t dev, const struct pccard_product *tab,
244     size_t ent_size, pccard_product_match_fn matchfn)
245 {
246           return CARD_DO_PRODUCT_LOOKUP(device_get_parent(dev), dev,
247               tab, ent_size, matchfn);
248 }
249 
250 void      pccard_read_cis(struct pccard_softc *);
251 void      pccard_check_cis_quirks(device_t);
252 void      pccard_print_cis(device_t);
253 int       pccard_scan_cis(device_t, pccard_scan_t, void *);
254 
255 #define   pccard_cis_read_1(tuple, idx0)                                                  \
256           (bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0)))
257 
258 #define   pccard_tuple_read_1(tuple, idx1)                                      \
259           (pccard_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1)))))
260 
261 #define   pccard_tuple_read_2(tuple, idx2)                                      \
262           (pccard_tuple_read_1((tuple), (idx2)) |                               \
263            (pccard_tuple_read_1((tuple), (idx2)+1)<<8))
264 
265 #define   pccard_tuple_read_3(tuple, idx3)                                      \
266           (pccard_tuple_read_1((tuple), (idx3)) |                               \
267            (pccard_tuple_read_1((tuple), (idx3)+1)<<8) |                        \
268            (pccard_tuple_read_1((tuple), (idx3)+2)<<16))
269 
270 #define   pccard_tuple_read_4(tuple, idx4)                                      \
271           (pccard_tuple_read_1((tuple), (idx4)) |                               \
272            (pccard_tuple_read_1((tuple), (idx4)+1)<<8) |                        \
273            (pccard_tuple_read_1((tuple), (idx4)+2)<<16) |                       \
274            (pccard_tuple_read_1((tuple), (idx4)+3)<<24))
275 
276 #define   pccard_tuple_read_n(tuple, n, idxn)                                   \
277           (((n)==1)?pccard_tuple_read_1((tuple), (idxn)) :            \
278            (((n)==2)?pccard_tuple_read_2((tuple), (idxn)) :           \
279             (((n)==3)?pccard_tuple_read_3((tuple), (idxn)) :                    \
280              /* n == 4 */ pccard_tuple_read_4((tuple), (idxn)))))
281 
282 #define   PCCARD_SPACE_MEMORY 1
283 #define   PCCARD_SPACE_IO               2
284 
285 #define   pccard_mfc(sc)                                                                  \
286                     (STAILQ_FIRST(&(sc)->card.pf_head) &&                       \
287                      STAILQ_NEXT(STAILQ_FIRST(&(sc)->card.pf_head),pf_list))
288 
289 #define   pccard_io_alloc(pf, start, size, align, pciop)                        \
290           (pccard_chip_io_alloc((pf)->sc->pct, pf->sc->pch, (start),  \
291            (size), (align), (pciop)))
292 
293 #define   pccard_io_free(pf, pciohp)                                            \
294           (pccard_chip_io_free((pf)->sc->pct, (pf)->sc->pch, (pciohp)))
295 
296 int       pccard_io_map(struct pccard_function *, int, bus_addr_t,
297               bus_size_t, struct pccard_io_handle *, int *);
298 void      pccard_io_unmap(struct pccard_function *, int);
299 
300 #define pccard_mem_alloc(pf, size, pcmhp)                                       \
301           (pccard_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp)))
302 #define pccard_mem_free(pf, pcmhp)                                              \
303           (pccard_chip_mem_free((pf)->sc->pct, (pf)->sc->pch, (pcmhp)))
304 #define pccard_mem_map(pf, kind, card_addr, size, pcmhp, offsetp, windowp) \
305           (pccard_chip_mem_map((pf)->sc->pct, (pf)->sc->pch, (kind),  \
306            (card_addr), (size), (pcmhp), (offsetp), (windowp)))
307 #define   pccard_mem_unmap(pf, window)                                          \
308           (pccard_chip_mem_unmap((pf)->sc->pct, (pf)->sc->pch, (window)))
309 
310 /* compat layer */
311 static __inline int
pccard_compat_probe(device_t dev)312 pccard_compat_probe(device_t dev)
313 {
314           return (CARD_COMPAT_DO_PROBE(device_get_parent(dev), dev));
315 }
316 
317 static __inline int
pccard_compat_attach(device_t dev)318 pccard_compat_attach(device_t dev)
319 {
320           return (CARD_COMPAT_DO_ATTACH(device_get_parent(dev), dev));
321 }
322 
323 /* ivar interface */
324 enum {
325           PCCARD_IVAR_ETHADDR,          /* read ethernet address from CIS tupple */
326           PCCARD_IVAR_VENDOR,
327           PCCARD_IVAR_PRODUCT,
328           PCCARD_IVAR_PRODEXT,
329           PCCARD_IVAR_FUNCTION_NUMBER,
330           PCCARD_IVAR_VENDOR_STR,       /* CIS string for "Manufacturer" */
331           PCCARD_IVAR_PRODUCT_STR,/* CIS strnig for "Product" */
332           PCCARD_IVAR_CIS3_STR,
333           PCCARD_IVAR_CIS4_STR,
334           PCCARD_IVAR_FUNCTION
335 };
336 
337 #define PCCARD_ACCESSOR(A, B, T)                                                \
338 __inline static T                                                               \
339 pccard_get_ ## A(device_t dev)                                                            \
340 {                                                                                         \
341           uintptr_t v;                                                                    \
342           BUS_READ_IVAR(device_get_parent(dev), dev, PCCARD_IVAR_ ## B, &v); \
343           return (T)v;                                                                    \
344 }
345 
346 PCCARD_ACCESSOR(ether,                  ETHADDR,            const uint8_t *)
347 PCCARD_ACCESSOR(vendor,                 VENDOR,                       uint32_t)
348 PCCARD_ACCESSOR(product,      PRODUCT,            uint32_t)
349 PCCARD_ACCESSOR(prodext,      PRODEXT,            uint16_t)
350 PCCARD_ACCESSOR(function_number,FUNCTION_NUMBER,  uint32_t)
351 PCCARD_ACCESSOR(function,     FUNCTION,           uint32_t)
352 PCCARD_ACCESSOR(vendor_str,   VENDOR_STR,                   const char *)
353 PCCARD_ACCESSOR(product_str,  PRODUCT_STR,                  const char *)
354 PCCARD_ACCESSOR(cis3_str,     CIS3_STR,           const char *)
355 PCCARD_ACCESSOR(cis4_str,     CIS4_STR,           const char *)
356 
357 /* shared memory flags */
358 enum {
359           PCCARD_A_MEM_COM,       /* common */
360           PCCARD_A_MEM_ATTR,      /* attribute */
361           PCCARD_A_MEM_8BIT,      /* 8 bit */
362           PCCARD_A_MEM_16BIT      /* 16 bit */
363 };
364 
365 #define PCCARD_SOFTC(d) (struct pccard_softc *) device_get_softc(d)
366 #define PCCARD_IVAR(d) (struct pccard_ivar *) device_get_ivars(d)
367 
368 #define PCCARD_S(a, b) PCMCIA_STR_ ## a ## _ ## b
369 #define PCCARD_P(a, b) PCMCIA_PRODUCT_ ## a ## _ ## b
370 #define PCCARD_C(a, b) PCMCIA_CIS_ ## a ## _ ## b
371 #if PCCARD_API_LEVEL >= 6
372 #define PCMCIA_CARD_D(v, p) { PCCARD_S(v, p), PCMCIA_VENDOR_ ## v, \
373                     PCCARD_P(v, p), PCCARD_C(v, p) }
374 #define PCMCIA_CARD2_D(v1, p1, p2) \
375                     { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \
376                       PCMCIA_CIS_ ## p2}
377 #define PCMCIA_CARD(v, p) { NULL, PCMCIA_VENDOR_ ## v, \
378                     PCCARD_P(v, p), PCCARD_C(v, p) }
379 #define PCMCIA_CARD2(v1, p1, p2) \
380                     { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \
381                       PCMCIA_CIS_ ## p2}
382 #else
383 #define PCMCIA_CARD_D(v, p, f) { PCCARD_S(v, p), PCMCIA_VENDOR_ ## v, \
384                     PCCARD_P(v, p), PCCARD_C(v, p) }
385 #define PCMCIA_CARD2_D(v1, p1, p2, f) \
386                     { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \
387                       PCMCIA_CIS_ ## p2}
388 #define PCMCIA_CARD(v, p, f) { NULL, PCMCIA_VENDOR_ ## v, \
389                     PCCARD_P(v, p), PCCARD_C(v, p) }
390 #define PCMCIA_CARD2(v1, p1, p2, f) \
391                     { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \
392                       PCMCIA_CIS_ ## p2}
393 #endif
394