| @@ -1,1410 +1,1408 @@ | | | @@ -1,1410 +1,1408 @@ |
1 | /* $NetBSD: i82365.c,v 1.113 2010/04/19 18:24:26 dyoung Exp $ */ | | 1 | /* $NetBSD: i82365.c,v 1.114 2011/07/26 22:21:02 dyoung Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2004 Charles M. Hannum. All rights reserved. | | 4 | * Copyright (c) 2004 Charles M. Hannum. All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. All advertising materials mentioning features or use of this software | | 14 | * 3. All advertising materials mentioning features or use of this software |
15 | * must display the following acknowledgement: | | 15 | * must display the following acknowledgement: |
16 | * This product includes software developed by Charles M. Hannum. | | 16 | * This product includes software developed by Charles M. Hannum. |
17 | * 4. The name of the author may not be used to endorse or promote products | | 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. | | 18 | * derived from this software without specific prior written permission. |
19 | */ | | 19 | */ |
20 | | | 20 | |
21 | /* | | 21 | /* |
22 | * Copyright (c) 2000 Christian E. Hopps. All rights reserved. | | 22 | * Copyright (c) 2000 Christian E. Hopps. All rights reserved. |
23 | * Copyright (c) 1997 Marc Horowitz. All rights reserved. | | 23 | * Copyright (c) 1997 Marc Horowitz. All rights reserved. |
24 | * | | 24 | * |
25 | * Redistribution and use in source and binary forms, with or without | | 25 | * Redistribution and use in source and binary forms, with or without |
26 | * modification, are permitted provided that the following conditions | | 26 | * modification, are permitted provided that the following conditions |
27 | * are met: | | 27 | * are met: |
28 | * 1. Redistributions of source code must retain the above copyright | | 28 | * 1. Redistributions of source code must retain the above copyright |
29 | * notice, this list of conditions and the following disclaimer. | | 29 | * notice, this list of conditions and the following disclaimer. |
30 | * 2. Redistributions in binary form must reproduce the above copyright | | 30 | * 2. Redistributions in binary form must reproduce the above copyright |
31 | * notice, this list of conditions and the following disclaimer in the | | 31 | * notice, this list of conditions and the following disclaimer in the |
32 | * documentation and/or other materials provided with the distribution. | | 32 | * documentation and/or other materials provided with the distribution. |
33 | * 3. All advertising materials mentioning features or use of this software | | 33 | * 3. All advertising materials mentioning features or use of this software |
34 | * must display the following acknowledgement: | | 34 | * must display the following acknowledgement: |
35 | * This product includes software developed by Marc Horowitz. | | 35 | * This product includes software developed by Marc Horowitz. |
36 | * 4. The name of the author may not be used to endorse or promote products | | 36 | * 4. The name of the author may not be used to endorse or promote products |
37 | * derived from this software without specific prior written permission. | | 37 | * derived from this software without specific prior written permission. |
38 | * | | 38 | * |
39 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 39 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
40 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 40 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
41 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 41 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
42 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 42 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
43 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 43 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 45 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 46 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 47 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
48 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 48 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
49 | */ | | 49 | */ |
50 | | | 50 | |
51 | #include <sys/cdefs.h> | | 51 | #include <sys/cdefs.h> |
52 | __KERNEL_RCSID(0, "$NetBSD: i82365.c,v 1.113 2010/04/19 18:24:26 dyoung Exp $"); | | 52 | __KERNEL_RCSID(0, "$NetBSD: i82365.c,v 1.114 2011/07/26 22:21:02 dyoung Exp $"); |
53 | | | 53 | |
54 | #define PCICDEBUG | | 54 | #define PCICDEBUG |
55 | | | 55 | |
56 | #include <sys/param.h> | | 56 | #include <sys/param.h> |
57 | #include <sys/systm.h> | | 57 | #include <sys/systm.h> |
58 | #include <sys/device.h> | | 58 | #include <sys/device.h> |
59 | #include <sys/extent.h> | | 59 | #include <sys/extent.h> |
60 | #include <sys/kernel.h> | | 60 | #include <sys/kernel.h> |
61 | #include <sys/malloc.h> | | 61 | #include <sys/malloc.h> |
62 | #include <sys/kthread.h> | | 62 | #include <sys/kthread.h> |
63 | | | 63 | |
64 | #include <sys/bus.h> | | 64 | #include <sys/bus.h> |
65 | #include <sys/intr.h> | | 65 | #include <sys/intr.h> |
66 | | | 66 | |
67 | #include <dev/pcmcia/pcmciareg.h> | | 67 | #include <dev/pcmcia/pcmciareg.h> |
68 | #include <dev/pcmcia/pcmciavar.h> | | 68 | #include <dev/pcmcia/pcmciavar.h> |
69 | | | 69 | |
70 | #include <dev/ic/i82365reg.h> | | 70 | #include <dev/ic/i82365reg.h> |
71 | #include <dev/ic/i82365var.h> | | 71 | #include <dev/ic/i82365var.h> |
72 | | | 72 | |
73 | #include "locators.h" | | 73 | #include "locators.h" |
74 | | | 74 | |
75 | #ifdef PCICDEBUG | | 75 | #ifdef PCICDEBUG |
76 | int pcic_debug = 0; | | 76 | int pcic_debug = 0; |
77 | #define DPRINTF(arg) if (pcic_debug) printf arg; | | 77 | #define DPRINTF(arg) if (pcic_debug) printf arg; |
78 | #else | | 78 | #else |
79 | #define DPRINTF(arg) | | 79 | #define DPRINTF(arg) |
80 | #endif | | 80 | #endif |
81 | | | 81 | |
82 | /* | | 82 | /* |
83 | * Individual drivers will allocate their own memory and io regions. Memory | | 83 | * Individual drivers will allocate their own memory and io regions. Memory |
84 | * regions must be a multiple of 4k, aligned on a 4k boundary. | | 84 | * regions must be a multiple of 4k, aligned on a 4k boundary. |
85 | */ | | 85 | */ |
86 | | | 86 | |
87 | #define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE | | 87 | #define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE |
88 | | | 88 | |
89 | void pcic_attach_socket(struct pcic_handle *); | | 89 | void pcic_attach_socket(struct pcic_handle *); |
90 | void pcic_attach_socket_finish(struct pcic_handle *); | | 90 | void pcic_attach_socket_finish(struct pcic_handle *); |
91 | | | 91 | |
92 | int pcic_print (void *arg, const char *pnp); | | 92 | int pcic_print (void *arg, const char *pnp); |
93 | int pcic_intr_socket(struct pcic_handle *); | | 93 | int pcic_intr_socket(struct pcic_handle *); |
94 | void pcic_poll_intr(void *); | | 94 | void pcic_poll_intr(void *); |
95 | | | 95 | |
96 | void pcic_attach_card(struct pcic_handle *); | | 96 | void pcic_attach_card(struct pcic_handle *); |
97 | void pcic_detach_card(struct pcic_handle *, int); | | 97 | void pcic_detach_card(struct pcic_handle *, int); |
98 | void pcic_deactivate_card(struct pcic_handle *); | | 98 | void pcic_deactivate_card(struct pcic_handle *); |
99 | | | 99 | |
100 | void pcic_chip_do_mem_map(struct pcic_handle *, int); | | 100 | void pcic_chip_do_mem_map(struct pcic_handle *, int); |
101 | void pcic_chip_do_io_map(struct pcic_handle *, int); | | 101 | void pcic_chip_do_io_map(struct pcic_handle *, int); |
102 | | | 102 | |
103 | void pcic_event_thread(void *); | | 103 | void pcic_event_thread(void *); |
104 | | | 104 | |
105 | void pcic_queue_event(struct pcic_handle *, int); | | 105 | void pcic_queue_event(struct pcic_handle *, int); |
106 | void pcic_power(int, void *); | | 106 | void pcic_power(int, void *); |
107 | | | 107 | |
108 | static int pcic_wait_ready(struct pcic_handle *); | | 108 | static int pcic_wait_ready(struct pcic_handle *); |
109 | static void pcic_delay(struct pcic_handle *, int, const char *); | | 109 | static void pcic_delay(struct pcic_handle *, int, const char *); |
110 | | | 110 | |
111 | static uint8_t st_pcic_read(struct pcic_handle *, int); | | 111 | static uint8_t st_pcic_read(struct pcic_handle *, int); |
112 | static void st_pcic_write(struct pcic_handle *, int, uint8_t); | | 112 | static void st_pcic_write(struct pcic_handle *, int, uint8_t); |
113 | | | 113 | |
114 | int | | 114 | int |
115 | pcic_ident_ok(int ident) | | 115 | pcic_ident_ok(int ident) |
116 | { | | 116 | { |
117 | | | 117 | |
118 | /* this is very empirical and heuristic */ | | 118 | /* this is very empirical and heuristic */ |
119 | | | 119 | |
120 | if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO)) | | 120 | if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO)) |
121 | return 0; | | 121 | return 0; |
122 | | | 122 | |
123 | if ((ident & PCIC_IDENT_REV_MASK) == 0) | | 123 | if ((ident & PCIC_IDENT_REV_MASK) == 0) |
124 | return 0; | | 124 | return 0; |
125 | | | 125 | |
126 | if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) { | | 126 | if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) { |
127 | #ifdef DIAGNOSTIC | | 127 | #ifdef DIAGNOSTIC |
128 | printf("pcic: does not support memory and I/O cards, " | | 128 | printf("pcic: does not support memory and I/O cards, " |
129 | "ignored (ident=%0x)\n", ident); | | 129 | "ignored (ident=%0x)\n", ident); |
130 | #endif | | 130 | #endif |
131 | return 0; | | 131 | return 0; |
132 | } | | 132 | } |
133 | | | 133 | |
134 | return 1; | | 134 | return 1; |
135 | } | | 135 | } |
136 | | | 136 | |
137 | int | | 137 | int |
138 | pcic_vendor(struct pcic_handle *h) | | 138 | pcic_vendor(struct pcic_handle *h) |
139 | { | | 139 | { |
140 | int reg; | | 140 | int reg; |
141 | int vendor; | | 141 | int vendor; |
142 | | | 142 | |
143 | reg = pcic_read(h, PCIC_IDENT); | | 143 | reg = pcic_read(h, PCIC_IDENT); |
144 | | | 144 | |
145 | if ((reg & PCIC_IDENT_REV_MASK) == 0) | | 145 | if ((reg & PCIC_IDENT_REV_MASK) == 0) |
146 | return PCIC_VENDOR_NONE; | | 146 | return PCIC_VENDOR_NONE; |
147 | | | 147 | |
148 | switch (reg) { | | 148 | switch (reg) { |
149 | case 0x00: | | 149 | case 0x00: |
150 | case 0xff: | | 150 | case 0xff: |
151 | return PCIC_VENDOR_NONE; | | 151 | return PCIC_VENDOR_NONE; |
152 | case PCIC_IDENT_ID_INTEL0: | | 152 | case PCIC_IDENT_ID_INTEL0: |
153 | vendor = PCIC_VENDOR_I82365SLR0; | | 153 | vendor = PCIC_VENDOR_I82365SLR0; |
154 | break; | | 154 | break; |
155 | case PCIC_IDENT_ID_INTEL1: | | 155 | case PCIC_IDENT_ID_INTEL1: |
156 | vendor = PCIC_VENDOR_I82365SLR1; | | 156 | vendor = PCIC_VENDOR_I82365SLR1; |
157 | break; | | 157 | break; |
158 | case PCIC_IDENT_ID_INTEL2: | | 158 | case PCIC_IDENT_ID_INTEL2: |
159 | vendor = PCIC_VENDOR_I82365SL_DF; | | 159 | vendor = PCIC_VENDOR_I82365SL_DF; |
160 | break; | | 160 | break; |
161 | case PCIC_IDENT_ID_IBM1: | | 161 | case PCIC_IDENT_ID_IBM1: |
162 | case PCIC_IDENT_ID_IBM2: | | 162 | case PCIC_IDENT_ID_IBM2: |
163 | vendor = PCIC_VENDOR_IBM; | | 163 | vendor = PCIC_VENDOR_IBM; |
164 | break; | | 164 | break; |
165 | case PCIC_IDENT_ID_IBM3: | | 165 | case PCIC_IDENT_ID_IBM3: |
166 | vendor = PCIC_VENDOR_IBM_KING; | | 166 | vendor = PCIC_VENDOR_IBM_KING; |
167 | break; | | 167 | break; |
168 | default: | | 168 | default: |
169 | vendor = PCIC_VENDOR_UNKNOWN; | | 169 | vendor = PCIC_VENDOR_UNKNOWN; |
170 | break; | | 170 | break; |
171 | } | | 171 | } |
172 | | | 172 | |
173 | if (vendor == PCIC_VENDOR_I82365SLR0 || | | 173 | if (vendor == PCIC_VENDOR_I82365SLR0 || |
174 | vendor == PCIC_VENDOR_I82365SLR1) { | | 174 | vendor == PCIC_VENDOR_I82365SLR1) { |
175 | /* | | 175 | /* |
176 | * Check for Cirrus PD67xx. | | 176 | * Check for Cirrus PD67xx. |
177 | * the chip_id of the cirrus toggles between 11 and 00 after a | | 177 | * the chip_id of the cirrus toggles between 11 and 00 after a |
178 | * write. weird. | | 178 | * write. weird. |
179 | */ | | 179 | */ |
180 | pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0); | | 180 | pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0); |
181 | reg = pcic_read(h, -1); | | 181 | reg = pcic_read(h, -1); |
182 | if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == | | 182 | if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == |
183 | PCIC_CIRRUS_CHIP_INFO_CHIP_ID) { | | 183 | PCIC_CIRRUS_CHIP_INFO_CHIP_ID) { |
184 | reg = pcic_read(h, -1); | | 184 | reg = pcic_read(h, -1); |
185 | if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) | | 185 | if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) |
186 | return PCIC_VENDOR_CIRRUS_PD67XX; | | 186 | return PCIC_VENDOR_CIRRUS_PD67XX; |
187 | } | | 187 | } |
188 | | | 188 | |
189 | /* | | 189 | /* |
190 | * check for Ricoh RF5C[23]96 | | 190 | * check for Ricoh RF5C[23]96 |
191 | */ | | 191 | */ |
192 | reg = pcic_read(h, PCIC_RICOH_REG_CHIP_ID); | | 192 | reg = pcic_read(h, PCIC_RICOH_REG_CHIP_ID); |
193 | switch (reg) { | | 193 | switch (reg) { |
194 | case PCIC_RICOH_CHIP_ID_5C296: | | 194 | case PCIC_RICOH_CHIP_ID_5C296: |
195 | return PCIC_VENDOR_RICOH_5C296; | | 195 | return PCIC_VENDOR_RICOH_5C296; |
196 | case PCIC_RICOH_CHIP_ID_5C396: | | 196 | case PCIC_RICOH_CHIP_ID_5C396: |
197 | return PCIC_VENDOR_RICOH_5C396; | | 197 | return PCIC_VENDOR_RICOH_5C396; |
198 | } | | 198 | } |
199 | } | | 199 | } |
200 | | | 200 | |
201 | return vendor; | | 201 | return vendor; |
202 | } | | 202 | } |
203 | | | 203 | |
204 | const char * | | 204 | const char * |
205 | pcic_vendor_to_string(int vendor) | | 205 | pcic_vendor_to_string(int vendor) |
206 | { | | 206 | { |
207 | | | 207 | |
208 | switch (vendor) { | | 208 | switch (vendor) { |
209 | case PCIC_VENDOR_I82365SLR0: | | 209 | case PCIC_VENDOR_I82365SLR0: |
210 | return "Intel 82365SL Revision 0"; | | 210 | return "Intel 82365SL Revision 0"; |
211 | case PCIC_VENDOR_I82365SLR1: | | 211 | case PCIC_VENDOR_I82365SLR1: |
212 | return "Intel 82365SL Revision 1"; | | 212 | return "Intel 82365SL Revision 1"; |
213 | case PCIC_VENDOR_CIRRUS_PD67XX: | | 213 | case PCIC_VENDOR_CIRRUS_PD67XX: |
214 | return "Cirrus PD6710/2X"; | | 214 | return "Cirrus PD6710/2X"; |
215 | case PCIC_VENDOR_I82365SL_DF: | | 215 | case PCIC_VENDOR_I82365SL_DF: |
216 | return "Intel 82365SL-DF"; | | 216 | return "Intel 82365SL-DF"; |
217 | case PCIC_VENDOR_RICOH_5C296: | | 217 | case PCIC_VENDOR_RICOH_5C296: |
218 | return "Ricoh RF5C296"; | | 218 | return "Ricoh RF5C296"; |
219 | case PCIC_VENDOR_RICOH_5C396: | | 219 | case PCIC_VENDOR_RICOH_5C396: |
220 | return "Ricoh RF5C396"; | | 220 | return "Ricoh RF5C396"; |
221 | case PCIC_VENDOR_IBM: | | 221 | case PCIC_VENDOR_IBM: |
222 | return "IBM PCIC"; | | 222 | return "IBM PCIC"; |
223 | case PCIC_VENDOR_IBM_KING: | | 223 | case PCIC_VENDOR_IBM_KING: |
224 | return "IBM KING"; | | 224 | return "IBM KING"; |
225 | } | | 225 | } |
226 | | | 226 | |
227 | return "Unknown controller"; | | 227 | return "Unknown controller"; |
228 | } | | 228 | } |
229 | | | 229 | |
230 | void | | 230 | void |
231 | pcic_attach(struct pcic_softc *sc) | | 231 | pcic_attach(struct pcic_softc *sc) |
232 | { | | 232 | { |
233 | int i, reg, chip, socket; | | 233 | int i, reg, chip, socket; |
234 | struct pcic_handle *h; | | 234 | struct pcic_handle *h; |
235 | device_t self; | | 235 | device_t self; |
236 | | | 236 | |
237 | DPRINTF(("pcic ident regs:")); | | 237 | DPRINTF(("pcic ident regs:")); |
238 | | | 238 | |
239 | self = &sc->dev; | | 239 | self = &sc->dev; |
240 | mutex_init(&sc->sc_pcic_lock, MUTEX_DEFAULT, IPL_NONE); | | 240 | mutex_init(&sc->sc_pcic_lock, MUTEX_DEFAULT, IPL_NONE); |
241 | | | 241 | |
242 | /* find and configure for the available sockets */ | | 242 | /* find and configure for the available sockets */ |
243 | for (i = 0; i < __arraycount(sc->handle); i++) { | | 243 | for (i = 0; i < __arraycount(sc->handle); i++) { |
244 | h = &sc->handle[i]; | | 244 | h = &sc->handle[i]; |
245 | chip = i / 2; | | 245 | chip = i / 2; |
246 | socket = i % 2; | | 246 | socket = i % 2; |
247 | | | 247 | |
248 | h->ph_parent = self; | | 248 | h->ph_parent = self; |
249 | h->chip = chip; | | 249 | h->chip = chip; |
250 | h->socket = socket; | | 250 | h->socket = socket; |
251 | h->sock = chip * PCIC_CHIP_OFFSET + socket * PCIC_SOCKET_OFFSET; | | 251 | h->sock = chip * PCIC_CHIP_OFFSET + socket * PCIC_SOCKET_OFFSET; |
252 | h->laststate = PCIC_LASTSTATE_EMPTY; | | 252 | h->laststate = PCIC_LASTSTATE_EMPTY; |
253 | /* initialize pcic_read and pcic_write functions */ | | 253 | /* initialize pcic_read and pcic_write functions */ |
254 | h->ph_read = st_pcic_read; | | 254 | h->ph_read = st_pcic_read; |
255 | h->ph_write = st_pcic_write; | | 255 | h->ph_write = st_pcic_write; |
256 | h->ph_bus_t = sc->iot; | | 256 | h->ph_bus_t = sc->iot; |
257 | h->ph_bus_h = sc->ioh; | | 257 | h->ph_bus_h = sc->ioh; |
258 | h->flags = 0; | | 258 | h->flags = 0; |
259 | | | 259 | |
260 | /* need to read vendor -- for cirrus to report no xtra chip */ | | 260 | /* need to read vendor -- for cirrus to report no xtra chip */ |
261 | if (socket == 0) { | | 261 | if (socket == 0) { |
262 | h->vendor = pcic_vendor(h); | | 262 | h->vendor = pcic_vendor(h); |
263 | if (i < __arraycount(sc->handle) - 1) | | 263 | if (i < __arraycount(sc->handle) - 1) |
264 | (h + 1)->vendor = h->vendor; | | 264 | (h + 1)->vendor = h->vendor; |
265 | } | | 265 | } |
266 | | | 266 | |
267 | switch (h->vendor) { | | 267 | switch (h->vendor) { |
268 | case PCIC_VENDOR_NONE: | | 268 | case PCIC_VENDOR_NONE: |
269 | /* no chip */ | | 269 | /* no chip */ |
270 | continue; | | 270 | continue; |
271 | case PCIC_VENDOR_CIRRUS_PD67XX: | | 271 | case PCIC_VENDOR_CIRRUS_PD67XX: |
272 | reg = pcic_read(h, PCIC_CIRRUS_CHIP_INFO); | | 272 | reg = pcic_read(h, PCIC_CIRRUS_CHIP_INFO); |
273 | if (socket == 0 || | | 273 | if (socket == 0 || |
274 | (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)) | | 274 | (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)) |
275 | h->flags = PCIC_FLAG_SOCKETP; | | 275 | h->flags = PCIC_FLAG_SOCKETP; |
276 | break; | | 276 | break; |
277 | default: | | 277 | default: |
278 | /* | | 278 | /* |
279 | * During the socket probe, read the ident register | | 279 | * During the socket probe, read the ident register |
280 | * twice. I don't understand why, but sometimes the | | 280 | * twice. I don't understand why, but sometimes the |
281 | * clone chips in hpcmips boxes read all-0s the first | | 281 | * clone chips in hpcmips boxes read all-0s the first |
282 | * time. -- mycroft | | 282 | * time. -- mycroft |
283 | */ | | 283 | */ |
284 | reg = pcic_read(h, PCIC_IDENT); | | 284 | reg = pcic_read(h, PCIC_IDENT); |
285 | DPRINTF(("socket %d ident reg 0x%02x\n", i, reg)); | | 285 | DPRINTF(("socket %d ident reg 0x%02x\n", i, reg)); |
286 | reg = pcic_read(h, PCIC_IDENT); | | 286 | reg = pcic_read(h, PCIC_IDENT); |
287 | DPRINTF(("socket %d ident reg 0x%02x\n", i, reg)); | | 287 | DPRINTF(("socket %d ident reg 0x%02x\n", i, reg)); |
288 | if (pcic_ident_ok(reg)) | | 288 | if (pcic_ident_ok(reg)) |
289 | h->flags = PCIC_FLAG_SOCKETP; | | 289 | h->flags = PCIC_FLAG_SOCKETP; |
290 | break; | | 290 | break; |
291 | } | | 291 | } |
292 | } | | 292 | } |
293 | | | 293 | |
294 | for (i = 0; i < __arraycount(sc->handle); i++) { | | 294 | for (i = 0; i < __arraycount(sc->handle); i++) { |
295 | h = &sc->handle[i]; | | 295 | h = &sc->handle[i]; |
296 | | | 296 | |
297 | if (h->flags & PCIC_FLAG_SOCKETP) { | | 297 | if (h->flags & PCIC_FLAG_SOCKETP) { |
298 | SIMPLEQ_INIT(&h->events); | | 298 | SIMPLEQ_INIT(&h->events); |
299 | | | 299 | |
300 | /* disable interrupts and leave socket in reset */ | | 300 | /* disable interrupts and leave socket in reset */ |
301 | pcic_write(h, PCIC_INTR, 0); | | 301 | pcic_write(h, PCIC_INTR, 0); |
302 | | | 302 | |
303 | /* zero out the address windows */ | | 303 | /* zero out the address windows */ |
304 | pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); | | 304 | pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); |
305 | | | 305 | |
306 | /* power down the socket */ | | 306 | /* power down the socket */ |
307 | pcic_write(h, PCIC_PWRCTL, 0); | | 307 | pcic_write(h, PCIC_PWRCTL, 0); |
308 | | | 308 | |
309 | pcic_write(h, PCIC_CSC_INTR, 0); | | 309 | pcic_write(h, PCIC_CSC_INTR, 0); |
310 | (void) pcic_read(h, PCIC_CSC); | | 310 | (void) pcic_read(h, PCIC_CSC); |
311 | } | | 311 | } |
312 | } | | 312 | } |
313 | | | 313 | |
314 | /* print detected info */ | | 314 | /* print detected info */ |
315 | for (i = 0; i < __arraycount(sc->handle) - 1; i += 2) { | | 315 | for (i = 0; i < __arraycount(sc->handle) - 1; i += 2) { |
316 | h = &sc->handle[i]; | | 316 | h = &sc->handle[i]; |
317 | chip = i / 2; | | 317 | chip = i / 2; |
318 | | | 318 | |
319 | if (h->vendor == PCIC_VENDOR_NONE) | | 319 | if (h->vendor == PCIC_VENDOR_NONE) |
320 | continue; | | 320 | continue; |
321 | | | 321 | |
322 | aprint_normal_dev(self, "controller %d (%s) has ", | | 322 | aprint_normal_dev(self, "controller %d (%s) has ", |
323 | chip, pcic_vendor_to_string(sc->handle[i].vendor)); | | 323 | chip, pcic_vendor_to_string(sc->handle[i].vendor)); |
324 | | | 324 | |
325 | if ((h->flags & PCIC_FLAG_SOCKETP) && | | 325 | if ((h->flags & PCIC_FLAG_SOCKETP) && |
326 | ((h + 1)->flags & PCIC_FLAG_SOCKETP)) | | 326 | ((h + 1)->flags & PCIC_FLAG_SOCKETP)) |
327 | aprint_normal("sockets A and B\n"); | | 327 | aprint_normal("sockets A and B\n"); |
328 | else if (h->flags & PCIC_FLAG_SOCKETP) | | 328 | else if (h->flags & PCIC_FLAG_SOCKETP) |
329 | aprint_normal("socket A only\n"); | | 329 | aprint_normal("socket A only\n"); |
330 | else if ((h + 1)->flags & PCIC_FLAG_SOCKETP) | | 330 | else if ((h + 1)->flags & PCIC_FLAG_SOCKETP) |
331 | aprint_normal("socket B only\n"); | | 331 | aprint_normal("socket B only\n"); |
332 | else | | 332 | else |
333 | aprint_normal("no sockets\n"); | | 333 | aprint_normal("no sockets\n"); |
334 | } | | 334 | } |
335 | } | | 335 | } |
336 | | | 336 | |
337 | /* | | 337 | /* |
338 | * attach the sockets before we know what interrupts we have | | 338 | * attach the sockets before we know what interrupts we have |
339 | */ | | 339 | */ |
340 | void | | 340 | void |
341 | pcic_attach_sockets(struct pcic_softc *sc) | | 341 | pcic_attach_sockets(struct pcic_softc *sc) |
342 | { | | 342 | { |
343 | int i; | | 343 | int i; |
344 | | | 344 | |
345 | for (i = 0; i < __arraycount(sc->handle); i++) | | 345 | for (i = 0; i < __arraycount(sc->handle); i++) |
346 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) | | 346 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) |
347 | pcic_attach_socket(&sc->handle[i]); | | 347 | pcic_attach_socket(&sc->handle[i]); |
348 | } | | 348 | } |
349 | | | 349 | |
350 | void | | 350 | void |
351 | pcic_power(int why, void *arg) | | 351 | pcic_power(int why, void *arg) |
352 | { | | 352 | { |
353 | struct pcic_handle *h = arg; | | 353 | struct pcic_handle *h = arg; |
354 | struct pcic_softc *sc = device_private(h->ph_parent); | | 354 | struct pcic_softc *sc = device_private(h->ph_parent); |
355 | int reg; | | 355 | int reg; |
356 | | | 356 | |
357 | DPRINTF(("%s: power: why %d\n", device_xname(h->ph_parent), why)); | | 357 | DPRINTF(("%s: power: why %d\n", device_xname(h->ph_parent), why)); |
358 | | | 358 | |
359 | if (h->flags & PCIC_FLAG_SOCKETP) { | | 359 | if (h->flags & PCIC_FLAG_SOCKETP) { |
360 | if ((why == PWR_RESUME) && | | 360 | if ((why == PWR_RESUME) && |
361 | (pcic_read(h, PCIC_CSC_INTR) == 0)) { | | 361 | (pcic_read(h, PCIC_CSC_INTR) == 0)) { |
362 | #ifdef PCICDEBUG | | 362 | #ifdef PCICDEBUG |
363 | char bitbuf[64]; | | 363 | char bitbuf[64]; |
364 | #endif | | 364 | #endif |
365 | reg = PCIC_CSC_INTR_CD_ENABLE; | | 365 | reg = PCIC_CSC_INTR_CD_ENABLE; |
366 | if (sc->irq != -1) | | 366 | if (sc->irq != -1) |
367 | reg |= sc->irq << PCIC_CSC_INTR_IRQ_SHIFT; | | 367 | reg |= sc->irq << PCIC_CSC_INTR_IRQ_SHIFT; |
368 | pcic_write(h, PCIC_CSC_INTR, reg); | | 368 | pcic_write(h, PCIC_CSC_INTR, reg); |
369 | #ifdef PCICDEBUG | | 369 | #ifdef PCICDEBUG |
370 | snprintb(bitbuf, sizeof(bitbuf), PCIC_CSC_INTR_FORMAT, | | 370 | snprintb(bitbuf, sizeof(bitbuf), PCIC_CSC_INTR_FORMAT, |
371 | pcic_read(h, PCIC_CSC_INTR)); | | 371 | pcic_read(h, PCIC_CSC_INTR)); |
372 | #endif | | 372 | #endif |
373 | DPRINTF(("%s: CSC_INTR was zero; reset to %s\n", | | 373 | DPRINTF(("%s: CSC_INTR was zero; reset to %s\n", |
374 | device_xname(&sc->dev), bitbuf)); | | 374 | device_xname(&sc->dev), bitbuf)); |
375 | } | | 375 | } |
376 | | | 376 | |
377 | /* | | 377 | /* |
378 | * check for card insertion or removal during suspend period. | | 378 | * check for card insertion or removal during suspend period. |
379 | * XXX: the code can't cope with card swap (remove then insert). | | 379 | * XXX: the code can't cope with card swap (remove then insert). |
380 | * how can we detect such situation? | | 380 | * how can we detect such situation? |
381 | */ | | 381 | */ |
382 | if (why == PWR_RESUME) | | 382 | if (why == PWR_RESUME) |
383 | (void)pcic_intr_socket(h); | | 383 | (void)pcic_intr_socket(h); |
384 | } | | 384 | } |
385 | } | | 385 | } |
386 | | | 386 | |
387 | | | 387 | |
388 | /* | | 388 | /* |
389 | * attach a socket -- we don't know about irqs yet | | 389 | * attach a socket -- we don't know about irqs yet |
390 | */ | | 390 | */ |
391 | void | | 391 | void |
392 | pcic_attach_socket(struct pcic_handle *h) | | 392 | pcic_attach_socket(struct pcic_handle *h) |
393 | { | | 393 | { |
394 | struct pcmciabus_attach_args paa; | | 394 | struct pcmciabus_attach_args paa; |
395 | struct pcic_softc *sc = device_private(h->ph_parent); | | 395 | struct pcic_softc *sc = device_private(h->ph_parent); |
396 | int locs[PCMCIABUSCF_NLOCS]; | | 396 | int locs[PCMCIABUSCF_NLOCS]; |
397 | | | 397 | |
398 | /* initialize the rest of the handle */ | | 398 | /* initialize the rest of the handle */ |
399 | | | 399 | |
400 | h->shutdown = 0; | | 400 | h->shutdown = 0; |
401 | h->memalloc = 0; | | 401 | h->memalloc = 0; |
402 | h->ioalloc = 0; | | 402 | h->ioalloc = 0; |
403 | h->ih_irq = 0; | | 403 | h->ih_irq = 0; |
404 | | | 404 | |
405 | /* now, config one pcmcia device per socket */ | | 405 | /* now, config one pcmcia device per socket */ |
406 | | | 406 | |
407 | paa.paa_busname = "pcmcia"; | | 407 | paa.paa_busname = "pcmcia"; |
408 | paa.pct = (pcmcia_chipset_tag_t) sc->pct; | | 408 | paa.pct = (pcmcia_chipset_tag_t) sc->pct; |
409 | paa.pch = (pcmcia_chipset_handle_t) h; | | 409 | paa.pch = (pcmcia_chipset_handle_t) h; |
410 | paa.iobase = sc->iobase; | | | |
411 | paa.iosize = sc->iosize; | | | |
412 | | | 410 | |
413 | locs[PCMCIABUSCF_CONTROLLER] = h->chip; | | 411 | locs[PCMCIABUSCF_CONTROLLER] = h->chip; |
414 | locs[PCMCIABUSCF_SOCKET] = h->socket; | | 412 | locs[PCMCIABUSCF_SOCKET] = h->socket; |
415 | | | 413 | |
416 | h->pcmcia = config_found_sm_loc(&sc->dev, "pcmciabus", locs, &paa, | | 414 | h->pcmcia = config_found_sm_loc(&sc->dev, "pcmciabus", locs, &paa, |
417 | pcic_print, config_stdsubmatch); | | 415 | pcic_print, config_stdsubmatch); |
418 | if (h->pcmcia == NULL) { | | 416 | if (h->pcmcia == NULL) { |
419 | h->flags &= ~PCIC_FLAG_SOCKETP; | | 417 | h->flags &= ~PCIC_FLAG_SOCKETP; |
420 | return; | | 418 | return; |
421 | } | | 419 | } |
422 | | | 420 | |
423 | } | | 421 | } |
424 | | | 422 | |
425 | /* | | 423 | /* |
426 | * now finish attaching the sockets, we are ready to allocate | | 424 | * now finish attaching the sockets, we are ready to allocate |
427 | * interrupts | | 425 | * interrupts |
428 | */ | | 426 | */ |
429 | void | | 427 | void |
430 | pcic_attach_sockets_finish(struct pcic_softc *sc) | | 428 | pcic_attach_sockets_finish(struct pcic_softc *sc) |
431 | { | | 429 | { |
432 | int i; | | 430 | int i; |
433 | | | 431 | |
434 | for (i = 0; i < __arraycount(sc->handle); i++) | | 432 | for (i = 0; i < __arraycount(sc->handle); i++) |
435 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) | | 433 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) |
436 | pcic_attach_socket_finish(&sc->handle[i]); | | 434 | pcic_attach_socket_finish(&sc->handle[i]); |
437 | } | | 435 | } |
438 | | | 436 | |
439 | /* | | 437 | /* |
440 | * finishing attaching the socket. Interrupts may now be on | | 438 | * finishing attaching the socket. Interrupts may now be on |
441 | * if so expects the pcic interrupt to be blocked | | 439 | * if so expects the pcic interrupt to be blocked |
442 | */ | | 440 | */ |
443 | void | | 441 | void |
444 | pcic_attach_socket_finish(struct pcic_handle *h) | | 442 | pcic_attach_socket_finish(struct pcic_handle *h) |
445 | { | | 443 | { |
446 | struct pcic_softc *sc = device_private(h->ph_parent); | | 444 | struct pcic_softc *sc = device_private(h->ph_parent); |
447 | int reg; | | 445 | int reg; |
448 | char cs[4]; | | 446 | char cs[4]; |
449 | | | 447 | |
450 | DPRINTF(("%s: attach finish socket %ld\n", device_xname(h->ph_parent), | | 448 | DPRINTF(("%s: attach finish socket %ld\n", device_xname(h->ph_parent), |
451 | (long) (h - &sc->handle[0]))); | | 449 | (long) (h - &sc->handle[0]))); |
452 | | | 450 | |
453 | /* | | 451 | /* |
454 | * Set up a powerhook to ensure it continues to interrupt on | | 452 | * Set up a powerhook to ensure it continues to interrupt on |
455 | * card detect even after suspend. | | 453 | * card detect even after suspend. |
456 | * (this works around a bug seen in suspend-to-disk on the | | 454 | * (this works around a bug seen in suspend-to-disk on the |
457 | * Sony VAIO Z505; on resume, the CSC_INTR state is not preserved). | | 455 | * Sony VAIO Z505; on resume, the CSC_INTR state is not preserved). |
458 | */ | | 456 | */ |
459 | powerhook_establish(device_xname(h->ph_parent), pcic_power, h); | | 457 | powerhook_establish(device_xname(h->ph_parent), pcic_power, h); |
460 | | | 458 | |
461 | /* enable interrupts on card detect, poll for them if no irq avail */ | | 459 | /* enable interrupts on card detect, poll for them if no irq avail */ |
462 | reg = PCIC_CSC_INTR_CD_ENABLE; | | 460 | reg = PCIC_CSC_INTR_CD_ENABLE; |
463 | if (sc->irq == -1) { | | 461 | if (sc->irq == -1) { |
464 | if (sc->poll_established == 0) { | | 462 | if (sc->poll_established == 0) { |
465 | callout_init(&sc->poll_ch, 0); | | 463 | callout_init(&sc->poll_ch, 0); |
466 | callout_reset(&sc->poll_ch, hz / 2, pcic_poll_intr, sc); | | 464 | callout_reset(&sc->poll_ch, hz / 2, pcic_poll_intr, sc); |
467 | sc->poll_established = 1; | | 465 | sc->poll_established = 1; |
468 | } | | 466 | } |
469 | } else | | 467 | } else |
470 | reg |= sc->irq << PCIC_CSC_INTR_IRQ_SHIFT; | | 468 | reg |= sc->irq << PCIC_CSC_INTR_IRQ_SHIFT; |
471 | pcic_write(h, PCIC_CSC_INTR, reg); | | 469 | pcic_write(h, PCIC_CSC_INTR, reg); |
472 | | | 470 | |
473 | /* steer above mgmt interrupt to configured place */ | | 471 | /* steer above mgmt interrupt to configured place */ |
474 | if (sc->irq == 0) | | 472 | if (sc->irq == 0) |
475 | pcic_write(h, PCIC_INTR, PCIC_INTR_ENABLE); | | 473 | pcic_write(h, PCIC_INTR, PCIC_INTR_ENABLE); |
476 | | | 474 | |
477 | /* clear possible card detect interrupt */ | | 475 | /* clear possible card detect interrupt */ |
478 | (void) pcic_read(h, PCIC_CSC); | | 476 | (void) pcic_read(h, PCIC_CSC); |
479 | | | 477 | |
480 | DPRINTF(("%s: attach finish vendor 0x%02x\n", | | 478 | DPRINTF(("%s: attach finish vendor 0x%02x\n", |
481 | device_xname(h->ph_parent), h->vendor)); | | 479 | device_xname(h->ph_parent), h->vendor)); |
482 | | | 480 | |
483 | /* unsleep the cirrus controller */ | | 481 | /* unsleep the cirrus controller */ |
484 | if (h->vendor == PCIC_VENDOR_CIRRUS_PD67XX) { | | 482 | if (h->vendor == PCIC_VENDOR_CIRRUS_PD67XX) { |
485 | reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2); | | 483 | reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2); |
486 | if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) { | | 484 | if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) { |
487 | DPRINTF(("%s: socket %02x was suspended\n", | | 485 | DPRINTF(("%s: socket %02x was suspended\n", |
488 | device_xname(h->ph_parent), h->sock)); | | 486 | device_xname(h->ph_parent), h->sock)); |
489 | reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND; | | 487 | reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND; |
490 | pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); | | 488 | pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); |
491 | } | | 489 | } |
492 | } | | 490 | } |
493 | | | 491 | |
494 | /* if there's a card there, then attach it. */ | | 492 | /* if there's a card there, then attach it. */ |
495 | reg = pcic_read(h, PCIC_IF_STATUS); | | 493 | reg = pcic_read(h, PCIC_IF_STATUS); |
496 | if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == | | 494 | if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == |
497 | PCIC_IF_STATUS_CARDDETECT_PRESENT) { | | 495 | PCIC_IF_STATUS_CARDDETECT_PRESENT) { |
498 | pcic_queue_event(h, PCIC_EVENT_INSERTION); | | 496 | pcic_queue_event(h, PCIC_EVENT_INSERTION); |
499 | h->laststate = PCIC_LASTSTATE_PRESENT; | | 497 | h->laststate = PCIC_LASTSTATE_PRESENT; |
500 | } else { | | 498 | } else { |
501 | h->laststate = PCIC_LASTSTATE_EMPTY; | | 499 | h->laststate = PCIC_LASTSTATE_EMPTY; |
502 | } | | 500 | } |
503 | | | 501 | |
504 | /* | | 502 | /* |
505 | * queue creation of a kernel thread to handle insert/removal events. | | 503 | * queue creation of a kernel thread to handle insert/removal events. |
506 | */ | | 504 | */ |
507 | #ifdef DIAGNOSTIC | | 505 | #ifdef DIAGNOSTIC |
508 | if (h->event_thread != NULL) | | 506 | if (h->event_thread != NULL) |
509 | panic("pcic_attach_socket: event thread"); | | 507 | panic("pcic_attach_socket: event thread"); |
510 | #endif | | 508 | #endif |
511 | config_pending_incr(); | | 509 | config_pending_incr(); |
512 | snprintf(cs, sizeof(cs), "%d,%d", h->chip, h->socket); | | 510 | snprintf(cs, sizeof(cs), "%d,%d", h->chip, h->socket); |
513 | | | 511 | |
514 | if (kthread_create(PRI_NONE, 0, NULL, pcic_event_thread, h, | | 512 | if (kthread_create(PRI_NONE, 0, NULL, pcic_event_thread, h, |
515 | &h->event_thread, "%s,%s", device_xname(h->ph_parent), cs)) { | | 513 | &h->event_thread, "%s,%s", device_xname(h->ph_parent), cs)) { |
516 | aprint_error_dev(h->ph_parent, | | 514 | aprint_error_dev(h->ph_parent, |
517 | "unable to create event thread for sock 0x%02x\n", h->sock); | | 515 | "unable to create event thread for sock 0x%02x\n", h->sock); |
518 | panic("pcic_attach_socket"); | | 516 | panic("pcic_attach_socket"); |
519 | } | | 517 | } |
520 | } | | 518 | } |
521 | | | 519 | |
522 | void | | 520 | void |
523 | pcic_event_thread(void *arg) | | 521 | pcic_event_thread(void *arg) |
524 | { | | 522 | { |
525 | struct pcic_handle *h = arg; | | 523 | struct pcic_handle *h = arg; |
526 | struct pcic_event *pe; | | 524 | struct pcic_event *pe; |
527 | int s, first = 1; | | 525 | int s, first = 1; |
528 | struct pcic_softc *sc = device_private(h->ph_parent); | | 526 | struct pcic_softc *sc = device_private(h->ph_parent); |
529 | | | 527 | |
530 | while (h->shutdown == 0) { | | 528 | while (h->shutdown == 0) { |
531 | /* | | 529 | /* |
532 | * Serialize event processing on the PCIC. We may | | 530 | * Serialize event processing on the PCIC. We may |
533 | * sleep while we hold this lock. | | 531 | * sleep while we hold this lock. |
534 | */ | | 532 | */ |
535 | mutex_enter(&sc->sc_pcic_lock); | | 533 | mutex_enter(&sc->sc_pcic_lock); |
536 | | | 534 | |
537 | s = splhigh(); | | 535 | s = splhigh(); |
538 | if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) { | | 536 | if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) { |
539 | splx(s); | | 537 | splx(s); |
540 | if (first) { | | 538 | if (first) { |
541 | first = 0; | | 539 | first = 0; |
542 | config_pending_decr(); | | 540 | config_pending_decr(); |
543 | } | | 541 | } |
544 | /* | | 542 | /* |
545 | * No events to process; release the PCIC lock. | | 543 | * No events to process; release the PCIC lock. |
546 | */ | | 544 | */ |
547 | (void) mutex_exit(&sc->sc_pcic_lock); | | 545 | (void) mutex_exit(&sc->sc_pcic_lock); |
548 | (void) tsleep(&h->events, PWAIT, "pcicev", 0); | | 546 | (void) tsleep(&h->events, PWAIT, "pcicev", 0); |
549 | continue; | | 547 | continue; |
550 | } else { | | 548 | } else { |
551 | splx(s); | | 549 | splx(s); |
552 | /* sleep .25s to be enqueued chatterling interrupts */ | | 550 | /* sleep .25s to be enqueued chatterling interrupts */ |
553 | (void) tsleep((void *)pcic_event_thread, PWAIT, | | 551 | (void) tsleep((void *)pcic_event_thread, PWAIT, |
554 | "pcicss", hz / 4); | | 552 | "pcicss", hz / 4); |
555 | } | | 553 | } |
556 | s = splhigh(); | | 554 | s = splhigh(); |
557 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); | | 555 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); |
558 | splx(s); | | 556 | splx(s); |
559 | | | 557 | |
560 | switch (pe->pe_type) { | | 558 | switch (pe->pe_type) { |
561 | case PCIC_EVENT_INSERTION: | | 559 | case PCIC_EVENT_INSERTION: |
562 | s = splhigh(); | | 560 | s = splhigh(); |
563 | for (;;) { | | 561 | for (;;) { |
564 | struct pcic_event *pe1, *pe2; | | 562 | struct pcic_event *pe1, *pe2; |
565 | | | 563 | |
566 | if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) | | 564 | if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) |
567 | break; | | 565 | break; |
568 | if (pe1->pe_type != PCIC_EVENT_REMOVAL) | | 566 | if (pe1->pe_type != PCIC_EVENT_REMOVAL) |
569 | break; | | 567 | break; |
570 | if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) | | 568 | if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) |
571 | break; | | 569 | break; |
572 | if (pe2->pe_type == PCIC_EVENT_INSERTION) { | | 570 | if (pe2->pe_type == PCIC_EVENT_INSERTION) { |
573 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); | | 571 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); |
574 | free(pe1, M_TEMP); | | 572 | free(pe1, M_TEMP); |
575 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); | | 573 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); |
576 | free(pe2, M_TEMP); | | 574 | free(pe2, M_TEMP); |
577 | } | | 575 | } |
578 | } | | 576 | } |
579 | splx(s); | | 577 | splx(s); |
580 | | | 578 | |
581 | DPRINTF(("%s: insertion event\n", | | 579 | DPRINTF(("%s: insertion event\n", |
582 | device_xname(h->ph_parent))); | | 580 | device_xname(h->ph_parent))); |
583 | pcic_attach_card(h); | | 581 | pcic_attach_card(h); |
584 | break; | | 582 | break; |
585 | | | 583 | |
586 | case PCIC_EVENT_REMOVAL: | | 584 | case PCIC_EVENT_REMOVAL: |
587 | s = splhigh(); | | 585 | s = splhigh(); |
588 | for (;;) { | | 586 | for (;;) { |
589 | struct pcic_event *pe1, *pe2; | | 587 | struct pcic_event *pe1, *pe2; |
590 | | | 588 | |
591 | if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) | | 589 | if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) |
592 | break; | | 590 | break; |
593 | if (pe1->pe_type != PCIC_EVENT_INSERTION) | | 591 | if (pe1->pe_type != PCIC_EVENT_INSERTION) |
594 | break; | | 592 | break; |
595 | if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) | | 593 | if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) |
596 | break; | | 594 | break; |
597 | if (pe2->pe_type == PCIC_EVENT_REMOVAL) { | | 595 | if (pe2->pe_type == PCIC_EVENT_REMOVAL) { |
598 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); | | 596 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); |
599 | free(pe1, M_TEMP); | | 597 | free(pe1, M_TEMP); |
600 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); | | 598 | SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); |
601 | free(pe2, M_TEMP); | | 599 | free(pe2, M_TEMP); |
602 | } | | 600 | } |
603 | } | | 601 | } |
604 | splx(s); | | 602 | splx(s); |
605 | | | 603 | |
606 | DPRINTF(("%s: removal event\n", | | 604 | DPRINTF(("%s: removal event\n", |
607 | device_xname(h->ph_parent))); | | 605 | device_xname(h->ph_parent))); |
608 | pcic_detach_card(h, DETACH_FORCE); | | 606 | pcic_detach_card(h, DETACH_FORCE); |
609 | break; | | 607 | break; |
610 | | | 608 | |
611 | default: | | 609 | default: |
612 | panic("pcic_event_thread: unknown event %d", | | 610 | panic("pcic_event_thread: unknown event %d", |
613 | pe->pe_type); | | 611 | pe->pe_type); |
614 | } | | 612 | } |
615 | free(pe, M_TEMP); | | 613 | free(pe, M_TEMP); |
616 | | | 614 | |
617 | mutex_exit(&sc->sc_pcic_lock); | | 615 | mutex_exit(&sc->sc_pcic_lock); |
618 | } | | 616 | } |
619 | | | 617 | |
620 | h->event_thread = NULL; | | 618 | h->event_thread = NULL; |
621 | | | 619 | |
622 | /* In case parent is waiting for us to exit. */ | | 620 | /* In case parent is waiting for us to exit. */ |
623 | wakeup(sc); | | 621 | wakeup(sc); |
624 | | | 622 | |
625 | kthread_exit(0); | | 623 | kthread_exit(0); |
626 | } | | 624 | } |
627 | | | 625 | |
628 | int | | 626 | int |
629 | pcic_print(void *arg, const char *pnp) | | 627 | pcic_print(void *arg, const char *pnp) |
630 | { | | 628 | { |
631 | struct pcmciabus_attach_args *paa = arg; | | 629 | struct pcmciabus_attach_args *paa = arg; |
632 | struct pcic_handle *h = (struct pcic_handle *) paa->pch; | | 630 | struct pcic_handle *h = (struct pcic_handle *) paa->pch; |
633 | | | 631 | |
634 | /* Only "pcmcia"s can attach to "pcic"s... easy. */ | | 632 | /* Only "pcmcia"s can attach to "pcic"s... easy. */ |
635 | if (pnp) | | 633 | if (pnp) |
636 | aprint_normal("pcmcia at %s", pnp); | | 634 | aprint_normal("pcmcia at %s", pnp); |
637 | | | 635 | |
638 | aprint_normal(" controller %d socket %d", h->chip, h->socket); | | 636 | aprint_normal(" controller %d socket %d", h->chip, h->socket); |
639 | | | 637 | |
640 | return UNCONF; | | 638 | return UNCONF; |
641 | } | | 639 | } |
642 | | | 640 | |
643 | void | | 641 | void |
644 | pcic_poll_intr(void *arg) | | 642 | pcic_poll_intr(void *arg) |
645 | { | | 643 | { |
646 | struct pcic_softc *sc; | | 644 | struct pcic_softc *sc; |
647 | int i, s; | | 645 | int i, s; |
648 | | | 646 | |
649 | s = spltty(); | | 647 | s = spltty(); |
650 | sc = arg; | | 648 | sc = arg; |
651 | for (i = 0; i < __arraycount(sc->handle); i++) | | 649 | for (i = 0; i < __arraycount(sc->handle); i++) |
652 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) | | 650 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) |
653 | (void)pcic_intr_socket(&sc->handle[i]); | | 651 | (void)pcic_intr_socket(&sc->handle[i]); |
654 | callout_reset(&sc->poll_ch, hz / 2, pcic_poll_intr, sc); | | 652 | callout_reset(&sc->poll_ch, hz / 2, pcic_poll_intr, sc); |
655 | splx(s); | | 653 | splx(s); |
656 | } | | 654 | } |
657 | | | 655 | |
658 | int | | 656 | int |
659 | pcic_intr(void *arg) | | 657 | pcic_intr(void *arg) |
660 | { | | 658 | { |
661 | struct pcic_softc *sc = arg; | | 659 | struct pcic_softc *sc = arg; |
662 | int i, ret = 0; | | 660 | int i, ret = 0; |
663 | | | 661 | |
664 | DPRINTF(("%s: intr\n", device_xname(&sc->dev))); | | 662 | DPRINTF(("%s: intr\n", device_xname(&sc->dev))); |
665 | | | 663 | |
666 | for (i = 0; i < __arraycount(sc->handle); i++) | | 664 | for (i = 0; i < __arraycount(sc->handle); i++) |
667 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) | | 665 | if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) |
668 | ret += pcic_intr_socket(&sc->handle[i]); | | 666 | ret += pcic_intr_socket(&sc->handle[i]); |
669 | | | 667 | |
670 | return ret ? 1 : 0; | | 668 | return ret ? 1 : 0; |
671 | } | | 669 | } |
672 | | | 670 | |
673 | int | | 671 | int |
674 | pcic_intr_socket(struct pcic_handle *h) | | 672 | pcic_intr_socket(struct pcic_handle *h) |
675 | { | | 673 | { |
676 | int cscreg; | | 674 | int cscreg; |
677 | | | 675 | |
678 | cscreg = pcic_read(h, PCIC_CSC); | | 676 | cscreg = pcic_read(h, PCIC_CSC); |
679 | | | 677 | |
680 | cscreg &= (PCIC_CSC_GPI | | | 678 | cscreg &= (PCIC_CSC_GPI | |
681 | PCIC_CSC_CD | | | 679 | PCIC_CSC_CD | |
682 | PCIC_CSC_READY | | | 680 | PCIC_CSC_READY | |
683 | PCIC_CSC_BATTWARN | | | 681 | PCIC_CSC_BATTWARN | |
684 | PCIC_CSC_BATTDEAD); | | 682 | PCIC_CSC_BATTDEAD); |
685 | | | 683 | |
686 | if (cscreg & PCIC_CSC_GPI) { | | 684 | if (cscreg & PCIC_CSC_GPI) { |
687 | DPRINTF(("%s: %02x GPI\n", | | 685 | DPRINTF(("%s: %02x GPI\n", |
688 | device_xname(h->ph_parent), h->sock)); | | 686 | device_xname(h->ph_parent), h->sock)); |
689 | } | | 687 | } |
690 | if (cscreg & PCIC_CSC_CD) { | | 688 | if (cscreg & PCIC_CSC_CD) { |
691 | int statreg; | | 689 | int statreg; |
692 | | | 690 | |
693 | statreg = pcic_read(h, PCIC_IF_STATUS); | | 691 | statreg = pcic_read(h, PCIC_IF_STATUS); |
694 | | | 692 | |
695 | DPRINTF(("%s: %02x CD %x\n", device_xname(h->ph_parent), | | 693 | DPRINTF(("%s: %02x CD %x\n", device_xname(h->ph_parent), |
696 | h->sock, statreg)); | | 694 | h->sock, statreg)); |
697 | | | 695 | |
698 | if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == | | 696 | if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == |
699 | PCIC_IF_STATUS_CARDDETECT_PRESENT) { | | 697 | PCIC_IF_STATUS_CARDDETECT_PRESENT) { |
700 | if (h->laststate != PCIC_LASTSTATE_PRESENT) { | | 698 | if (h->laststate != PCIC_LASTSTATE_PRESENT) { |
701 | DPRINTF(("%s: enqueing INSERTION event\n", | | 699 | DPRINTF(("%s: enqueing INSERTION event\n", |
702 | device_xname(h->ph_parent))); | | 700 | device_xname(h->ph_parent))); |
703 | pcic_queue_event(h, PCIC_EVENT_INSERTION); | | 701 | pcic_queue_event(h, PCIC_EVENT_INSERTION); |
704 | } | | 702 | } |
705 | h->laststate = PCIC_LASTSTATE_PRESENT; | | 703 | h->laststate = PCIC_LASTSTATE_PRESENT; |
706 | } else { | | 704 | } else { |
707 | if (h->laststate == PCIC_LASTSTATE_PRESENT) { | | 705 | if (h->laststate == PCIC_LASTSTATE_PRESENT) { |
708 | /* Deactivate the card now. */ | | 706 | /* Deactivate the card now. */ |
709 | DPRINTF(("%s: deactivating card\n", | | 707 | DPRINTF(("%s: deactivating card\n", |
710 | device_xname(h->ph_parent))); | | 708 | device_xname(h->ph_parent))); |
711 | pcic_deactivate_card(h); | | 709 | pcic_deactivate_card(h); |
712 | | | 710 | |
713 | DPRINTF(("%s: enqueing REMOVAL event\n", | | 711 | DPRINTF(("%s: enqueing REMOVAL event\n", |
714 | device_xname(h->ph_parent))); | | 712 | device_xname(h->ph_parent))); |
715 | pcic_queue_event(h, PCIC_EVENT_REMOVAL); | | 713 | pcic_queue_event(h, PCIC_EVENT_REMOVAL); |
716 | } | | 714 | } |
717 | h->laststate = PCIC_LASTSTATE_EMPTY; | | 715 | h->laststate = PCIC_LASTSTATE_EMPTY; |
718 | } | | 716 | } |
719 | } | | 717 | } |
720 | if (cscreg & PCIC_CSC_READY) { | | 718 | if (cscreg & PCIC_CSC_READY) { |
721 | DPRINTF(("%s: %02x READY\n", device_xname(h->ph_parent), | | 719 | DPRINTF(("%s: %02x READY\n", device_xname(h->ph_parent), |
722 | h->sock)); | | 720 | h->sock)); |
723 | /* shouldn't happen */ | | 721 | /* shouldn't happen */ |
724 | } | | 722 | } |
725 | if (cscreg & PCIC_CSC_BATTWARN) { | | 723 | if (cscreg & PCIC_CSC_BATTWARN) { |
726 | DPRINTF(("%s: %02x BATTWARN\n", device_xname(h->ph_parent), | | 724 | DPRINTF(("%s: %02x BATTWARN\n", device_xname(h->ph_parent), |
727 | h->sock)); | | 725 | h->sock)); |
728 | } | | 726 | } |
729 | if (cscreg & PCIC_CSC_BATTDEAD) { | | 727 | if (cscreg & PCIC_CSC_BATTDEAD) { |
730 | DPRINTF(("%s: %02x BATTDEAD\n", device_xname(h->ph_parent), | | 728 | DPRINTF(("%s: %02x BATTDEAD\n", device_xname(h->ph_parent), |
731 | h->sock)); | | 729 | h->sock)); |
732 | } | | 730 | } |
733 | return cscreg ? 1 : 0; | | 731 | return cscreg ? 1 : 0; |
734 | } | | 732 | } |
735 | | | 733 | |
736 | void | | 734 | void |
737 | pcic_queue_event(struct pcic_handle *h, int event) | | 735 | pcic_queue_event(struct pcic_handle *h, int event) |
738 | { | | 736 | { |
739 | struct pcic_event *pe; | | 737 | struct pcic_event *pe; |
740 | int s; | | 738 | int s; |
741 | | | 739 | |
742 | pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT); | | 740 | pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT); |
743 | if (pe == NULL) | | 741 | if (pe == NULL) |
744 | panic("pcic_queue_event: can't allocate event"); | | 742 | panic("pcic_queue_event: can't allocate event"); |
745 | | | 743 | |
746 | pe->pe_type = event; | | 744 | pe->pe_type = event; |
747 | s = splhigh(); | | 745 | s = splhigh(); |
748 | SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q); | | 746 | SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q); |
749 | splx(s); | | 747 | splx(s); |
750 | wakeup(&h->events); | | 748 | wakeup(&h->events); |
751 | } | | 749 | } |
752 | | | 750 | |
753 | void | | 751 | void |
754 | pcic_attach_card(struct pcic_handle *h) | | 752 | pcic_attach_card(struct pcic_handle *h) |
755 | { | | 753 | { |
756 | | | 754 | |
757 | if ((h->flags & PCIC_FLAG_CARDP) == 0) { | | 755 | if ((h->flags & PCIC_FLAG_CARDP) == 0) { |
758 | /* call the MI attach function */ | | 756 | /* call the MI attach function */ |
759 | pcmcia_card_attach(h->pcmcia); | | 757 | pcmcia_card_attach(h->pcmcia); |
760 | | | 758 | |
761 | h->flags |= PCIC_FLAG_CARDP; | | 759 | h->flags |= PCIC_FLAG_CARDP; |
762 | } else { | | 760 | } else { |
763 | DPRINTF(("pcic_attach_card: already attached")); | | 761 | DPRINTF(("pcic_attach_card: already attached")); |
764 | } | | 762 | } |
765 | } | | 763 | } |
766 | | | 764 | |
767 | void | | 765 | void |
768 | pcic_detach_card(struct pcic_handle *h, int flags) | | 766 | pcic_detach_card(struct pcic_handle *h, int flags) |
769 | /* flags: DETACH_* */ | | 767 | /* flags: DETACH_* */ |
770 | { | | 768 | { |
771 | | | 769 | |
772 | if (h->flags & PCIC_FLAG_CARDP) { | | 770 | if (h->flags & PCIC_FLAG_CARDP) { |
773 | h->flags &= ~PCIC_FLAG_CARDP; | | 771 | h->flags &= ~PCIC_FLAG_CARDP; |
774 | | | 772 | |
775 | /* call the MI detach function */ | | 773 | /* call the MI detach function */ |
776 | pcmcia_card_detach(h->pcmcia, flags); | | 774 | pcmcia_card_detach(h->pcmcia, flags); |
777 | } else { | | 775 | } else { |
778 | DPRINTF(("pcic_detach_card: already detached")); | | 776 | DPRINTF(("pcic_detach_card: already detached")); |
779 | } | | 777 | } |
780 | } | | 778 | } |
781 | | | 779 | |
782 | void | | 780 | void |
783 | pcic_deactivate_card(struct pcic_handle *h) | | 781 | pcic_deactivate_card(struct pcic_handle *h) |
784 | { | | 782 | { |
785 | int intr; | | 783 | int intr; |
786 | | | 784 | |
787 | /* call the MI deactivate function */ | | 785 | /* call the MI deactivate function */ |
788 | pcmcia_card_deactivate(h->pcmcia); | | 786 | pcmcia_card_deactivate(h->pcmcia); |
789 | | | 787 | |
790 | /* reset the socket */ | | 788 | /* reset the socket */ |
791 | intr = pcic_read(h, PCIC_INTR); | | 789 | intr = pcic_read(h, PCIC_INTR); |
792 | intr &= PCIC_INTR_ENABLE; | | 790 | intr &= PCIC_INTR_ENABLE; |
793 | pcic_write(h, PCIC_INTR, intr); | | 791 | pcic_write(h, PCIC_INTR, intr); |
794 | | | 792 | |
795 | /* power down the socket */ | | 793 | /* power down the socket */ |
796 | pcic_write(h, PCIC_PWRCTL, 0); | | 794 | pcic_write(h, PCIC_PWRCTL, 0); |
797 | } | | 795 | } |
798 | | | 796 | |
799 | int | | 797 | int |
800 | pcic_chip_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, | | 798 | pcic_chip_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, |
801 | struct pcmcia_mem_handle *pcmhp) | | 799 | struct pcmcia_mem_handle *pcmhp) |
802 | { | | 800 | { |
803 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 801 | struct pcic_handle *h = (struct pcic_handle *) pch; |
804 | bus_space_handle_t memh; | | 802 | bus_space_handle_t memh; |
805 | bus_addr_t addr; | | 803 | bus_addr_t addr; |
806 | bus_size_t sizepg; | | 804 | bus_size_t sizepg; |
807 | int i, mask, mhandle; | | 805 | int i, mask, mhandle; |
808 | struct pcic_softc *sc = device_private(h->ph_parent); | | 806 | struct pcic_softc *sc = device_private(h->ph_parent); |
809 | | | 807 | |
810 | /* out of sc->memh, allocate as many pages as necessary */ | | 808 | /* out of sc->memh, allocate as many pages as necessary */ |
811 | | | 809 | |
812 | /* convert size to PCIC pages */ | | 810 | /* convert size to PCIC pages */ |
813 | sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN; | | 811 | sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN; |
814 | if (sizepg > PCIC_MAX_MEM_PAGES) | | 812 | if (sizepg > PCIC_MAX_MEM_PAGES) |
815 | return 1; | | 813 | return 1; |
816 | | | 814 | |
817 | mask = (1 << sizepg) - 1; | | 815 | mask = (1 << sizepg) - 1; |
818 | | | 816 | |
819 | addr = 0; /* XXX gcc -Wuninitialized */ | | 817 | addr = 0; /* XXX gcc -Wuninitialized */ |
820 | mhandle = 0; /* XXX gcc -Wuninitialized */ | | 818 | mhandle = 0; /* XXX gcc -Wuninitialized */ |
821 | | | 819 | |
822 | for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) { | | 820 | for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) { |
823 | if ((sc->subregionmask & (mask << i)) == (mask << i)) { | | 821 | if ((sc->subregionmask & (mask << i)) == (mask << i)) { |
824 | if (bus_space_subregion(sc->memt, sc->memh, | | 822 | if (bus_space_subregion(sc->memt, sc->memh, |
825 | i * PCIC_MEM_PAGESIZE, | | 823 | i * PCIC_MEM_PAGESIZE, |
826 | sizepg * PCIC_MEM_PAGESIZE, &memh)) | | 824 | sizepg * PCIC_MEM_PAGESIZE, &memh)) |
827 | return 1; | | 825 | return 1; |
828 | mhandle = mask << i; | | 826 | mhandle = mask << i; |
829 | addr = sc->membase + (i * PCIC_MEM_PAGESIZE); | | 827 | addr = sc->membase + (i * PCIC_MEM_PAGESIZE); |
830 | sc->subregionmask &= ~(mhandle); | | 828 | sc->subregionmask &= ~(mhandle); |
831 | pcmhp->memt = sc->memt; | | 829 | pcmhp->memt = sc->memt; |
832 | pcmhp->memh = memh; | | 830 | pcmhp->memh = memh; |
833 | pcmhp->addr = addr; | | 831 | pcmhp->addr = addr; |
834 | pcmhp->size = size; | | 832 | pcmhp->size = size; |
835 | pcmhp->mhandle = mhandle; | | 833 | pcmhp->mhandle = mhandle; |
836 | pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE; | | 834 | pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE; |
837 | return 0; | | 835 | return 0; |
838 | } | | 836 | } |
839 | } | | 837 | } |
840 | | | 838 | |
841 | return 1; | | 839 | return 1; |
842 | } | | 840 | } |
843 | | | 841 | |
844 | void | | 842 | void |
845 | pcic_chip_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pcmhp) | | 843 | pcic_chip_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pcmhp) |
846 | { | | 844 | { |
847 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 845 | struct pcic_handle *h = (struct pcic_handle *) pch; |
848 | struct pcic_softc *sc = device_private(h->ph_parent); | | 846 | struct pcic_softc *sc = device_private(h->ph_parent); |
849 | | | 847 | |
850 | sc->subregionmask |= pcmhp->mhandle; | | 848 | sc->subregionmask |= pcmhp->mhandle; |
851 | } | | 849 | } |
852 | | | 850 | |
853 | static const struct mem_map_index_st { | | 851 | static const struct mem_map_index_st { |
854 | int sysmem_start_lsb; | | 852 | int sysmem_start_lsb; |
855 | int sysmem_start_msb; | | 853 | int sysmem_start_msb; |
856 | int sysmem_stop_lsb; | | 854 | int sysmem_stop_lsb; |
857 | int sysmem_stop_msb; | | 855 | int sysmem_stop_msb; |
858 | int cardmem_lsb; | | 856 | int cardmem_lsb; |
859 | int cardmem_msb; | | 857 | int cardmem_msb; |
860 | int memenable; | | 858 | int memenable; |
861 | } mem_map_index[] = { | | 859 | } mem_map_index[] = { |
862 | { | | 860 | { |
863 | PCIC_SYSMEM_ADDR0_START_LSB, | | 861 | PCIC_SYSMEM_ADDR0_START_LSB, |
864 | PCIC_SYSMEM_ADDR0_START_MSB, | | 862 | PCIC_SYSMEM_ADDR0_START_MSB, |
865 | PCIC_SYSMEM_ADDR0_STOP_LSB, | | 863 | PCIC_SYSMEM_ADDR0_STOP_LSB, |
866 | PCIC_SYSMEM_ADDR0_STOP_MSB, | | 864 | PCIC_SYSMEM_ADDR0_STOP_MSB, |
867 | PCIC_CARDMEM_ADDR0_LSB, | | 865 | PCIC_CARDMEM_ADDR0_LSB, |
868 | PCIC_CARDMEM_ADDR0_MSB, | | 866 | PCIC_CARDMEM_ADDR0_MSB, |
869 | PCIC_ADDRWIN_ENABLE_MEM0, | | 867 | PCIC_ADDRWIN_ENABLE_MEM0, |
870 | }, | | 868 | }, |
871 | { | | 869 | { |
872 | PCIC_SYSMEM_ADDR1_START_LSB, | | 870 | PCIC_SYSMEM_ADDR1_START_LSB, |
873 | PCIC_SYSMEM_ADDR1_START_MSB, | | 871 | PCIC_SYSMEM_ADDR1_START_MSB, |
874 | PCIC_SYSMEM_ADDR1_STOP_LSB, | | 872 | PCIC_SYSMEM_ADDR1_STOP_LSB, |
875 | PCIC_SYSMEM_ADDR1_STOP_MSB, | | 873 | PCIC_SYSMEM_ADDR1_STOP_MSB, |
876 | PCIC_CARDMEM_ADDR1_LSB, | | 874 | PCIC_CARDMEM_ADDR1_LSB, |
877 | PCIC_CARDMEM_ADDR1_MSB, | | 875 | PCIC_CARDMEM_ADDR1_MSB, |
878 | PCIC_ADDRWIN_ENABLE_MEM1, | | 876 | PCIC_ADDRWIN_ENABLE_MEM1, |
879 | }, | | 877 | }, |
880 | { | | 878 | { |
881 | PCIC_SYSMEM_ADDR2_START_LSB, | | 879 | PCIC_SYSMEM_ADDR2_START_LSB, |
882 | PCIC_SYSMEM_ADDR2_START_MSB, | | 880 | PCIC_SYSMEM_ADDR2_START_MSB, |
883 | PCIC_SYSMEM_ADDR2_STOP_LSB, | | 881 | PCIC_SYSMEM_ADDR2_STOP_LSB, |
884 | PCIC_SYSMEM_ADDR2_STOP_MSB, | | 882 | PCIC_SYSMEM_ADDR2_STOP_MSB, |
885 | PCIC_CARDMEM_ADDR2_LSB, | | 883 | PCIC_CARDMEM_ADDR2_LSB, |
886 | PCIC_CARDMEM_ADDR2_MSB, | | 884 | PCIC_CARDMEM_ADDR2_MSB, |
887 | PCIC_ADDRWIN_ENABLE_MEM2, | | 885 | PCIC_ADDRWIN_ENABLE_MEM2, |
888 | }, | | 886 | }, |
889 | { | | 887 | { |
890 | PCIC_SYSMEM_ADDR3_START_LSB, | | 888 | PCIC_SYSMEM_ADDR3_START_LSB, |
891 | PCIC_SYSMEM_ADDR3_START_MSB, | | 889 | PCIC_SYSMEM_ADDR3_START_MSB, |
892 | PCIC_SYSMEM_ADDR3_STOP_LSB, | | 890 | PCIC_SYSMEM_ADDR3_STOP_LSB, |
893 | PCIC_SYSMEM_ADDR3_STOP_MSB, | | 891 | PCIC_SYSMEM_ADDR3_STOP_MSB, |
894 | PCIC_CARDMEM_ADDR3_LSB, | | 892 | PCIC_CARDMEM_ADDR3_LSB, |
895 | PCIC_CARDMEM_ADDR3_MSB, | | 893 | PCIC_CARDMEM_ADDR3_MSB, |
896 | PCIC_ADDRWIN_ENABLE_MEM3, | | 894 | PCIC_ADDRWIN_ENABLE_MEM3, |
897 | }, | | 895 | }, |
898 | { | | 896 | { |
899 | PCIC_SYSMEM_ADDR4_START_LSB, | | 897 | PCIC_SYSMEM_ADDR4_START_LSB, |
900 | PCIC_SYSMEM_ADDR4_START_MSB, | | 898 | PCIC_SYSMEM_ADDR4_START_MSB, |
901 | PCIC_SYSMEM_ADDR4_STOP_LSB, | | 899 | PCIC_SYSMEM_ADDR4_STOP_LSB, |
902 | PCIC_SYSMEM_ADDR4_STOP_MSB, | | 900 | PCIC_SYSMEM_ADDR4_STOP_MSB, |
903 | PCIC_CARDMEM_ADDR4_LSB, | | 901 | PCIC_CARDMEM_ADDR4_LSB, |
904 | PCIC_CARDMEM_ADDR4_MSB, | | 902 | PCIC_CARDMEM_ADDR4_MSB, |
905 | PCIC_ADDRWIN_ENABLE_MEM4, | | 903 | PCIC_ADDRWIN_ENABLE_MEM4, |
906 | }, | | 904 | }, |
907 | }; | | 905 | }; |
908 | | | 906 | |
909 | void | | 907 | void |
910 | pcic_chip_do_mem_map(struct pcic_handle *h, int win) | | 908 | pcic_chip_do_mem_map(struct pcic_handle *h, int win) |
911 | { | | 909 | { |
912 | int reg; | | 910 | int reg; |
913 | int kind = h->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK; | | 911 | int kind = h->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK; |
914 | int mem8 = | | 912 | int mem8 = |
915 | (h->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8 | | 913 | (h->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8 |
916 | || (kind == PCMCIA_MEM_ATTR); | | 914 | || (kind == PCMCIA_MEM_ATTR); |
917 | | | 915 | |
918 | DPRINTF(("mem8 %d\n", mem8)); | | 916 | DPRINTF(("mem8 %d\n", mem8)); |
919 | /* mem8 = 1; */ | | 917 | /* mem8 = 1; */ |
920 | | | 918 | |
921 | pcic_write(h, mem_map_index[win].sysmem_start_lsb, | | 919 | pcic_write(h, mem_map_index[win].sysmem_start_lsb, |
922 | (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); | | 920 | (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); |
923 | pcic_write(h, mem_map_index[win].sysmem_start_msb, | | 921 | pcic_write(h, mem_map_index[win].sysmem_start_msb, |
924 | ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & | | 922 | ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & |
925 | PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | | | 923 | PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | |
926 | (mem8 ? 0 : PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT)); | | 924 | (mem8 ? 0 : PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT)); |
927 | | | 925 | |
928 | pcic_write(h, mem_map_index[win].sysmem_stop_lsb, | | 926 | pcic_write(h, mem_map_index[win].sysmem_stop_lsb, |
929 | ((h->mem[win].addr + h->mem[win].size) >> | | 927 | ((h->mem[win].addr + h->mem[win].size) >> |
930 | PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); | | 928 | PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); |
931 | pcic_write(h, mem_map_index[win].sysmem_stop_msb, | | 929 | pcic_write(h, mem_map_index[win].sysmem_stop_msb, |
932 | (((h->mem[win].addr + h->mem[win].size) >> | | 930 | (((h->mem[win].addr + h->mem[win].size) >> |
933 | (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & | | 931 | (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & |
934 | PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | | | 932 | PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | |
935 | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2); | | 933 | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2); |
936 | | | 934 | |
937 | pcic_write(h, mem_map_index[win].cardmem_lsb, | | 935 | pcic_write(h, mem_map_index[win].cardmem_lsb, |
938 | (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff); | | 936 | (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff); |
939 | pcic_write(h, mem_map_index[win].cardmem_msb, | | 937 | pcic_write(h, mem_map_index[win].cardmem_msb, |
940 | ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) & | | 938 | ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) & |
941 | PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) | | | 939 | PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) | |
942 | ((kind == PCMCIA_MEM_ATTR) ? | | 940 | ((kind == PCMCIA_MEM_ATTR) ? |
943 | PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0)); | | 941 | PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0)); |
944 | | | 942 | |
945 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); | | 943 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); |
946 | reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16); | | 944 | reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16); |
947 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); | | 945 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); |
948 | | | 946 | |
949 | delay(100); | | 947 | delay(100); |
950 | | | 948 | |
951 | #ifdef PCICDEBUG | | 949 | #ifdef PCICDEBUG |
952 | { | | 950 | { |
953 | int r1, r2, r3, r4, r5, r6; | | 951 | int r1, r2, r3, r4, r5, r6; |
954 | | | 952 | |
955 | r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb); | | 953 | r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb); |
956 | r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb); | | 954 | r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb); |
957 | r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb); | | 955 | r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb); |
958 | r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb); | | 956 | r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb); |
959 | r5 = pcic_read(h, mem_map_index[win].cardmem_msb); | | 957 | r5 = pcic_read(h, mem_map_index[win].cardmem_msb); |
960 | r6 = pcic_read(h, mem_map_index[win].cardmem_lsb); | | 958 | r6 = pcic_read(h, mem_map_index[win].cardmem_lsb); |
961 | | | 959 | |
962 | DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x " | | 960 | DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x " |
963 | "%02x%02x\n", win, r1, r2, r3, r4, r5, r6)); | | 961 | "%02x%02x\n", win, r1, r2, r3, r4, r5, r6)); |
964 | } | | 962 | } |
965 | #endif | | 963 | #endif |
966 | } | | 964 | } |
967 | | | 965 | |
968 | int | | 966 | int |
969 | pcic_chip_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr, | | 967 | pcic_chip_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr, |
970 | bus_size_t size, struct pcmcia_mem_handle *pcmhp, bus_size_t *offsetp, | | 968 | bus_size_t size, struct pcmcia_mem_handle *pcmhp, bus_size_t *offsetp, |
971 | int *windowp) | | 969 | int *windowp) |
972 | { | | 970 | { |
973 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 971 | struct pcic_handle *h = (struct pcic_handle *) pch; |
974 | bus_addr_t busaddr; | | 972 | bus_addr_t busaddr; |
975 | long card_offset; | | 973 | long card_offset; |
976 | int i, win; | | 974 | int i, win; |
977 | | | 975 | |
978 | win = -1; | | 976 | win = -1; |
979 | for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0])); | | 977 | for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0])); |
980 | i++) { | | 978 | i++) { |
981 | if ((h->memalloc & (1 << i)) == 0) { | | 979 | if ((h->memalloc & (1 << i)) == 0) { |
982 | win = i; | | 980 | win = i; |
983 | h->memalloc |= (1 << i); | | 981 | h->memalloc |= (1 << i); |
984 | break; | | 982 | break; |
985 | } | | 983 | } |
986 | } | | 984 | } |
987 | | | 985 | |
988 | if (win == -1) | | 986 | if (win == -1) |
989 | return 1; | | 987 | return 1; |
990 | | | 988 | |
991 | *windowp = win; | | 989 | *windowp = win; |
992 | | | 990 | |
993 | /* XXX this is pretty gross */ | | 991 | /* XXX this is pretty gross */ |
994 | | | 992 | |
995 | { | | 993 | { |
996 | struct pcic_softc *sc = device_private(h->ph_parent); | | 994 | struct pcic_softc *sc = device_private(h->ph_parent); |
997 | if (!bus_space_is_equal(sc->memt, pcmhp->memt)) | | 995 | if (!bus_space_is_equal(sc->memt, pcmhp->memt)) |
998 | panic("pcic_chip_mem_map memt is bogus"); | | 996 | panic("pcic_chip_mem_map memt is bogus"); |
999 | } | | 997 | } |
1000 | | | 998 | |
1001 | busaddr = pcmhp->addr; | | 999 | busaddr = pcmhp->addr; |
1002 | | | 1000 | |
1003 | /* | | 1001 | /* |
1004 | * compute the address offset to the pcmcia address space for the | | 1002 | * compute the address offset to the pcmcia address space for the |
1005 | * pcic. this is intentionally signed. The masks and shifts below | | 1003 | * pcic. this is intentionally signed. The masks and shifts below |
1006 | * will cause TRT to happen in the pcic registers. Deal with making | | 1004 | * will cause TRT to happen in the pcic registers. Deal with making |
1007 | * sure the address is aligned, and return the alignment offset. | | 1005 | * sure the address is aligned, and return the alignment offset. |
1008 | */ | | 1006 | */ |
1009 | | | 1007 | |
1010 | *offsetp = card_addr % PCIC_MEM_ALIGN; | | 1008 | *offsetp = card_addr % PCIC_MEM_ALIGN; |
1011 | card_addr -= *offsetp; | | 1009 | card_addr -= *offsetp; |
1012 | | | 1010 | |
1013 | DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr " | | 1011 | DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr " |
1014 | "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size, | | 1012 | "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size, |
1015 | (u_long) card_addr)); | | 1013 | (u_long) card_addr)); |
1016 | | | 1014 | |
1017 | /* | | 1015 | /* |
1018 | * include the offset in the size, and decrement size by one, since | | 1016 | * include the offset in the size, and decrement size by one, since |
1019 | * the hw wants start/stop | | 1017 | * the hw wants start/stop |
1020 | */ | | 1018 | */ |
1021 | size += *offsetp - 1; | | 1019 | size += *offsetp - 1; |
1022 | | | 1020 | |
1023 | card_offset = (((long) card_addr) - ((long) busaddr)); | | 1021 | card_offset = (((long) card_addr) - ((long) busaddr)); |
1024 | | | 1022 | |
1025 | h->mem[win].addr = busaddr; | | 1023 | h->mem[win].addr = busaddr; |
1026 | h->mem[win].size = size; | | 1024 | h->mem[win].size = size; |
1027 | h->mem[win].offset = card_offset; | | 1025 | h->mem[win].offset = card_offset; |
1028 | h->mem[win].kind = kind; | | 1026 | h->mem[win].kind = kind; |
1029 | | | 1027 | |
1030 | pcic_chip_do_mem_map(h, win); | | 1028 | pcic_chip_do_mem_map(h, win); |
1031 | | | 1029 | |
1032 | return 0; | | 1030 | return 0; |
1033 | } | | 1031 | } |
1034 | | | 1032 | |
1035 | void | | 1033 | void |
1036 | pcic_chip_mem_unmap(pcmcia_chipset_handle_t pch, int window) | | 1034 | pcic_chip_mem_unmap(pcmcia_chipset_handle_t pch, int window) |
1037 | { | | 1035 | { |
1038 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 1036 | struct pcic_handle *h = (struct pcic_handle *) pch; |
1039 | int reg; | | 1037 | int reg; |
1040 | | | 1038 | |
1041 | if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0]))) | | 1039 | if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0]))) |
1042 | panic("pcic_chip_mem_unmap: window out of range"); | | 1040 | panic("pcic_chip_mem_unmap: window out of range"); |
1043 | | | 1041 | |
1044 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); | | 1042 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); |
1045 | reg &= ~mem_map_index[window].memenable; | | 1043 | reg &= ~mem_map_index[window].memenable; |
1046 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); | | 1044 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); |
1047 | | | 1045 | |
1048 | h->memalloc &= ~(1 << window); | | 1046 | h->memalloc &= ~(1 << window); |
1049 | } | | 1047 | } |
1050 | | | 1048 | |
1051 | int | | 1049 | int |
1052 | pcic_chip_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, | | 1050 | pcic_chip_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, |
1053 | bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pcihp) | | 1051 | bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pcihp) |
1054 | { | | 1052 | { |
1055 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 1053 | struct pcic_handle *h = (struct pcic_handle *) pch; |
1056 | bus_space_tag_t iot; | | 1054 | bus_space_tag_t iot; |
1057 | bus_space_handle_t ioh; | | 1055 | bus_space_handle_t ioh; |
1058 | bus_addr_t ioaddr; | | 1056 | bus_addr_t ioaddr; |
1059 | int flags = 0; | | 1057 | int flags = 0; |
1060 | struct pcic_softc *sc = device_private(h->ph_parent); | | 1058 | struct pcic_softc *sc = device_private(h->ph_parent); |
1061 | | | 1059 | |
1062 | /* | | 1060 | /* |
1063 | * Allocate some arbitrary I/O space. | | 1061 | * Allocate some arbitrary I/O space. |
1064 | */ | | 1062 | */ |
1065 | | | 1063 | |
1066 | iot = sc->iot; | | 1064 | iot = sc->iot; |
1067 | | | 1065 | |
1068 | if (start) { | | 1066 | if (start) { |
1069 | ioaddr = start; | | 1067 | ioaddr = start; |
1070 | if (bus_space_map(iot, start, size, 0, &ioh)) | | 1068 | if (bus_space_map(iot, start, size, 0, &ioh)) |
1071 | return 1; | | 1069 | return 1; |
1072 | DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n", | | 1070 | DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n", |
1073 | (u_long) ioaddr, (u_long) size)); | | 1071 | (u_long) ioaddr, (u_long) size)); |
1074 | } else { | | 1072 | } else { |
1075 | flags |= PCMCIA_IO_ALLOCATED; | | 1073 | flags |= PCMCIA_IO_ALLOCATED; |
1076 | if (bus_space_alloc(iot, sc->iobase, | | 1074 | if (bus_space_alloc(iot, sc->iobase, |
1077 | sc->iobase + sc->iosize, size, align, 0, 0, | | 1075 | sc->iobase + sc->iosize, size, align, 0, 0, |
1078 | &ioaddr, &ioh)) | | 1076 | &ioaddr, &ioh)) |
1079 | return 1; | | 1077 | return 1; |
1080 | DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n", | | 1078 | DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n", |
1081 | (u_long) ioaddr, (u_long) size)); | | 1079 | (u_long) ioaddr, (u_long) size)); |
1082 | } | | 1080 | } |
1083 | | | 1081 | |
1084 | pcihp->iot = iot; | | 1082 | pcihp->iot = iot; |
1085 | pcihp->ioh = ioh; | | 1083 | pcihp->ioh = ioh; |
1086 | pcihp->addr = ioaddr; | | 1084 | pcihp->addr = ioaddr; |
1087 | pcihp->size = size; | | 1085 | pcihp->size = size; |
1088 | pcihp->flags = flags; | | 1086 | pcihp->flags = flags; |
1089 | | | 1087 | |
1090 | return 0; | | 1088 | return 0; |
1091 | } | | 1089 | } |
1092 | | | 1090 | |
1093 | void | | 1091 | void |
1094 | pcic_chip_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pcihp) | | 1092 | pcic_chip_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pcihp) |
1095 | { | | 1093 | { |
1096 | bus_space_tag_t iot = pcihp->iot; | | 1094 | bus_space_tag_t iot = pcihp->iot; |
1097 | bus_space_handle_t ioh = pcihp->ioh; | | 1095 | bus_space_handle_t ioh = pcihp->ioh; |
1098 | bus_size_t size = pcihp->size; | | 1096 | bus_size_t size = pcihp->size; |
1099 | | | 1097 | |
1100 | if (pcihp->flags & PCMCIA_IO_ALLOCATED) | | 1098 | if (pcihp->flags & PCMCIA_IO_ALLOCATED) |
1101 | bus_space_free(iot, ioh, size); | | 1099 | bus_space_free(iot, ioh, size); |
1102 | else | | 1100 | else |
1103 | bus_space_unmap(iot, ioh, size); | | 1101 | bus_space_unmap(iot, ioh, size); |
1104 | } | | 1102 | } |
1105 | | | 1103 | |
1106 | | | 1104 | |
1107 | static const struct io_map_index_st { | | 1105 | static const struct io_map_index_st { |
1108 | int start_lsb; | | 1106 | int start_lsb; |
1109 | int start_msb; | | 1107 | int start_msb; |
1110 | int stop_lsb; | | 1108 | int stop_lsb; |
1111 | int stop_msb; | | 1109 | int stop_msb; |
1112 | int ioenable; | | 1110 | int ioenable; |
1113 | int ioctlmask; | | 1111 | int ioctlmask; |
1114 | int ioctlbits[3]; /* indexed by PCMCIA_WIDTH_* */ | | 1112 | int ioctlbits[3]; /* indexed by PCMCIA_WIDTH_* */ |
1115 | } io_map_index[] = { | | 1113 | } io_map_index[] = { |
1116 | { | | 1114 | { |
1117 | PCIC_IOADDR0_START_LSB, | | 1115 | PCIC_IOADDR0_START_LSB, |
1118 | PCIC_IOADDR0_START_MSB, | | 1116 | PCIC_IOADDR0_START_MSB, |
1119 | PCIC_IOADDR0_STOP_LSB, | | 1117 | PCIC_IOADDR0_STOP_LSB, |
1120 | PCIC_IOADDR0_STOP_MSB, | | 1118 | PCIC_IOADDR0_STOP_MSB, |
1121 | PCIC_ADDRWIN_ENABLE_IO0, | | 1119 | PCIC_ADDRWIN_ENABLE_IO0, |
1122 | PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT | | | 1120 | PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT | |
1123 | PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK, | | 1121 | PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK, |
1124 | { | | 1122 | { |
1125 | PCIC_IOCTL_IO0_IOCS16SRC_CARD, | | 1123 | PCIC_IOCTL_IO0_IOCS16SRC_CARD, |
1126 | PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | | | 1124 | PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | |
1127 | PCIC_IOCTL_IO0_DATASIZE_8BIT, | | 1125 | PCIC_IOCTL_IO0_DATASIZE_8BIT, |
1128 | PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | | | 1126 | PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | |
1129 | PCIC_IOCTL_IO0_DATASIZE_16BIT, | | 1127 | PCIC_IOCTL_IO0_DATASIZE_16BIT, |
1130 | }, | | 1128 | }, |
1131 | }, | | 1129 | }, |
1132 | { | | 1130 | { |
1133 | PCIC_IOADDR1_START_LSB, | | 1131 | PCIC_IOADDR1_START_LSB, |
1134 | PCIC_IOADDR1_START_MSB, | | 1132 | PCIC_IOADDR1_START_MSB, |
1135 | PCIC_IOADDR1_STOP_LSB, | | 1133 | PCIC_IOADDR1_STOP_LSB, |
1136 | PCIC_IOADDR1_STOP_MSB, | | 1134 | PCIC_IOADDR1_STOP_MSB, |
1137 | PCIC_ADDRWIN_ENABLE_IO1, | | 1135 | PCIC_ADDRWIN_ENABLE_IO1, |
1138 | PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT | | | 1136 | PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT | |
1139 | PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK, | | 1137 | PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK, |
1140 | { | | 1138 | { |
1141 | PCIC_IOCTL_IO1_IOCS16SRC_CARD, | | 1139 | PCIC_IOCTL_IO1_IOCS16SRC_CARD, |
1142 | PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | | | 1140 | PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | |
1143 | PCIC_IOCTL_IO1_DATASIZE_8BIT, | | 1141 | PCIC_IOCTL_IO1_DATASIZE_8BIT, |
1144 | PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | | | 1142 | PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | |
1145 | PCIC_IOCTL_IO1_DATASIZE_16BIT, | | 1143 | PCIC_IOCTL_IO1_DATASIZE_16BIT, |
1146 | }, | | 1144 | }, |
1147 | }, | | 1145 | }, |
1148 | }; | | 1146 | }; |
1149 | | | 1147 | |
1150 | void | | 1148 | void |
1151 | pcic_chip_do_io_map(struct pcic_handle *h, int win) | | 1149 | pcic_chip_do_io_map(struct pcic_handle *h, int win) |
1152 | { | | 1150 | { |
1153 | int reg; | | 1151 | int reg; |
1154 | | | 1152 | |
1155 | DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n", | | 1153 | DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n", |
1156 | win, (long) h->io[win].addr, (long) h->io[win].size, | | 1154 | win, (long) h->io[win].addr, (long) h->io[win].size, |
1157 | h->io[win].width * 8)); | | 1155 | h->io[win].width * 8)); |
1158 | | | 1156 | |
1159 | pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff); | | 1157 | pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff); |
1160 | pcic_write(h, io_map_index[win].start_msb, | | 1158 | pcic_write(h, io_map_index[win].start_msb, |
1161 | (h->io[win].addr >> 8) & 0xff); | | 1159 | (h->io[win].addr >> 8) & 0xff); |
1162 | | | 1160 | |
1163 | pcic_write(h, io_map_index[win].stop_lsb, | | 1161 | pcic_write(h, io_map_index[win].stop_lsb, |
1164 | (h->io[win].addr + h->io[win].size - 1) & 0xff); | | 1162 | (h->io[win].addr + h->io[win].size - 1) & 0xff); |
1165 | pcic_write(h, io_map_index[win].stop_msb, | | 1163 | pcic_write(h, io_map_index[win].stop_msb, |
1166 | ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff); | | 1164 | ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff); |
1167 | | | 1165 | |
1168 | reg = pcic_read(h, PCIC_IOCTL); | | 1166 | reg = pcic_read(h, PCIC_IOCTL); |
1169 | reg &= ~io_map_index[win].ioctlmask; | | 1167 | reg &= ~io_map_index[win].ioctlmask; |
1170 | reg |= io_map_index[win].ioctlbits[h->io[win].width]; | | 1168 | reg |= io_map_index[win].ioctlbits[h->io[win].width]; |
1171 | pcic_write(h, PCIC_IOCTL, reg); | | 1169 | pcic_write(h, PCIC_IOCTL, reg); |
1172 | | | 1170 | |
1173 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); | | 1171 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); |
1174 | reg |= io_map_index[win].ioenable; | | 1172 | reg |= io_map_index[win].ioenable; |
1175 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); | | 1173 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); |
1176 | } | | 1174 | } |
1177 | | | 1175 | |
1178 | int | | 1176 | int |
1179 | pcic_chip_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, | | 1177 | pcic_chip_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, |
1180 | bus_size_t size, struct pcmcia_io_handle *pcihp, int *windowp) | | 1178 | bus_size_t size, struct pcmcia_io_handle *pcihp, int *windowp) |
1181 | { | | 1179 | { |
1182 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 1180 | struct pcic_handle *h = (struct pcic_handle *) pch; |
1183 | bus_addr_t ioaddr = pcihp->addr + offset; | | 1181 | bus_addr_t ioaddr = pcihp->addr + offset; |
1184 | int i, win; | | 1182 | int i, win; |
1185 | #ifdef PCICDEBUG | | 1183 | #ifdef PCICDEBUG |
1186 | static const char *width_names[] = { "auto", "io8", "io16" }; | | 1184 | static const char *width_names[] = { "auto", "io8", "io16" }; |
1187 | #endif | | 1185 | #endif |
1188 | struct pcic_softc *sc = device_private(h->ph_parent); | | 1186 | struct pcic_softc *sc = device_private(h->ph_parent); |
1189 | | | 1187 | |
1190 | /* XXX Sanity check offset/size. */ | | 1188 | /* XXX Sanity check offset/size. */ |
1191 | | | 1189 | |
1192 | win = -1; | | 1190 | win = -1; |
1193 | for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) { | | 1191 | for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) { |
1194 | if ((h->ioalloc & (1 << i)) == 0) { | | 1192 | if ((h->ioalloc & (1 << i)) == 0) { |
1195 | win = i; | | 1193 | win = i; |
1196 | h->ioalloc |= (1 << i); | | 1194 | h->ioalloc |= (1 << i); |
1197 | break; | | 1195 | break; |
1198 | } | | 1196 | } |
1199 | } | | 1197 | } |
1200 | | | 1198 | |
1201 | if (win == -1) | | 1199 | if (win == -1) |
1202 | return 1; | | 1200 | return 1; |
1203 | | | 1201 | |
1204 | *windowp = win; | | 1202 | *windowp = win; |
1205 | | | 1203 | |
1206 | /* XXX this is pretty gross */ | | 1204 | /* XXX this is pretty gross */ |
1207 | | | 1205 | |
1208 | if (!bus_space_is_equal(sc->iot, pcihp->iot)) | | 1206 | if (!bus_space_is_equal(sc->iot, pcihp->iot)) |
1209 | panic("pcic_chip_io_map iot is bogus"); | | 1207 | panic("pcic_chip_io_map iot is bogus"); |
1210 | | | 1208 | |
1211 | DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n", | | 1209 | DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n", |
1212 | win, width_names[width], (u_long) ioaddr, (u_long) size)); | | 1210 | win, width_names[width], (u_long) ioaddr, (u_long) size)); |
1213 | | | 1211 | |
1214 | /* XXX wtf is this doing here? */ | | 1212 | /* XXX wtf is this doing here? */ |
1215 | | | 1213 | |
1216 | printf("%s: port 0x%lx", device_xname(&sc->dev), (u_long) ioaddr); | | 1214 | printf("%s: port 0x%lx", device_xname(&sc->dev), (u_long) ioaddr); |
1217 | if (size > 1) | | 1215 | if (size > 1) |
1218 | printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1); | | 1216 | printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1); |
1219 | printf("\n"); | | 1217 | printf("\n"); |
1220 | | | 1218 | |
1221 | h->io[win].addr = ioaddr; | | 1219 | h->io[win].addr = ioaddr; |
1222 | h->io[win].size = size; | | 1220 | h->io[win].size = size; |
1223 | h->io[win].width = width; | | 1221 | h->io[win].width = width; |
1224 | | | 1222 | |
1225 | pcic_chip_do_io_map(h, win); | | 1223 | pcic_chip_do_io_map(h, win); |
1226 | | | 1224 | |
1227 | return 0; | | 1225 | return 0; |
1228 | } | | 1226 | } |
1229 | | | 1227 | |
1230 | void | | 1228 | void |
1231 | pcic_chip_io_unmap(pcmcia_chipset_handle_t pch, int window) | | 1229 | pcic_chip_io_unmap(pcmcia_chipset_handle_t pch, int window) |
1232 | { | | 1230 | { |
1233 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 1231 | struct pcic_handle *h = (struct pcic_handle *) pch; |
1234 | int reg; | | 1232 | int reg; |
1235 | | | 1233 | |
1236 | if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0]))) | | 1234 | if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0]))) |
1237 | panic("pcic_chip_io_unmap: window out of range"); | | 1235 | panic("pcic_chip_io_unmap: window out of range"); |
1238 | | | 1236 | |
1239 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); | | 1237 | reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); |
1240 | reg &= ~io_map_index[window].ioenable; | | 1238 | reg &= ~io_map_index[window].ioenable; |
1241 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); | | 1239 | pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); |
1242 | | | 1240 | |
1243 | h->ioalloc &= ~(1 << window); | | 1241 | h->ioalloc &= ~(1 << window); |
1244 | } | | 1242 | } |
1245 | | | 1243 | |
1246 | static int | | 1244 | static int |
1247 | pcic_wait_ready(struct pcic_handle *h) | | 1245 | pcic_wait_ready(struct pcic_handle *h) |
1248 | { | | 1246 | { |
1249 | uint8_t stat; | | 1247 | uint8_t stat; |
1250 | int i; | | 1248 | int i; |
1251 | | | 1249 | |
1252 | /* wait an initial 10ms for quick cards */ | | 1250 | /* wait an initial 10ms for quick cards */ |
1253 | stat = pcic_read(h, PCIC_IF_STATUS); | | 1251 | stat = pcic_read(h, PCIC_IF_STATUS); |
1254 | if (stat & PCIC_IF_STATUS_READY) | | 1252 | if (stat & PCIC_IF_STATUS_READY) |
1255 | return 0; | | 1253 | return 0; |
1256 | pcic_delay(h, 10, "pccwr0"); | | 1254 | pcic_delay(h, 10, "pccwr0"); |
1257 | for (i = 0; i < 50; i++) { | | 1255 | for (i = 0; i < 50; i++) { |
1258 | stat = pcic_read(h, PCIC_IF_STATUS); | | 1256 | stat = pcic_read(h, PCIC_IF_STATUS); |
1259 | if (stat & PCIC_IF_STATUS_READY) | | 1257 | if (stat & PCIC_IF_STATUS_READY) |
1260 | return 0; | | 1258 | return 0; |
1261 | if ((stat & PCIC_IF_STATUS_CARDDETECT_MASK) != | | 1259 | if ((stat & PCIC_IF_STATUS_CARDDETECT_MASK) != |
1262 | PCIC_IF_STATUS_CARDDETECT_PRESENT) | | 1260 | PCIC_IF_STATUS_CARDDETECT_PRESENT) |
1263 | return ENXIO; | | 1261 | return ENXIO; |
1264 | /* wait .1s (100ms) each iteration now */ | | 1262 | /* wait .1s (100ms) each iteration now */ |
1265 | pcic_delay(h, 100, "pccwr1"); | | 1263 | pcic_delay(h, 100, "pccwr1"); |
1266 | } | | 1264 | } |
1267 | | | 1265 | |
1268 | printf("pcic_wait_ready: ready never happened, status=%02x\n", stat); | | 1266 | printf("pcic_wait_ready: ready never happened, status=%02x\n", stat); |
1269 | return EWOULDBLOCK; | | 1267 | return EWOULDBLOCK; |
1270 | } | | 1268 | } |
1271 | | | 1269 | |
1272 | /* | | 1270 | /* |
1273 | * Perform long (msec order) delay. | | 1271 | * Perform long (msec order) delay. |
1274 | */ | | 1272 | */ |
1275 | static void | | 1273 | static void |
1276 | pcic_delay(struct pcic_handle *h, int timo, const char *wmesg) | | 1274 | pcic_delay(struct pcic_handle *h, int timo, const char *wmesg) |
1277 | /* timo: in ms. must not be zero */ | | 1275 | /* timo: in ms. must not be zero */ |
1278 | { | | 1276 | { |
1279 | | | 1277 | |
1280 | #ifdef DIAGNOSTIC | | 1278 | #ifdef DIAGNOSTIC |
1281 | if (timo <= 0) | | 1279 | if (timo <= 0) |
1282 | panic("pcic_delay: called with timeout %d", timo); | | 1280 | panic("pcic_delay: called with timeout %d", timo); |
1283 | if (!curlwp) | | 1281 | if (!curlwp) |
1284 | panic("pcic_delay: called in interrupt context"); | | 1282 | panic("pcic_delay: called in interrupt context"); |
1285 | if (!h->event_thread) | | 1283 | if (!h->event_thread) |
1286 | panic("pcic_delay: no event thread"); | | 1284 | panic("pcic_delay: no event thread"); |
1287 | #endif | | 1285 | #endif |
1288 | DPRINTF(("pcic_delay: \"%s\" %p, sleep %d ms\n", | | 1286 | DPRINTF(("pcic_delay: \"%s\" %p, sleep %d ms\n", |
1289 | wmesg, h->event_thread, timo)); | | 1287 | wmesg, h->event_thread, timo)); |
1290 | if (doing_shutdown) | | 1288 | if (doing_shutdown) |
1291 | delay(timo * 1000); | | 1289 | delay(timo * 1000); |
1292 | else | | 1290 | else |
1293 | tsleep(pcic_delay, PWAIT, wmesg, | | 1291 | tsleep(pcic_delay, PWAIT, wmesg, |
1294 | roundup(timo * hz, 1000) / 1000); | | 1292 | roundup(timo * hz, 1000) / 1000); |
1295 | } | | 1293 | } |
1296 | | | 1294 | |
1297 | void | | 1295 | void |
1298 | pcic_chip_socket_enable(pcmcia_chipset_handle_t pch) | | 1296 | pcic_chip_socket_enable(pcmcia_chipset_handle_t pch) |
1299 | { | | 1297 | { |
1300 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 1298 | struct pcic_handle *h = (struct pcic_handle *) pch; |
1301 | int win; | | 1299 | int win; |
1302 | uint8_t power, intr; | | 1300 | uint8_t power, intr; |
1303 | #ifdef DIAGNOSTIC | | 1301 | #ifdef DIAGNOSTIC |
1304 | int reg; | | 1302 | int reg; |
1305 | #endif | | 1303 | #endif |
1306 | | | 1304 | |
1307 | #ifdef DIAGNOSTIC | | 1305 | #ifdef DIAGNOSTIC |
1308 | if (h->flags & PCIC_FLAG_ENABLED) | | 1306 | if (h->flags & PCIC_FLAG_ENABLED) |
1309 | printf("pcic_chip_socket_enable: enabling twice\n"); | | 1307 | printf("pcic_chip_socket_enable: enabling twice\n"); |
1310 | #endif | | 1308 | #endif |
1311 | | | 1309 | |
1312 | /* disable interrupts; assert RESET */ | | 1310 | /* disable interrupts; assert RESET */ |
1313 | intr = pcic_read(h, PCIC_INTR); | | 1311 | intr = pcic_read(h, PCIC_INTR); |
1314 | intr &= PCIC_INTR_ENABLE; | | 1312 | intr &= PCIC_INTR_ENABLE; |
1315 | pcic_write(h, PCIC_INTR, intr); | | 1313 | pcic_write(h, PCIC_INTR, intr); |
1316 | | | 1314 | |
1317 | /* zero out the address windows */ | | 1315 | /* zero out the address windows */ |
1318 | pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); | | 1316 | pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); |
1319 | | | 1317 | |
1320 | /* power off; assert output enable bit */ | | 1318 | /* power off; assert output enable bit */ |
1321 | power = PCIC_PWRCTL_OE; | | 1319 | power = PCIC_PWRCTL_OE; |
1322 | pcic_write(h, PCIC_PWRCTL, power); | | 1320 | pcic_write(h, PCIC_PWRCTL, power); |
1323 | | | 1321 | |
1324 | /* | | 1322 | /* |
1325 | * power hack for RICOH RF5C[23]96 | | 1323 | * power hack for RICOH RF5C[23]96 |
1326 | */ | | 1324 | */ |
1327 | switch (h->vendor) { | | 1325 | switch (h->vendor) { |
1328 | case PCIC_VENDOR_RICOH_5C296: | | 1326 | case PCIC_VENDOR_RICOH_5C296: |
1329 | case PCIC_VENDOR_RICOH_5C396: | | 1327 | case PCIC_VENDOR_RICOH_5C396: |
1330 | { | | 1328 | { |
1331 | int regtmp; | | 1329 | int regtmp; |
1332 | regtmp = pcic_read(h, PCIC_RICOH_REG_MCR2); | | 1330 | regtmp = pcic_read(h, PCIC_RICOH_REG_MCR2); |
1333 | #ifdef RICOH_POWER_HACK | | 1331 | #ifdef RICOH_POWER_HACK |
1334 | regtmp |= PCIC_RICOH_MCR2_VCC_DIRECT; | | 1332 | regtmp |= PCIC_RICOH_MCR2_VCC_DIRECT; |
1335 | #else | | 1333 | #else |
1336 | regtmp &= | | 1334 | regtmp &= |
1337 | ~(PCIC_RICOH_MCR2_VCC_DIRECT|PCIC_RICOH_MCR2_VCC_SEL_3V); | | 1335 | ~(PCIC_RICOH_MCR2_VCC_DIRECT|PCIC_RICOH_MCR2_VCC_SEL_3V); |
1338 | #endif | | 1336 | #endif |
1339 | pcic_write(h, PCIC_RICOH_REG_MCR2, regtmp); | | 1337 | pcic_write(h, PCIC_RICOH_REG_MCR2, regtmp); |
1340 | } | | 1338 | } |
1341 | break; | | 1339 | break; |
1342 | default: | | 1340 | default: |
1343 | break; | | 1341 | break; |
1344 | } | | 1342 | } |
1345 | | | 1343 | |
1346 | #ifdef VADEM_POWER_HACK | | 1344 | #ifdef VADEM_POWER_HACK |
1347 | bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x0e); | | 1345 | bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x0e); |
1348 | bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x37); | | 1346 | bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x37); |
1349 | printf("prcr = %02x\n", pcic_read(h, 0x02)); | | 1347 | printf("prcr = %02x\n", pcic_read(h, 0x02)); |
1350 | printf("cvsr = %02x\n", pcic_read(h, 0x2f)); | | 1348 | printf("cvsr = %02x\n", pcic_read(h, 0x2f)); |
1351 | printf("DANGER WILL ROBINSON! Changing voltage select!\n"); | | 1349 | printf("DANGER WILL ROBINSON! Changing voltage select!\n"); |
1352 | pcic_write(h, 0x2f, pcic_read(h, 0x2f) & ~0x03); | | 1350 | pcic_write(h, 0x2f, pcic_read(h, 0x2f) & ~0x03); |
1353 | printf("cvsr = %02x\n", pcic_read(h, 0x2f)); | | 1351 | printf("cvsr = %02x\n", pcic_read(h, 0x2f)); |
1354 | #endif | | 1352 | #endif |
1355 | | | 1353 | |
1356 | /* power up the socket */ | | 1354 | /* power up the socket */ |
1357 | power |= PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC; | | 1355 | power |= PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC; |
1358 | pcic_write(h, PCIC_PWRCTL, power); | | 1356 | pcic_write(h, PCIC_PWRCTL, power); |
1359 | | | 1357 | |
1360 | /* | | 1358 | /* |
1361 | * Table 4-18 and figure 4-6 of the PC Card specifiction say: | | 1359 | * Table 4-18 and figure 4-6 of the PC Card specifiction say: |
1362 | * Vcc Rising Time (Tpr) = 100ms | | 1360 | * Vcc Rising Time (Tpr) = 100ms |
1363 | * RESET Width (Th (Hi-z RESET)) = 1ms | | 1361 | * RESET Width (Th (Hi-z RESET)) = 1ms |
1364 | * RESET Width (Tw (RESET)) = 10us | | 1362 | * RESET Width (Tw (RESET)) = 10us |
1365 | * | | 1363 | * |
1366 | * some machines require some more time to be settled | | 1364 | * some machines require some more time to be settled |
1367 | * (100ms is added here). | | 1365 | * (100ms is added here). |
1368 | */ | | 1366 | */ |
1369 | pcic_delay(h, 200 + 1, "pccen1"); | | 1367 | pcic_delay(h, 200 + 1, "pccen1"); |
1370 | | | 1368 | |
1371 | /* negate RESET */ | | 1369 | /* negate RESET */ |
1372 | intr |= PCIC_INTR_RESET; | | 1370 | intr |= PCIC_INTR_RESET; |
1373 | pcic_write(h, PCIC_INTR, intr); | | 1371 | pcic_write(h, PCIC_INTR, intr); |
1374 | | | 1372 | |
1375 | /* | | 1373 | /* |
1376 | * RESET Setup Time (Tsu (RESET)) = 20ms | | 1374 | * RESET Setup Time (Tsu (RESET)) = 20ms |
1377 | */ | | 1375 | */ |
1378 | pcic_delay(h, 20, "pccen2"); | | 1376 | pcic_delay(h, 20, "pccen2"); |
1379 | | | 1377 | |
1380 | #ifdef DIAGNOSTIC | | 1378 | #ifdef DIAGNOSTIC |
1381 | reg = pcic_read(h, PCIC_IF_STATUS); | | 1379 | reg = pcic_read(h, PCIC_IF_STATUS); |
1382 | if ((reg & PCIC_IF_STATUS_POWERACTIVE) == 0) | | 1380 | if ((reg & PCIC_IF_STATUS_POWERACTIVE) == 0) |
1383 | printf("pcic_chip_socket_enable: no power, status=%x\n", reg); | | 1381 | printf("pcic_chip_socket_enable: no power, status=%x\n", reg); |
1384 | #endif | | 1382 | #endif |
1385 | | | 1383 | |
1386 | /* wait for the chip to finish initializing */ | | 1384 | /* wait for the chip to finish initializing */ |
1387 | if (pcic_wait_ready(h)) { | | 1385 | if (pcic_wait_ready(h)) { |
1388 | /* XXX return a failure status?? */ | | 1386 | /* XXX return a failure status?? */ |
1389 | pcic_write(h, PCIC_PWRCTL, 0); | | 1387 | pcic_write(h, PCIC_PWRCTL, 0); |
1390 | return; | | 1388 | return; |
1391 | } | | 1389 | } |
1392 | | | 1390 | |
1393 | /* reinstall all the memory and io mappings */ | | 1391 | /* reinstall all the memory and io mappings */ |
1394 | for (win = 0; win < PCIC_MEM_WINS; win++) | | 1392 | for (win = 0; win < PCIC_MEM_WINS; win++) |
1395 | if (h->memalloc & (1 << win)) | | 1393 | if (h->memalloc & (1 << win)) |
1396 | pcic_chip_do_mem_map(h, win); | | 1394 | pcic_chip_do_mem_map(h, win); |
1397 | for (win = 0; win < PCIC_IO_WINS; win++) | | 1395 | for (win = 0; win < PCIC_IO_WINS; win++) |
1398 | if (h->ioalloc & (1 << win)) | | 1396 | if (h->ioalloc & (1 << win)) |
1399 | pcic_chip_do_io_map(h, win); | | 1397 | pcic_chip_do_io_map(h, win); |
1400 | | | 1398 | |
1401 | h->flags |= PCIC_FLAG_ENABLED; | | 1399 | h->flags |= PCIC_FLAG_ENABLED; |
1402 | } | | 1400 | } |
1403 | | | 1401 | |
1404 | void | | 1402 | void |
1405 | pcic_chip_socket_disable(pcmcia_chipset_handle_t pch) | | 1403 | pcic_chip_socket_disable(pcmcia_chipset_handle_t pch) |
1406 | { | | 1404 | { |
1407 | struct pcic_handle *h = (struct pcic_handle *) pch; | | 1405 | struct pcic_handle *h = (struct pcic_handle *) pch; |
1408 | uint8_t intr; | | 1406 | uint8_t intr; |
1409 | | | 1407 | |
1410 | DPRINTF(("pcic_chip_socket_disable\n")); | | 1408 | DPRINTF(("pcic_chip_socket_disable\n")); |