Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcmcia_cis.c
Go to the documentation of this file.
1 /*
2  * PCMCIA high-level CIS access functions
3  *
4  * The initial developer of the original code is David A. Hinds
5  * <[email protected]>. Portions created by David A. Hinds
6  * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
7  *
8  * Copyright (C) 1999 David A. Hinds
9  * Copyright (C) 2004-2010 Dominik Brodowski
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  *
15  */
16 
17 #include <linux/slab.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/netdevice.h>
21 
22 #include <pcmcia/cisreg.h>
23 #include <pcmcia/cistpl.h>
24 #include <pcmcia/ss.h>
25 #include <pcmcia/ds.h>
26 #include "cs_internal.h"
27 
28 
38 int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
39  cisdata_t code, void *parse)
40 {
41  tuple_t tuple;
42  cisdata_t *buf;
43  int ret;
44 
45  buf = kmalloc(256, GFP_KERNEL);
46  if (buf == NULL) {
47  dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
48  return -ENOMEM;
49  }
50  tuple.DesiredTuple = code;
51  tuple.Attributes = 0;
52  if (function == BIND_FN_ALL)
54  ret = pccard_get_first_tuple(s, function, &tuple);
55  if (ret != 0)
56  goto done;
57  tuple.TupleData = buf;
58  tuple.TupleOffset = 0;
59  tuple.TupleDataMax = 255;
60  ret = pccard_get_tuple_data(s, &tuple);
61  if (ret != 0)
62  goto done;
63  ret = pcmcia_parse_tuple(&tuple, parse);
64 done:
65  kfree(buf);
66  return ret;
67 }
68 
69 
85 int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
86  cisdata_t code, cisparse_t *parse, void *priv_data,
87  int (*loop_tuple) (tuple_t *tuple,
88  cisparse_t *parse,
89  void *priv_data))
90 {
91  tuple_t tuple;
92  cisdata_t *buf;
93  int ret;
94 
95  buf = kzalloc(256, GFP_KERNEL);
96  if (buf == NULL) {
97  dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
98  return -ENOMEM;
99  }
100 
101  tuple.TupleData = buf;
102  tuple.TupleDataMax = 255;
103  tuple.TupleOffset = 0;
104  tuple.DesiredTuple = code;
105  tuple.Attributes = 0;
106 
107  ret = pccard_get_first_tuple(s, function, &tuple);
108  while (!ret) {
109  if (pccard_get_tuple_data(s, &tuple))
110  goto next_entry;
111 
112  if (parse)
113  if (pcmcia_parse_tuple(&tuple, parse))
114  goto next_entry;
115 
116  ret = loop_tuple(&tuple, parse, priv_data);
117  if (!ret)
118  break;
119 
120 next_entry:
121  ret = pccard_get_next_tuple(s, function, &tuple);
122  }
123 
124  kfree(buf);
125  return ret;
126 }
127 
128 
132 static int pcmcia_io_cfg_data_width(unsigned int flags)
133 {
134  if (!(flags & CISTPL_IO_8BIT))
135  return IO_DATA_PATH_WIDTH_16;
136  if (!(flags & CISTPL_IO_16BIT))
137  return IO_DATA_PATH_WIDTH_8;
138  return IO_DATA_PATH_WIDTH_AUTO;
139 }
140 
141 
142 struct pcmcia_cfg_mem {
143  struct pcmcia_device *p_dev;
144  int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
145  void *priv_data;
148 };
149 
157 static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
158 {
159  struct pcmcia_cfg_mem *cfg_mem = priv;
160  struct pcmcia_device *p_dev = cfg_mem->p_dev;
162  cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
163  unsigned int flags = p_dev->config_flags;
164  unsigned int vcc = p_dev->socket->socket.Vcc;
165 
166  dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
167  cfg->index, flags);
168 
169  /* default values */
170  cfg_mem->p_dev->config_index = cfg->index;
171  if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
172  cfg_mem->dflt = *cfg;
173 
174  /* check for matching Vcc? */
175  if (flags & CONF_AUTO_CHECK_VCC) {
176  if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
177  if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
178  return -ENODEV;
179  } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
180  if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
181  return -ENODEV;
182  }
183  }
184 
185  /* set Vpp? */
186  if (flags & CONF_AUTO_SET_VPP) {
187  if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
188  p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
189  else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
190  p_dev->vpp =
191  dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
192  }
193 
194  /* enable audio? */
195  if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
196  p_dev->config_flags |= CONF_ENABLE_SPKR;
197 
198 
199  /* IO window settings? */
200  if (flags & CONF_AUTO_SET_IO) {
201  cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
202  int i = 0;
203 
204  p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
205  p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
206  if (io->nwin == 0)
207  return -ENODEV;
208 
209  p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
210  p_dev->resource[0]->flags |=
211  pcmcia_io_cfg_data_width(io->flags);
212  if (io->nwin > 1) {
213  /* For multifunction cards, by convention, we
214  * configure the network function with window 0,
215  * and serial with window 1 */
216  i = (io->win[1].len > io->win[0].len);
217  p_dev->resource[1]->flags = p_dev->resource[0]->flags;
218  p_dev->resource[1]->start = io->win[1-i].base;
219  p_dev->resource[1]->end = io->win[1-i].len;
220  }
221  p_dev->resource[0]->start = io->win[i].base;
222  p_dev->resource[0]->end = io->win[i].len;
223  p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
224  }
225 
226  /* MEM window settings? */
227  if (flags & CONF_AUTO_SET_IOMEM) {
228  /* so far, we only set one memory window */
229  cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
230 
231  p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
232  if (mem->nwin == 0)
233  return -ENODEV;
234 
235  p_dev->resource[2]->start = mem->win[0].host_addr;
236  p_dev->resource[2]->end = mem->win[0].len;
237  if (p_dev->resource[2]->end < 0x1000)
238  p_dev->resource[2]->end = 0x1000;
239  p_dev->card_addr = mem->win[0].card_addr;
240  }
241 
242  dev_dbg(&p_dev->dev,
243  "checking configuration %x: %pr %pr %pr (%d lines)\n",
244  p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
245  p_dev->resource[2], p_dev->io_lines);
246 
247  return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
248 }
249 
262 int pcmcia_loop_config(struct pcmcia_device *p_dev,
263  int (*conf_check) (struct pcmcia_device *p_dev,
264  void *priv_data),
265  void *priv_data)
266 {
267  struct pcmcia_cfg_mem *cfg_mem;
268  int ret;
269 
270  cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
271  if (cfg_mem == NULL)
272  return -ENOMEM;
273 
274  cfg_mem->p_dev = p_dev;
275  cfg_mem->conf_check = conf_check;
276  cfg_mem->priv_data = priv_data;
277 
278  ret = pccard_loop_tuple(p_dev->socket, p_dev->func,
279  CISTPL_CFTABLE_ENTRY, &cfg_mem->parse,
280  cfg_mem, pcmcia_do_loop_config);
281 
282  kfree(cfg_mem);
283  return ret;
284 }
285 EXPORT_SYMBOL(pcmcia_loop_config);
286 
287 
288 struct pcmcia_loop_mem {
289  struct pcmcia_device *p_dev;
290  void *priv_data;
291  int (*loop_tuple) (struct pcmcia_device *p_dev,
292  tuple_t *tuple,
293  void *priv_data);
294 };
295 
303 static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv)
304 {
305  struct pcmcia_loop_mem *loop = priv;
306 
307  return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data);
308 };
309 
322 int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code,
323  int (*loop_tuple) (struct pcmcia_device *p_dev,
324  tuple_t *tuple,
325  void *priv_data),
326  void *priv_data)
327 {
328  struct pcmcia_loop_mem loop = {
329  .p_dev = p_dev,
330  .loop_tuple = loop_tuple,
331  .priv_data = priv_data};
332 
333  return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL,
334  &loop, pcmcia_do_loop_tuple);
335 }
336 EXPORT_SYMBOL(pcmcia_loop_tuple);
337 
338 
339 struct pcmcia_loop_get {
340  size_t len;
341  cisdata_t **buf;
342 };
343 
353 static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple,
354  void *priv)
355 {
356  struct pcmcia_loop_get *get = priv;
357 
358  *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL);
359  if (*get->buf) {
360  get->len = tuple->TupleDataLen;
361  memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen);
362  } else
363  dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n");
364  return 0;
365 }
366 
377 size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code,
378  unsigned char **buf)
379 {
380  struct pcmcia_loop_get get = {
381  .len = 0,
382  .buf = buf,
383  };
384 
385  *get.buf = NULL;
386  pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get);
387 
388  return get.len;
389 }
390 EXPORT_SYMBOL(pcmcia_get_tuple);
391 
392 
401 static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple,
402  void *priv)
403 {
404  struct net_device *dev = priv;
405  int i;
406 
407  if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
408  return -EINVAL;
409  if (tuple->TupleDataLen < ETH_ALEN + 2) {
410  dev_warn(&p_dev->dev, "Invalid CIS tuple length for "
411  "LAN_NODE_ID\n");
412  return -EINVAL;
413  }
414 
415  if (tuple->TupleData[1] != ETH_ALEN) {
416  dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n");
417  return -EINVAL;
418  }
419  for (i = 0; i < 6; i++)
420  dev->dev_addr[i] = tuple->TupleData[i+2];
421  return 0;
422 }
423 
433 int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev)
434 {
435  return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev);
436 }
437 EXPORT_SYMBOL(pcmcia_get_mac_from_cis);
438