aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pcmcia/ipwireless/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/pcmcia/ipwireless/main.c')
-rw-r--r--drivers/char/pcmcia/ipwireless/main.c296
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
74static void signalled_reboot_callback(void *callback_data) 71static 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
82static int config_ipwireless(struct ipw_dev *ipw) 79static 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, 168exit3:
169 pcmcia_release_window(p_dev, ipw->handle_attr_memory);
170exit2:
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; 178exit1:
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) { 184static 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
343exit4: 255exit:
344 pcmcia_disable_device(link);
345exit3:
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 }
353exit2:
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 }
360exit1:
361 pcmcia_disable_device(link); 268 pcmcia_disable_device(link);
362exit0:
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 }