• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * PCMCIA high-level CIS access functions
4  *
5  * The initial developer of the original code is David A. Hinds
6  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
7  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
8  *
9  * Copyright (C) 1999	     David A. Hinds
10  * Copyright (C) 2004-2010   Dominik Brodowski
11  */
12 
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/netdevice.h>
17 #include <linux/etherdevice.h>
18 
19 #include <pcmcia/cisreg.h>
20 #include <pcmcia/cistpl.h>
21 #include <pcmcia/ss.h>
22 #include <pcmcia/ds.h>
23 #include "cs_internal.h"
24 
25 
26 /**
27  * pccard_read_tuple() - internal CIS tuple access
28  * @s:		the struct pcmcia_socket where the card is inserted
29  * @function:	the device function we loop for
30  * @code:	which CIS code shall we look for?
31  * @parse:	buffer where the tuple shall be parsed (or NULL, if no parse)
32  *
33  * pccard_read_tuple() reads out one tuple and attempts to parse it
34  */
pccard_read_tuple(struct pcmcia_socket * s,unsigned int function,cisdata_t code,void * parse)35 int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
36 		cisdata_t code, void *parse)
37 {
38 	tuple_t tuple;
39 	cisdata_t *buf;
40 	int ret;
41 
42 	buf = kmalloc(256, GFP_KERNEL);
43 	if (buf == NULL) {
44 		dev_warn(&s->dev, "no memory to read tuple\n");
45 		return -ENOMEM;
46 	}
47 	tuple.DesiredTuple = code;
48 	tuple.Attributes = 0;
49 	if (function == BIND_FN_ALL)
50 		tuple.Attributes = TUPLE_RETURN_COMMON;
51 	ret = pccard_get_first_tuple(s, function, &tuple);
52 	if (ret != 0)
53 		goto done;
54 	tuple.TupleData = buf;
55 	tuple.TupleOffset = 0;
56 	tuple.TupleDataMax = 255;
57 	ret = pccard_get_tuple_data(s, &tuple);
58 	if (ret != 0)
59 		goto done;
60 	ret = pcmcia_parse_tuple(&tuple, parse);
61 done:
62 	kfree(buf);
63 	return ret;
64 }
65 
66 
67 /**
68  * pccard_loop_tuple() - loop over tuples in the CIS
69  * @s:		the struct pcmcia_socket where the card is inserted
70  * @function:	the device function we loop for
71  * @code:	which CIS code shall we look for?
72  * @parse:	buffer where the tuple shall be parsed (or NULL, if no parse)
73  * @priv_data:	private data to be passed to the loop_tuple function.
74  * @loop_tuple:	function to call for each CIS entry of type @function. IT
75  *		gets passed the raw tuple, the paresed tuple (if @parse is
76  *		set) and @priv_data.
77  *
78  * pccard_loop_tuple() loops over all CIS entries of type @function, and
79  * calls the @loop_tuple function for each entry. If the call to @loop_tuple
80  * returns 0, the loop exits. Returns 0 on success or errorcode otherwise.
81  */
pccard_loop_tuple(struct pcmcia_socket * s,unsigned int function,cisdata_t code,cisparse_t * parse,void * priv_data,int (* loop_tuple)(tuple_t * tuple,cisparse_t * parse,void * priv_data))82 static int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
83 			     cisdata_t code, cisparse_t *parse, void *priv_data,
84 			     int (*loop_tuple) (tuple_t *tuple,
85 					 cisparse_t *parse,
86 					 void *priv_data))
87 {
88 	tuple_t tuple;
89 	cisdata_t *buf;
90 	int ret;
91 
92 	buf = kzalloc(256, GFP_KERNEL);
93 	if (buf == NULL) {
94 		dev_warn(&s->dev, "no memory to read tuple\n");
95 		return -ENOMEM;
96 	}
97 
98 	tuple.TupleData = buf;
99 	tuple.TupleDataMax = 255;
100 	tuple.TupleOffset = 0;
101 	tuple.DesiredTuple = code;
102 	tuple.Attributes = 0;
103 
104 	ret = pccard_get_first_tuple(s, function, &tuple);
105 	while (!ret) {
106 		if (pccard_get_tuple_data(s, &tuple))
107 			goto next_entry;
108 
109 		if (parse)
110 			if (pcmcia_parse_tuple(&tuple, parse))
111 				goto next_entry;
112 
113 		ret = loop_tuple(&tuple, parse, priv_data);
114 		if (!ret)
115 			break;
116 
117 next_entry:
118 		ret = pccard_get_next_tuple(s, function, &tuple);
119 	}
120 
121 	kfree(buf);
122 	return ret;
123 }
124 
125 
126 /*
127  * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
128  */
pcmcia_io_cfg_data_width(unsigned int flags)129 static int pcmcia_io_cfg_data_width(unsigned int flags)
130 {
131 	if (!(flags & CISTPL_IO_8BIT))
132 		return IO_DATA_PATH_WIDTH_16;
133 	if (!(flags & CISTPL_IO_16BIT))
134 		return IO_DATA_PATH_WIDTH_8;
135 	return IO_DATA_PATH_WIDTH_AUTO;
136 }
137 
138 
139 struct pcmcia_cfg_mem {
140 	struct pcmcia_device *p_dev;
141 	int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
142 	void *priv_data;
143 	cisparse_t parse;
144 	cistpl_cftable_entry_t dflt;
145 };
146 
147 /*
148  * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config()
149  *
150  * pcmcia_do_loop_config() is the internal callback for the call from
151  * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred
152  * by a struct pcmcia_cfg_mem.
153  */
pcmcia_do_loop_config(tuple_t * tuple,cisparse_t * parse,void * priv)154 static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
155 {
156 	struct pcmcia_cfg_mem *cfg_mem = priv;
157 	struct pcmcia_device *p_dev = cfg_mem->p_dev;
158 	cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
159 	cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
160 	unsigned int flags = p_dev->config_flags;
161 	unsigned int vcc = p_dev->socket->socket.Vcc;
162 
163 	dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
164 		cfg->index, flags);
165 
166 	/* default values */
167 	cfg_mem->p_dev->config_index = cfg->index;
168 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
169 		cfg_mem->dflt = *cfg;
170 
171 	/* check for matching Vcc? */
172 	if (flags & CONF_AUTO_CHECK_VCC) {
173 		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
174 			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
175 				return -ENODEV;
176 		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
177 			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
178 				return -ENODEV;
179 		}
180 	}
181 
182 	/* set Vpp? */
183 	if (flags & CONF_AUTO_SET_VPP) {
184 		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
185 			p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
186 		else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
187 			p_dev->vpp =
188 				dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
189 	}
190 
191 	/* enable audio? */
192 	if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
193 		p_dev->config_flags |= CONF_ENABLE_SPKR;
194 
195 
196 	/* IO window settings? */
197 	if (flags & CONF_AUTO_SET_IO) {
198 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
199 		int i = 0;
200 
201 		p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
202 		p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
203 		if (io->nwin == 0)
204 			return -ENODEV;
205 
206 		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
207 		p_dev->resource[0]->flags |=
208 					pcmcia_io_cfg_data_width(io->flags);
209 		if (io->nwin > 1) {
210 			/* For multifunction cards, by convention, we
211 			 * configure the network function with window 0,
212 			 * and serial with window 1 */
213 			i = (io->win[1].len > io->win[0].len);
214 			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
215 			p_dev->resource[1]->start = io->win[1-i].base;
216 			p_dev->resource[1]->end = io->win[1-i].len;
217 		}
218 		p_dev->resource[0]->start = io->win[i].base;
219 		p_dev->resource[0]->end = io->win[i].len;
220 		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
221 	}
222 
223 	/* MEM window settings? */
224 	if (flags & CONF_AUTO_SET_IOMEM) {
225 		/* so far, we only set one memory window */
226 		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
227 
228 		p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
229 		if (mem->nwin == 0)
230 			return -ENODEV;
231 
232 		p_dev->resource[2]->start = mem->win[0].host_addr;
233 		p_dev->resource[2]->end = mem->win[0].len;
234 		if (p_dev->resource[2]->end < 0x1000)
235 			p_dev->resource[2]->end = 0x1000;
236 		p_dev->card_addr = mem->win[0].card_addr;
237 	}
238 
239 	dev_dbg(&p_dev->dev,
240 		"checking configuration %x: %pr %pr %pr (%d lines)\n",
241 		p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
242 		p_dev->resource[2], p_dev->io_lines);
243 
244 	return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
245 }
246 
247 /**
248  * pcmcia_loop_config() - loop over configuration options
249  * @p_dev:	the struct pcmcia_device which we need to loop for.
250  * @conf_check:	function to call for each configuration option.
251  *		It gets passed the struct pcmcia_device and private data
252  *		being passed to pcmcia_loop_config()
253  * @priv_data:	private data to be passed to the conf_check function.
254  *
255  * pcmcia_loop_config() loops over all configuration options, and calls
256  * the driver-specific conf_check() for each one, checking whether
257  * it is a valid one. Returns 0 on success or errorcode otherwise.
258  */
pcmcia_loop_config(struct pcmcia_device * p_dev,int (* conf_check)(struct pcmcia_device * p_dev,void * priv_data),void * priv_data)259 int pcmcia_loop_config(struct pcmcia_device *p_dev,
260 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
261 						 void *priv_data),
262 		       void *priv_data)
263 {
264 	struct pcmcia_cfg_mem *cfg_mem;
265 	int ret;
266 
267 	cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
268 	if (cfg_mem == NULL)
269 		return -ENOMEM;
270 
271 	cfg_mem->p_dev = p_dev;
272 	cfg_mem->conf_check = conf_check;
273 	cfg_mem->priv_data = priv_data;
274 
275 	ret = pccard_loop_tuple(p_dev->socket, p_dev->func,
276 				CISTPL_CFTABLE_ENTRY, &cfg_mem->parse,
277 				cfg_mem, pcmcia_do_loop_config);
278 
279 	kfree(cfg_mem);
280 	return ret;
281 }
282 EXPORT_SYMBOL(pcmcia_loop_config);
283 
284 
285 struct pcmcia_loop_mem {
286 	struct pcmcia_device *p_dev;
287 	void *priv_data;
288 	int (*loop_tuple) (struct pcmcia_device *p_dev,
289 			   tuple_t *tuple,
290 			   void *priv_data);
291 };
292 
293 /*
294  * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config()
295  *
296  * pcmcia_do_loop_tuple() is the internal callback for the call from
297  * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred
298  * by a struct pcmcia_cfg_mem.
299  */
pcmcia_do_loop_tuple(tuple_t * tuple,cisparse_t * parse,void * priv)300 static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv)
301 {
302 	struct pcmcia_loop_mem *loop = priv;
303 
304 	return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data);
305 };
306 
307 /**
308  * pcmcia_loop_tuple() - loop over tuples in the CIS
309  * @p_dev:	the struct pcmcia_device which we need to loop for.
310  * @code:	which CIS code shall we look for?
311  * @priv_data:	private data to be passed to the loop_tuple function.
312  * @loop_tuple:	function to call for each CIS entry of type @function. IT
313  *		gets passed the raw tuple and @priv_data.
314  *
315  * pcmcia_loop_tuple() loops over all CIS entries of type @function, and
316  * calls the @loop_tuple function for each entry. If the call to @loop_tuple
317  * returns 0, the loop exits. Returns 0 on success or errorcode otherwise.
318  */
pcmcia_loop_tuple(struct pcmcia_device * p_dev,cisdata_t code,int (* loop_tuple)(struct pcmcia_device * p_dev,tuple_t * tuple,void * priv_data),void * priv_data)319 int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code,
320 		      int (*loop_tuple) (struct pcmcia_device *p_dev,
321 					 tuple_t *tuple,
322 					 void *priv_data),
323 		      void *priv_data)
324 {
325 	struct pcmcia_loop_mem loop = {
326 		.p_dev = p_dev,
327 		.loop_tuple = loop_tuple,
328 		.priv_data = priv_data};
329 
330 	return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL,
331 				 &loop, pcmcia_do_loop_tuple);
332 }
333 EXPORT_SYMBOL(pcmcia_loop_tuple);
334 
335 
336 struct pcmcia_loop_get {
337 	size_t len;
338 	cisdata_t **buf;
339 };
340 
341 /*
342  * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple()
343  *
344  * pcmcia_do_get_tuple() is the internal callback for the call from
345  * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in
346  * the first tuple, return 0 unconditionally. Create a memory buffer large
347  * enough to hold the content of the tuple, and fill it with the tuple data.
348  * The caller is responsible to free the buffer.
349  */
pcmcia_do_get_tuple(struct pcmcia_device * p_dev,tuple_t * tuple,void * priv)350 static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple,
351 			       void *priv)
352 {
353 	struct pcmcia_loop_get *get = priv;
354 
355 	*get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL);
356 	if (*get->buf) {
357 		get->len = tuple->TupleDataLen;
358 		memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen);
359 	} else
360 		dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n");
361 	return 0;
362 }
363 
364 /**
365  * pcmcia_get_tuple() - get first tuple from CIS
366  * @p_dev:	the struct pcmcia_device which we need to loop for.
367  * @code:	which CIS code shall we look for?
368  * @buf:        pointer to store the buffer to.
369  *
370  * pcmcia_get_tuple() gets the content of the first CIS entry of type @code.
371  * It returns the buffer length (or zero). The caller is responsible to free
372  * the buffer passed in @buf.
373  */
pcmcia_get_tuple(struct pcmcia_device * p_dev,cisdata_t code,unsigned char ** buf)374 size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code,
375 			unsigned char **buf)
376 {
377 	struct pcmcia_loop_get get = {
378 		.len = 0,
379 		.buf = buf,
380 	};
381 
382 	*get.buf = NULL;
383 	pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get);
384 
385 	return get.len;
386 }
387 EXPORT_SYMBOL(pcmcia_get_tuple);
388 
389 #ifdef CONFIG_NET
390 /*
391  * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis()
392  *
393  * pcmcia_do_get_mac() is the internal callback for the call from
394  * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the
395  * tuple contains a proper LAN_NODE_ID of length 6, and copy the data
396  * to struct net_device->dev_addr[i].
397  */
pcmcia_do_get_mac(struct pcmcia_device * p_dev,tuple_t * tuple,void * priv)398 static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple,
399 			     void *priv)
400 {
401 	struct net_device *dev = priv;
402 
403 	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
404 		return -EINVAL;
405 	if (tuple->TupleDataLen < ETH_ALEN + 2) {
406 		dev_warn(&p_dev->dev, "Invalid CIS tuple length for "
407 			"LAN_NODE_ID\n");
408 		return -EINVAL;
409 	}
410 
411 	if (tuple->TupleData[1] != ETH_ALEN) {
412 		dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n");
413 		return -EINVAL;
414 	}
415 	eth_hw_addr_set(dev, &tuple->TupleData[2]);
416 	return 0;
417 }
418 
419 /**
420  * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE
421  * @p_dev:	the struct pcmcia_device for which we want the address.
422  * @dev:	a properly prepared struct net_device to store the info to.
423  *
424  * pcmcia_get_mac_from_cis() reads out the hardware MAC address from
425  * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which
426  * must be set up properly by the driver (see examples!).
427  */
pcmcia_get_mac_from_cis(struct pcmcia_device * p_dev,struct net_device * dev)428 int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev)
429 {
430 	return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev);
431 }
432 EXPORT_SYMBOL(pcmcia_get_mac_from_cis);
433 
434 #endif /* CONFIG_NET */
435