diff options
Diffstat (limited to 'drivers/char/pcmcia/ipwireless/main.c')
-rw-r--r-- | drivers/char/pcmcia/ipwireless/main.c | 296 |
1 files changed, 100 insertions, 196 deletions
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 5216fce0c62d..dff24dae1485 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c | |||
@@ -65,10 +65,7 @@ static void signalled_reboot_work(struct work_struct *work_reboot) | |||
65 | struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev, | 65 | struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev, |
66 | work_reboot); | 66 | work_reboot); |
67 | struct pcmcia_device *link = ipw->link; | 67 | struct pcmcia_device *link = ipw->link; |
68 | int ret = pcmcia_reset_card(link->socket); | 68 | pcmcia_reset_card(link->socket); |
69 | |||
70 | if (ret != 0) | ||
71 | cs_error(link, ResetCard, ret); | ||
72 | } | 69 | } |
73 | 70 | ||
74 | static void signalled_reboot_callback(void *callback_data) | 71 | static void signalled_reboot_callback(void *callback_data) |
@@ -79,208 +76,127 @@ static void signalled_reboot_callback(void *callback_data) | |||
79 | schedule_work(&ipw->work_reboot); | 76 | schedule_work(&ipw->work_reboot); |
80 | } | 77 | } |
81 | 78 | ||
82 | static int config_ipwireless(struct ipw_dev *ipw) | 79 | static int ipwireless_probe(struct pcmcia_device *p_dev, |
80 | cistpl_cftable_entry_t *cfg, | ||
81 | cistpl_cftable_entry_t *dflt, | ||
82 | unsigned int vcc, | ||
83 | void *priv_data) | ||
83 | { | 84 | { |
84 | struct pcmcia_device *link = ipw->link; | 85 | struct ipw_dev *ipw = priv_data; |
85 | int ret; | 86 | struct resource *io_resource; |
86 | tuple_t tuple; | ||
87 | unsigned short buf[64]; | ||
88 | cisparse_t parse; | ||
89 | unsigned short cor_value; | ||
90 | memreq_t memreq_attr_memory; | 87 | memreq_t memreq_attr_memory; |
91 | memreq_t memreq_common_memory; | 88 | memreq_t memreq_common_memory; |
89 | int ret; | ||
92 | 90 | ||
93 | ipw->is_v2_card = 0; | 91 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
94 | 92 | p_dev->io.BasePort1 = cfg->io.win[0].base; | |
95 | tuple.Attributes = 0; | 93 | p_dev->io.NumPorts1 = cfg->io.win[0].len; |
96 | tuple.TupleData = (cisdata_t *) buf; | 94 | p_dev->io.IOAddrLines = 16; |
97 | tuple.TupleDataMax = sizeof(buf); | ||
98 | tuple.TupleOffset = 0; | ||
99 | |||
100 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; | ||
101 | |||
102 | ret = pcmcia_get_first_tuple(link, &tuple); | ||
103 | |||
104 | while (ret == 0) { | ||
105 | ret = pcmcia_get_tuple_data(link, &tuple); | ||
106 | |||
107 | if (ret != 0) { | ||
108 | cs_error(link, GetTupleData, ret); | ||
109 | goto exit0; | ||
110 | } | ||
111 | ret = pcmcia_get_next_tuple(link, &tuple); | ||
112 | } | ||
113 | |||
114 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
115 | |||
116 | ret = pcmcia_get_first_tuple(link, &tuple); | ||
117 | |||
118 | if (ret != 0) { | ||
119 | cs_error(link, GetFirstTuple, ret); | ||
120 | goto exit0; | ||
121 | } | ||
122 | |||
123 | ret = pcmcia_get_tuple_data(link, &tuple); | ||
124 | |||
125 | if (ret != 0) { | ||
126 | cs_error(link, GetTupleData, ret); | ||
127 | goto exit0; | ||
128 | } | ||
129 | |||
130 | ret = pcmcia_parse_tuple(&tuple, &parse); | ||
131 | |||
132 | if (ret != 0) { | ||
133 | cs_error(link, ParseTuple, ret); | ||
134 | goto exit0; | ||
135 | } | ||
136 | |||
137 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
138 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
139 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
140 | link->io.IOAddrLines = 16; | ||
141 | |||
142 | link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; | ||
143 | 95 | ||
144 | /* 0x40 causes it to generate level mode interrupts. */ | 96 | /* 0x40 causes it to generate level mode interrupts. */ |
145 | /* 0x04 enables IREQ pin. */ | 97 | /* 0x04 enables IREQ pin. */ |
146 | cor_value = parse.cftable_entry.index | 0x44; | 98 | p_dev->conf.ConfigIndex = cfg->index | 0x44; |
147 | link->conf.ConfigIndex = cor_value; | 99 | ret = pcmcia_request_io(p_dev, &p_dev->io); |
100 | if (ret) | ||
101 | return ret; | ||
148 | 102 | ||
149 | /* IRQ and I/O settings */ | 103 | io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1, |
150 | tuple.DesiredTuple = CISTPL_CONFIG; | 104 | IPWIRELESS_PCCARD_NAME); |
151 | 105 | ||
152 | ret = pcmcia_get_first_tuple(link, &tuple); | 106 | if (cfg->mem.nwin == 0) |
107 | return 0; | ||
153 | 108 | ||
154 | if (ret != 0) { | 109 | ipw->request_common_memory.Attributes = |
155 | cs_error(link, GetFirstTuple, ret); | 110 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
156 | goto exit0; | 111 | ipw->request_common_memory.Base = cfg->mem.win[0].host_addr; |
157 | } | 112 | ipw->request_common_memory.Size = cfg->mem.win[0].len; |
113 | if (ipw->request_common_memory.Size < 0x1000) | ||
114 | ipw->request_common_memory.Size = 0x1000; | ||
115 | ipw->request_common_memory.AccessSpeed = 0; | ||
158 | 116 | ||
159 | ret = pcmcia_get_tuple_data(link, &tuple); | 117 | ret = pcmcia_request_window(p_dev, &ipw->request_common_memory, |
160 | 118 | &ipw->handle_common_memory); | |
161 | if (ret != 0) { | ||
162 | cs_error(link, GetTupleData, ret); | ||
163 | goto exit0; | ||
164 | } | ||
165 | 119 | ||
166 | ret = pcmcia_parse_tuple(&tuple, &parse); | 120 | if (ret != 0) |
121 | goto exit1; | ||
167 | 122 | ||
168 | if (ret != 0) { | 123 | memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr; |
169 | cs_error(link, GetTupleData, ret); | 124 | memreq_common_memory.Page = 0; |
170 | goto exit0; | ||
171 | } | ||
172 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
173 | link->conf.ConfigBase = parse.config.base; | ||
174 | link->conf.Present = parse.config.rmask[0]; | ||
175 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
176 | 125 | ||
177 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; | 126 | ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory, |
178 | link->irq.Handler = ipwireless_interrupt; | 127 | &memreq_common_memory); |
179 | link->irq.Instance = ipw->hardware; | ||
180 | 128 | ||
181 | ret = pcmcia_request_io(link, &link->io); | 129 | if (ret != 0) |
130 | goto exit2; | ||
182 | 131 | ||
183 | if (ret != 0) { | 132 | ipw->is_v2_card = cfg->mem.win[0].len == 0x100; |
184 | cs_error(link, RequestIO, ret); | ||
185 | goto exit0; | ||
186 | } | ||
187 | 133 | ||
188 | request_region(link->io.BasePort1, link->io.NumPorts1, | 134 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, |
135 | ipw->request_common_memory.Size); | ||
136 | request_mem_region(ipw->request_common_memory.Base, | ||
137 | ipw->request_common_memory.Size, | ||
189 | IPWIRELESS_PCCARD_NAME); | 138 | IPWIRELESS_PCCARD_NAME); |
190 | 139 | ||
191 | /* memory settings */ | 140 | ipw->request_attr_memory.Attributes = |
192 | 141 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | |
193 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 142 | ipw->request_attr_memory.Base = 0; |
194 | 143 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ | |
195 | ret = pcmcia_get_first_tuple(link, &tuple); | 144 | ipw->request_attr_memory.AccessSpeed = 0; |
196 | |||
197 | if (ret != 0) { | ||
198 | cs_error(link, GetFirstTuple, ret); | ||
199 | goto exit1; | ||
200 | } | ||
201 | |||
202 | ret = pcmcia_get_tuple_data(link, &tuple); | ||
203 | 145 | ||
204 | if (ret != 0) { | 146 | ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory, |
205 | cs_error(link, GetTupleData, ret); | 147 | &ipw->handle_attr_memory); |
206 | goto exit1; | ||
207 | } | ||
208 | |||
209 | ret = pcmcia_parse_tuple(&tuple, &parse); | ||
210 | |||
211 | if (ret != 0) { | ||
212 | cs_error(link, ParseTuple, ret); | ||
213 | goto exit1; | ||
214 | } | ||
215 | 148 | ||
216 | if (parse.cftable_entry.mem.nwin > 0) { | 149 | if (ret != 0) |
217 | ipw->request_common_memory.Attributes = | 150 | goto exit2; |
218 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; | ||
219 | ipw->request_common_memory.Base = | ||
220 | parse.cftable_entry.mem.win[0].host_addr; | ||
221 | ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; | ||
222 | if (ipw->request_common_memory.Size < 0x1000) | ||
223 | ipw->request_common_memory.Size = 0x1000; | ||
224 | ipw->request_common_memory.AccessSpeed = 0; | ||
225 | |||
226 | ret = pcmcia_request_window(&link, &ipw->request_common_memory, | ||
227 | &ipw->handle_common_memory); | ||
228 | 151 | ||
229 | if (ret != 0) { | 152 | memreq_attr_memory.CardOffset = 0; |
230 | cs_error(link, RequestWindow, ret); | 153 | memreq_attr_memory.Page = 0; |
231 | goto exit1; | ||
232 | } | ||
233 | 154 | ||
234 | memreq_common_memory.CardOffset = | 155 | ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, |
235 | parse.cftable_entry.mem.win[0].card_addr; | 156 | &memreq_attr_memory); |
236 | memreq_common_memory.Page = 0; | ||
237 | 157 | ||
238 | ret = pcmcia_map_mem_page(ipw->handle_common_memory, | 158 | if (ret != 0) |
239 | &memreq_common_memory); | 159 | goto exit3; |
240 | 160 | ||
241 | if (ret != 0) { | 161 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, |
242 | cs_error(link, MapMemPage, ret); | 162 | ipw->request_attr_memory.Size); |
243 | goto exit1; | 163 | request_mem_region(ipw->request_attr_memory.Base, |
244 | } | 164 | ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); |
245 | 165 | ||
246 | ipw->is_v2_card = | 166 | return 0; |
247 | parse.cftable_entry.mem.win[0].len == 0x100; | ||
248 | 167 | ||
249 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, | 168 | exit3: |
169 | pcmcia_release_window(p_dev, ipw->handle_attr_memory); | ||
170 | exit2: | ||
171 | if (ipw->common_memory) { | ||
172 | release_mem_region(ipw->request_common_memory.Base, | ||
250 | ipw->request_common_memory.Size); | 173 | ipw->request_common_memory.Size); |
251 | request_mem_region(ipw->request_common_memory.Base, | 174 | iounmap(ipw->common_memory); |
252 | ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); | 175 | pcmcia_release_window(p_dev, ipw->handle_common_memory); |
253 | 176 | } else | |
254 | ipw->request_attr_memory.Attributes = | 177 | pcmcia_release_window(p_dev, ipw->handle_common_memory); |
255 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | 178 | exit1: |
256 | ipw->request_attr_memory.Base = 0; | 179 | release_resource(io_resource); |
257 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ | 180 | pcmcia_disable_device(p_dev); |
258 | ipw->request_attr_memory.AccessSpeed = 0; | 181 | return -1; |
259 | 182 | } | |
260 | ret = pcmcia_request_window(&link, &ipw->request_attr_memory, | ||
261 | &ipw->handle_attr_memory); | ||
262 | 183 | ||
263 | if (ret != 0) { | 184 | static int config_ipwireless(struct ipw_dev *ipw) |
264 | cs_error(link, RequestWindow, ret); | 185 | { |
265 | goto exit2; | 186 | struct pcmcia_device *link = ipw->link; |
266 | } | 187 | int ret = 0; |
267 | 188 | ||
268 | memreq_attr_memory.CardOffset = 0; | 189 | ipw->is_v2_card = 0; |
269 | memreq_attr_memory.Page = 0; | ||
270 | 190 | ||
271 | ret = pcmcia_map_mem_page(ipw->handle_attr_memory, | 191 | ret = pcmcia_loop_config(link, ipwireless_probe, ipw); |
272 | &memreq_attr_memory); | 192 | if (ret != 0) |
193 | return ret; | ||
273 | 194 | ||
274 | if (ret != 0) { | 195 | link->conf.Attributes = CONF_ENABLE_IRQ; |
275 | cs_error(link, MapMemPage, ret); | 196 | link->conf.IntType = INT_MEMORY_AND_IO; |
276 | goto exit2; | ||
277 | } | ||
278 | 197 | ||
279 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, | 198 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
280 | ipw->request_attr_memory.Size); | 199 | link->irq.Handler = ipwireless_interrupt; |
281 | request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, | ||
282 | IPWIRELESS_PCCARD_NAME); | ||
283 | } | ||
284 | 200 | ||
285 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); | 201 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); |
286 | 202 | ||
@@ -291,10 +207,8 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
291 | 207 | ||
292 | ret = pcmcia_request_irq(link, &link->irq); | 208 | ret = pcmcia_request_irq(link, &link->irq); |
293 | 209 | ||
294 | if (ret != 0) { | 210 | if (ret != 0) |
295 | cs_error(link, RequestIRQ, ret); | 211 | goto exit; |
296 | goto exit3; | ||
297 | } | ||
298 | 212 | ||
299 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", | 213 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", |
300 | ipw->is_v2_card ? "V2/V3" : "V1"); | 214 | ipw->is_v2_card ? "V2/V3" : "V1"); |
@@ -316,12 +230,12 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
316 | 230 | ||
317 | ipw->network = ipwireless_network_create(ipw->hardware); | 231 | ipw->network = ipwireless_network_create(ipw->hardware); |
318 | if (!ipw->network) | 232 | if (!ipw->network) |
319 | goto exit3; | 233 | goto exit; |
320 | 234 | ||
321 | ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, | 235 | ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, |
322 | ipw->nodes); | 236 | ipw->nodes); |
323 | if (!ipw->tty) | 237 | if (!ipw->tty) |
324 | goto exit3; | 238 | goto exit; |
325 | 239 | ||
326 | ipwireless_init_hardware_v2_v3(ipw->hardware); | 240 | ipwireless_init_hardware_v2_v3(ipw->hardware); |
327 | 241 | ||
@@ -331,35 +245,27 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
331 | */ | 245 | */ |
332 | ret = pcmcia_request_configuration(link, &link->conf); | 246 | ret = pcmcia_request_configuration(link, &link->conf); |
333 | 247 | ||
334 | if (ret != 0) { | 248 | if (ret != 0) |
335 | cs_error(link, RequestConfiguration, ret); | 249 | goto exit; |
336 | goto exit4; | ||
337 | } | ||
338 | 250 | ||
339 | link->dev_node = &ipw->nodes[0]; | 251 | link->dev_node = &ipw->nodes[0]; |
340 | 252 | ||
341 | return 0; | 253 | return 0; |
342 | 254 | ||
343 | exit4: | 255 | exit: |
344 | pcmcia_disable_device(link); | ||
345 | exit3: | ||
346 | if (ipw->attr_memory) { | 256 | if (ipw->attr_memory) { |
347 | release_mem_region(ipw->request_attr_memory.Base, | 257 | release_mem_region(ipw->request_attr_memory.Base, |
348 | ipw->request_attr_memory.Size); | 258 | ipw->request_attr_memory.Size); |
349 | iounmap(ipw->attr_memory); | 259 | iounmap(ipw->attr_memory); |
350 | pcmcia_release_window(ipw->handle_attr_memory); | 260 | pcmcia_release_window(link, ipw->handle_attr_memory); |
351 | pcmcia_disable_device(link); | ||
352 | } | 261 | } |
353 | exit2: | ||
354 | if (ipw->common_memory) { | 262 | if (ipw->common_memory) { |
355 | release_mem_region(ipw->request_common_memory.Base, | 263 | release_mem_region(ipw->request_common_memory.Base, |
356 | ipw->request_common_memory.Size); | 264 | ipw->request_common_memory.Size); |
357 | iounmap(ipw->common_memory); | 265 | iounmap(ipw->common_memory); |
358 | pcmcia_release_window(ipw->handle_common_memory); | 266 | pcmcia_release_window(link, ipw->handle_common_memory); |
359 | } | 267 | } |
360 | exit1: | ||
361 | pcmcia_disable_device(link); | 268 | pcmcia_disable_device(link); |
362 | exit0: | ||
363 | return -1; | 269 | return -1; |
364 | } | 270 | } |
365 | 271 | ||
@@ -378,9 +284,9 @@ static void release_ipwireless(struct ipw_dev *ipw) | |||
378 | iounmap(ipw->attr_memory); | 284 | iounmap(ipw->attr_memory); |
379 | } | 285 | } |
380 | if (ipw->common_memory) | 286 | if (ipw->common_memory) |
381 | pcmcia_release_window(ipw->handle_common_memory); | 287 | pcmcia_release_window(ipw->link, ipw->handle_common_memory); |
382 | if (ipw->attr_memory) | 288 | if (ipw->attr_memory) |
383 | pcmcia_release_window(ipw->handle_attr_memory); | 289 | pcmcia_release_window(ipw->link, ipw->handle_attr_memory); |
384 | 290 | ||
385 | /* Break the link with Card Services */ | 291 | /* Break the link with Card Services */ |
386 | pcmcia_disable_device(ipw->link); | 292 | pcmcia_disable_device(ipw->link); |
@@ -406,7 +312,6 @@ static int ipwireless_attach(struct pcmcia_device *link) | |||
406 | 312 | ||
407 | ipw->link = link; | 313 | ipw->link = link; |
408 | link->priv = ipw; | 314 | link->priv = ipw; |
409 | link->irq.Instance = ipw; | ||
410 | 315 | ||
411 | /* Link this device into our device list. */ | 316 | /* Link this device into our device list. */ |
412 | link->dev_node = &ipw->nodes[0]; | 317 | link->dev_node = &ipw->nodes[0]; |
@@ -421,7 +326,6 @@ static int ipwireless_attach(struct pcmcia_device *link) | |||
421 | ret = config_ipwireless(ipw); | 326 | ret = config_ipwireless(ipw); |
422 | 327 | ||
423 | if (ret != 0) { | 328 | if (ret != 0) { |
424 | cs_error(link, RegisterClient, ret); | ||
425 | ipwireless_detach(link); | 329 | ipwireless_detach(link); |
426 | return ret; | 330 | return ret; |
427 | } | 331 | } |