1 | /* $NetBSD: pcmciavar.h,v 1.35 2011/07/26 22:24:36 dyoung Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1997 Marc Horowitz. All rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. All advertising materials mentioning features or use of this software |
15 | * must display the following acknowledgement: |
16 | * This product includes software developed by Marc Horowitz. |
17 | * 4. The name of the author may not be used to endorse or promote products |
18 | * derived from this software without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
21 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
23 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | #include <sys/types.h> |
33 | #include <sys/queue.h> |
34 | |
35 | #include <dev/pcmcia/pcmciachip.h> |
36 | |
37 | extern int pcmcia_verbose; |
38 | |
39 | /* |
40 | * Contains information about mapped/allocated i/o spaces. |
41 | */ |
42 | struct pcmcia_io_handle { |
43 | bus_space_tag_t iot; /* bus space tag (from chipset) */ |
44 | bus_space_handle_t ioh; /* mapped space handle */ |
45 | bus_addr_t addr; /* resulting address in bus space */ |
46 | bus_size_t size; /* size of i/o space */ |
47 | int flags; /* misc. information */ |
48 | void *ihandle; /* opaque i/o handle */ |
49 | }; |
50 | |
51 | #define PCMCIA_IO_ALLOCATED 0x01 /* i/o space was allocated */ |
52 | |
53 | /* |
54 | * Contains information about allocated memory space. |
55 | */ |
56 | struct pcmcia_mem_handle { |
57 | bus_space_tag_t memt; /* bus space tag (from chipset) */ |
58 | bus_space_handle_t memh; /* mapped space handle */ |
59 | bus_addr_t addr; /* resulting address in bus space */ |
60 | bus_size_t size; /* size of mem space */ |
61 | pcmcia_mem_handle_t mhandle; /* opaque memory handle */ |
62 | bus_size_t realsize; /* how much we really allocated */ |
63 | }; |
64 | |
65 | /* pcmcia itself */ |
66 | |
67 | #define PCMCIA_CFE_MWAIT_REQUIRED 0x0001 |
68 | #define PCMCIA_CFE_RDYBSY_ACTIVE 0x0002 |
69 | #define PCMCIA_CFE_WP_ACTIVE 0x0004 |
70 | #define PCMCIA_CFE_BVD_ACTIVE 0x0008 |
71 | #define PCMCIA_CFE_IO8 0x0010 |
72 | #define PCMCIA_CFE_IO16 0x0020 |
73 | #define PCMCIA_CFE_IRQSHARE 0x0040 |
74 | #define PCMCIA_CFE_IRQPULSE 0x0080 |
75 | #define PCMCIA_CFE_IRQLEVEL 0x0100 |
76 | #define PCMCIA_CFE_POWERDOWN 0x0200 |
77 | #define PCMCIA_CFE_READONLY 0x0400 |
78 | #define PCMCIA_CFE_AUDIO 0x0800 |
79 | |
80 | struct pcmcia_config_entry { |
81 | int number; |
82 | u_int32_t flags; |
83 | int iftype; |
84 | int num_iospace; |
85 | |
86 | /* |
87 | * The card will only decode this mask in any case, so we can |
88 | * do dynamic allocation with this in mind, in case the suggestions |
89 | * below are no good. |
90 | */ |
91 | u_long iomask; |
92 | struct { |
93 | u_long length; |
94 | u_long start; |
95 | |
96 | struct pcmcia_io_handle handle; |
97 | int window; |
98 | } iospace[4]; /* XXX this could be as high as 16 */ |
99 | u_int16_t irqmask; |
100 | int num_memspace; |
101 | struct { |
102 | u_long length; |
103 | u_long cardaddr; |
104 | u_long hostaddr; |
105 | |
106 | struct pcmcia_mem_handle handle; |
107 | bus_size_t offset; |
108 | int window; |
109 | |
110 | } memspace[2]; /* XXX this could be as high as 8 */ |
111 | int maxtwins; |
112 | SIMPLEQ_ENTRY(pcmcia_config_entry) cfe_list; |
113 | }; |
114 | |
115 | |
116 | struct pcmcia_funce_disk { |
117 | int pfd_interface; |
118 | }; |
119 | |
120 | struct pcmcia_funce_lan { |
121 | int pfl_nidlen; |
122 | u_int8_t pfl_nid[8]; |
123 | }; |
124 | |
125 | union pcmcia_funce { |
126 | struct pcmcia_funce_disk pfv_disk; |
127 | struct pcmcia_funce_lan pfv_lan; |
128 | }; |
129 | |
130 | |
131 | struct pcmcia_function { |
132 | /* read off the card */ |
133 | int number; |
134 | int function; |
135 | int last_config_index; |
136 | u_long ccr_base; |
137 | u_long ccr_mask; |
138 | SIMPLEQ_HEAD(, pcmcia_config_entry) cfe_head; |
139 | SIMPLEQ_ENTRY(pcmcia_function) pf_list; |
140 | /* run-time state */ |
141 | struct pcmcia_softc *sc; |
142 | device_t child; |
143 | struct pcmcia_config_entry *cfe; |
144 | struct pcmcia_mem_handle pf_pcmh; |
145 | #define pf_ccrt pf_pcmh.memt |
146 | #define pf_ccrh pf_pcmh.memh |
147 | #define pf_ccr_mhandle pf_pcmh.mhandle |
148 | #define pf_ccr_realsize pf_pcmh.realsize |
149 | bus_size_t pf_ccr_offset; |
150 | int pf_ccr_window; |
151 | bus_addr_t pf_mfc_iobase; |
152 | bus_addr_t pf_mfc_iomax; |
153 | void *pf_ih; |
154 | int pf_flags; |
155 | |
156 | union pcmcia_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 | #define PFF_DETACHED 0x0002 /* card is detached */ |
165 | |
166 | SIMPLEQ_HEAD(pcmcia_function_head, pcmcia_function); |
167 | |
168 | struct pcmcia_card { |
169 | int cis1_major; |
170 | int cis1_minor; |
171 | /* XXX waste of space? */ |
172 | char cis1_info_buf[256]; |
173 | char *cis1_info[4]; |
174 | /* |
175 | * Use int32_t for manufacturer and product so that they can |
176 | * hold the id value found in card CIS and special value that |
177 | * indicates no id was found. |
178 | */ |
179 | int32_t manufacturer; |
180 | #define PCMCIA_VENDOR_INVALID -1 |
181 | int32_t product; |
182 | #define PCMCIA_PRODUCT_INVALID -1 |
183 | u_int16_t error; |
184 | #define PCMCIA_CIS_INVALID { NULL, NULL, NULL, NULL } |
185 | struct pcmcia_function_head pf_head; |
186 | }; |
187 | |
188 | struct pcmcia_softc { |
189 | device_t dev; |
190 | |
191 | /* this stuff is for the socket */ |
192 | pcmcia_chipset_tag_t pct; |
193 | pcmcia_chipset_handle_t pch; |
194 | |
195 | /* this stuff is for the card */ |
196 | struct pcmcia_card card; |
197 | void *ih; |
198 | int sc_enabled_count; /* how many functions are |
199 | enabled */ |
200 | }; |
201 | |
202 | struct pcmcia_cis_quirk { |
203 | int32_t manufacturer; |
204 | int32_t product; |
205 | const char *cis1_info[4]; |
206 | const struct pcmcia_function *pf; |
207 | const struct pcmcia_config_entry *cfe; |
208 | }; |
209 | |
210 | struct pcmcia_attach_args { |
211 | int32_t manufacturer; |
212 | int32_t product; |
213 | struct pcmcia_card *card; |
214 | struct pcmcia_function *pf; |
215 | }; |
216 | |
217 | struct pcmcia_tuple { |
218 | unsigned int code; |
219 | unsigned int length; |
220 | u_long mult; |
221 | bus_size_t ptr; |
222 | bus_space_tag_t memt; |
223 | bus_space_handle_t memh; |
224 | }; |
225 | |
226 | struct pcmcia_product { |
227 | u_int32_t pp_vendor; |
228 | u_int32_t pp_product; |
229 | const char *pp_cisinfo[4]; |
230 | }; |
231 | |
232 | typedef int (*pcmcia_product_match_fn)(struct pcmcia_attach_args *, |
233 | const struct pcmcia_product *, int); |
234 | |
235 | const void *pcmcia_product_lookup(struct pcmcia_attach_args *, const void *, |
236 | size_t, size_t, pcmcia_product_match_fn); |
237 | |
238 | void pcmcia_devinfo(struct pcmcia_card *, int, char *, size_t); |
239 | |
240 | void pcmcia_read_cis(struct pcmcia_softc *); |
241 | void pcmcia_check_cis_quirks(struct pcmcia_softc *); |
242 | void pcmcia_print_cis(struct pcmcia_softc *); |
243 | int pcmcia_scan_cis(device_t, |
244 | int (*) (struct pcmcia_tuple *, void *), void *); |
245 | |
246 | #define pcmcia_cis_read_1(tuple, idx0) \ |
247 | (bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0))) |
248 | |
249 | #define pcmcia_tuple_read_1(tuple, idx1) \ |
250 | (pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1))))) |
251 | |
252 | #define pcmcia_tuple_read_2(tuple, idx2) \ |
253 | (pcmcia_tuple_read_1((tuple), (idx2)) | \ |
254 | (pcmcia_tuple_read_1((tuple), (idx2)+1)<<8)) |
255 | |
256 | #define pcmcia_tuple_read_3(tuple, idx3) \ |
257 | (pcmcia_tuple_read_1((tuple), (idx3)) | \ |
258 | (pcmcia_tuple_read_1((tuple), (idx3)+1)<<8) | \ |
259 | (pcmcia_tuple_read_1((tuple), (idx3)+2)<<16)) |
260 | |
261 | #define pcmcia_tuple_read_4(tuple, idx4) \ |
262 | (pcmcia_tuple_read_1((tuple), (idx4)) | \ |
263 | (pcmcia_tuple_read_1((tuple), (idx4)+1)<<8) | \ |
264 | (pcmcia_tuple_read_1((tuple), (idx4)+2)<<16) | \ |
265 | (pcmcia_tuple_read_1((tuple), (idx4)+3)<<24)) |
266 | |
267 | #define pcmcia_tuple_read_n(tuple, n, idxn) \ |
268 | (((n)==1)?pcmcia_tuple_read_1((tuple), (idxn)) : \ |
269 | (((n)==2)?pcmcia_tuple_read_2((tuple), (idxn)) : \ |
270 | (((n)==3)?pcmcia_tuple_read_3((tuple), (idxn)) : \ |
271 | /* n == 4 */ pcmcia_tuple_read_4((tuple), (idxn))))) |
272 | |
273 | #define PCMCIA_SPACE_MEMORY 1 |
274 | #define PCMCIA_SPACE_IO 2 |
275 | |
276 | int pcmcia_ccr_read(struct pcmcia_function *, int); |
277 | void pcmcia_ccr_write(struct pcmcia_function *, int, int); |
278 | |
279 | #define pcmcia_mfc(sc) (! SIMPLEQ_EMPTY(&(sc)->card.pf_head) && \ |
280 | SIMPLEQ_NEXT(SIMPLEQ_FIRST(&(sc)->card.pf_head), pf_list)) |
281 | |
282 | void pcmcia_socket_enable(device_t); |
283 | void pcmcia_socket_disable(device_t); |
284 | void pcmcia_socket_settype(device_t, int); |
285 | |
286 | int pcmcia_config_alloc(struct pcmcia_function *, |
287 | struct pcmcia_config_entry *); |
288 | void pcmcia_config_free(struct pcmcia_function *); |
289 | int pcmcia_config_map(struct pcmcia_function *); |
290 | void pcmcia_config_unmap(struct pcmcia_function *); |
291 | |
292 | |
293 | int pcmcia_function_configure(struct pcmcia_function *, |
294 | int (*validator)(struct pcmcia_config_entry *)); |
295 | void pcmcia_function_unconfigure(struct pcmcia_function *); |
296 | void pcmcia_function_init(struct pcmcia_function *, |
297 | struct pcmcia_config_entry *); |
298 | int pcmcia_function_enable(struct pcmcia_function *); |
299 | void pcmcia_function_disable(struct pcmcia_function *); |
300 | |
301 | #define pcmcia_io_alloc(pf, start, size, align, pciop) \ |
302 | (pcmcia_chip_io_alloc((pf)->sc->pct, pf->sc->pch, (start), \ |
303 | (size), (align), (pciop))) |
304 | |
305 | #define pcmcia_io_free(pf, pciohp) \ |
306 | (pcmcia_chip_io_free((pf)->sc->pct, (pf)->sc->pch, (pciohp))) |
307 | |
308 | int pcmcia_io_map(struct pcmcia_function *, int, |
309 | struct pcmcia_io_handle *, int *); |
310 | void pcmcia_io_unmap(struct pcmcia_function *, int); |
311 | |
312 | void pcmcia_free_pf(struct pcmcia_function_head *); |
313 | |
314 | #define pcmcia_mem_alloc(pf, size, pcmhp) \ |
315 | (pcmcia_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp))) |
316 | |
317 | #define pcmcia_mem_free(pf, pcmhp) \ |
318 | (pcmcia_chip_mem_free((pf)->sc->pct, (pf)->sc->pch, (pcmhp))) |
319 | |
320 | #define pcmcia_mem_map(pf, kind, card_addr, size, pcmhp, offsetp, windowp) \ |
321 | (pcmcia_chip_mem_map((pf)->sc->pct, (pf)->sc->pch, (kind), \ |
322 | (card_addr), (size), (pcmhp), (offsetp), (windowp))) |
323 | |
324 | #define pcmcia_mem_unmap(pf, window) \ |
325 | (pcmcia_chip_mem_unmap((pf)->sc->pct, (pf)->sc->pch, (window))) |
326 | |
327 | void *pcmcia_intr_establish(struct pcmcia_function *, int, |
328 | int (*) (void *), void *); |
329 | void pcmcia_intr_disestablish(struct pcmcia_function *, void *); |
330 | |