• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * eisa_enumerator.c - provide support for EISA adapters in PA-RISC machines
4  *
5  * Copyright (c) 2002 Daniel Engstrom <5116@telia.com>
6  */
7 
8 #include <linux/ioport.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <asm/io.h>
13 #include <linux/uaccess.h>
14 #include <asm/byteorder.h>
15 
16 #include <asm/eisa_bus.h>
17 #include <asm/eisa_eeprom.h>
18 
19 
20 /*
21  * Todo:
22  *
23  * PORT init with MASK attr and other size than byte
24  * MEMORY with other decode than 20 bit
25  * CRC stuff
26  * FREEFORM stuff
27  */
28 
29 #define EPI 0xc80
30 #define NUM_SLOT 16
31 #define SLOT2PORT(x) (x<<12)
32 
33 
34 /* macros to handle unaligned accesses and
35  * byte swapping. The data in the EEPROM is
36  * little-endian on the big-endian PAROSC */
37 #define get_8(x) (*(u_int8_t*)(x))
38 
get_16(const unsigned char * x)39 static inline u_int16_t get_16(const unsigned char *x)
40 {
41 	return (x[1] << 8) | x[0];
42 }
43 
get_32(const unsigned char * x)44 static inline u_int32_t get_32(const unsigned char *x)
45 {
46 	return (x[3] << 24) | (x[2] << 16) | (x[1] << 8) | x[0];
47 }
48 
get_24(const unsigned char * x)49 static inline u_int32_t get_24(const unsigned char *x)
50 {
51 	return (x[2] << 24) | (x[1] << 16) | (x[0] << 8);
52 }
53 
print_eisa_id(char * s,u_int32_t id)54 static void print_eisa_id(char *s, u_int32_t id)
55 {
56 	char vendor[4];
57 	int rev;
58 	int device;
59 
60 	rev = id & 0xff;
61 	id >>= 8;
62 	device = id & 0xff;
63 	id >>= 8;
64 	vendor[3] = '\0';
65 	vendor[2] = '@' + (id & 0x1f);
66 	id >>= 5;
67 	vendor[1] = '@' + (id & 0x1f);
68 	id >>= 5;
69 	vendor[0] = '@' + (id & 0x1f);
70 	id >>= 5;
71 
72 	sprintf(s, "%s%02X%02X", vendor, device, rev);
73 }
74 
configure_memory(const unsigned char * buf,struct resource * mem_parent,char * name)75 static int configure_memory(const unsigned char *buf,
76 		       struct resource *mem_parent,
77 		       char *name)
78 {
79 	int len;
80 	u_int8_t c;
81 	int i;
82 	struct resource *res;
83 
84 	len=0;
85 
86 	for (i=0;i<HPEE_MEMORY_MAX_ENT;i++) {
87 		c = get_8(buf+len);
88 
89 		if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) {
90 			int result;
91 
92 			res->name = name;
93 			res->start = mem_parent->start + get_24(buf+len+2);
94 			res->end = res->start + get_16(buf+len+5)*1024;
95 			res->flags = IORESOURCE_MEM;
96 			pr_cont("memory %pR ", res);
97 			result = request_resource(mem_parent, res);
98 			if (result < 0) {
99 				printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
100 				return result;
101 			}
102 		}
103 
104 		len+=7;
105 
106 		if (!(c & HPEE_MEMORY_MORE)) {
107 			break;
108 		}
109 	}
110 
111 	return len;
112 }
113 
114 
configure_irq(const unsigned char * buf)115 static int configure_irq(const unsigned char *buf)
116 {
117 	int len;
118 	u_int8_t c;
119 	int i;
120 
121 	len=0;
122 
123 	for (i=0;i<HPEE_IRQ_MAX_ENT;i++) {
124 		c = get_8(buf+len);
125 
126 		pr_cont("IRQ %d ", c & HPEE_IRQ_CHANNEL_MASK);
127 		if (c & HPEE_IRQ_TRIG_LEVEL) {
128 			eisa_make_irq_level(c & HPEE_IRQ_CHANNEL_MASK);
129 		} else {
130 			eisa_make_irq_edge(c & HPEE_IRQ_CHANNEL_MASK);
131 		}
132 
133 		len+=2;
134 		/* hpux seems to allow for
135 		 * two bytes of irq data but only defines one of
136 		 * them, I think */
137 		if  (!(c & HPEE_IRQ_MORE)) {
138 			break;
139 		}
140 	}
141 
142 	return len;
143 }
144 
145 
configure_dma(const unsigned char * buf)146 static int configure_dma(const unsigned char *buf)
147 {
148 	int len;
149 	u_int8_t c;
150 	int i;
151 
152 	len=0;
153 
154 	for (i=0;i<HPEE_DMA_MAX_ENT;i++) {
155 		c = get_8(buf+len);
156 		pr_cont("DMA %d ", c&HPEE_DMA_CHANNEL_MASK);
157 		/* fixme: maybe initialize the dma channel withthe timing ? */
158 		len+=2;
159 		if (!(c & HPEE_DMA_MORE)) {
160 			break;
161 		}
162 	}
163 
164 	return len;
165 }
166 
configure_port(const unsigned char * buf,struct resource * io_parent,char * board)167 static int configure_port(const unsigned char *buf, struct resource *io_parent,
168 		     char *board)
169 {
170 	int len;
171 	u_int8_t c;
172 	int i;
173 	struct resource *res;
174 	int result;
175 
176 	len=0;
177 
178 	for (i=0;i<HPEE_PORT_MAX_ENT;i++) {
179 		c = get_8(buf+len);
180 
181 		if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) {
182 			res->name = board;
183 			res->start = get_16(buf+len+1);
184 			res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1;
185 			res->flags = IORESOURCE_IO;
186 			pr_cont("ioports %pR ", res);
187 			result = request_resource(io_parent, res);
188 			if (result < 0) {
189 				printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
190 				return result;
191 			}
192 		}
193 
194 		len+=3;
195 		if (!(c & HPEE_PORT_MORE)) {
196 			break;
197 		}
198 	}
199 
200 	return len;
201 }
202 
203 
204 /* byte 1 and 2 is the port number to write
205  * and at byte 3 the value to write starts.
206  * I assume that there are and- and or- masks
207  * here when HPEE_PORT_INIT_MASK is set but I have
208  * not yet encountered this. */
configure_port_init(const unsigned char * buf)209 static int configure_port_init(const unsigned char *buf)
210 {
211 	int len=0;
212 	u_int8_t c;
213 
214 	while (len<HPEE_PORT_INIT_MAX_LEN) {
215 		int s=0;
216 		c = get_8(buf+len);
217 
218 		switch (c & HPEE_PORT_INIT_WIDTH_MASK)  {
219 		 case HPEE_PORT_INIT_WIDTH_BYTE:
220 			s=1;
221 			if (c & HPEE_PORT_INIT_MASK) {
222 				printk(KERN_WARNING "port_init: unverified mask attribute\n");
223 				outb((inb(get_16(buf+len+1) &
224 					  get_8(buf+len+3)) |
225 				      get_8(buf+len+4)), get_16(buf+len+1));
226 
227 			} else {
228 				outb(get_8(buf+len+3), get_16(buf+len+1));
229 
230 			}
231 			break;
232 		 case HPEE_PORT_INIT_WIDTH_WORD:
233 			s=2;
234 			if (c & HPEE_PORT_INIT_MASK) {
235  				printk(KERN_WARNING "port_init: unverified mask attribute\n");
236 				       outw((inw(get_16(buf+len+1)) &
237 					     get_16(buf+len+3)) |
238 					    get_16(buf+len+5),
239 					    get_16(buf+len+1));
240 			} else {
241 				outw(cpu_to_le16(get_16(buf+len+3)), get_16(buf+len+1));
242 			}
243 			break;
244 		 case HPEE_PORT_INIT_WIDTH_DWORD:
245 			s=4;
246 			if (c & HPEE_PORT_INIT_MASK) {
247  				printk(KERN_WARNING "port_init: unverified mask attribute\n");
248 				outl((inl(get_16(buf+len+1) &
249 					  get_32(buf+len+3)) |
250 				      get_32(buf+len+7)), get_16(buf+len+1));
251 			} else {
252 				outl(cpu_to_le32(get_32(buf+len+3)), get_16(buf+len+1));
253 			}
254 
255 			break;
256 		 default:
257 			printk(KERN_ERR "Invalid port init word %02x\n", c);
258 			return 0;
259 		}
260 
261 		if (c & HPEE_PORT_INIT_MASK) {
262 			s*=2;
263 		}
264 
265 		len+=s+3;
266 		if (!(c & HPEE_PORT_INIT_MORE)) {
267 			break;
268 		}
269 	}
270 
271 	return len;
272 }
273 
configure_choise(const unsigned char * buf,u_int8_t * info)274 static int configure_choise(const unsigned char *buf, u_int8_t *info)
275 {
276 	int len;
277 
278 	/* theis record contain the value of the functions
279 	 * configuration choises and an info byte which
280 	 * describes which other records to expect in this
281 	 * function */
282 	len = get_8(buf);
283 	*info=get_8(buf+len+1);
284 
285 	return len+2;
286 }
287 
configure_type_string(const unsigned char * buf)288 static int configure_type_string(const unsigned char *buf)
289 {
290 	int len;
291 
292 	/* just skip past the type field */
293 	len = get_8(buf);
294 	if (len > 80) {
295 		printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len);
296 	}
297 
298 	return 1+len;
299 }
300 
configure_function(const unsigned char * buf,int * more)301 static int configure_function(const unsigned char *buf, int *more)
302 {
303 	/* the init field seems to be a two-byte field
304 	 * which is non-zero if there are an other function following
305 	 * I think it is the length of the function def
306 	 */
307 	*more = get_16(buf);
308 
309 	return 2;
310 }
311 
parse_slot_config(int slot,const unsigned char * buf,struct eeprom_eisa_slot_info * es,struct resource * io_parent,struct resource * mem_parent)312 static int parse_slot_config(int slot,
313 			     const unsigned char *buf,
314 			     struct eeprom_eisa_slot_info *es,
315 			     struct resource *io_parent,
316 			     struct resource *mem_parent)
317 {
318 	int res=0;
319 	int function_len;
320 	unsigned int pos=0;
321 	unsigned int maxlen;
322 	int num_func=0;
323 	u_int8_t flags;
324 	int p0;
325 
326 	char *board;
327 	int id_string_used=0;
328 
329 	if (NULL == (board = kmalloc(8, GFP_KERNEL))) {
330 		return -1;
331 	}
332 	print_eisa_id(board, es->eisa_slot_id);
333 	printk(KERN_INFO "EISA slot %d: %s %s ",
334 	       slot, board, es->flags&HPEE_FLAG_BOARD_IS_ISA ? "ISA" : "EISA");
335 
336 	maxlen = es->config_data_length < HPEE_MAX_LENGTH ?
337 			 es->config_data_length : HPEE_MAX_LENGTH;
338 	while ((pos < maxlen) && (num_func <= es->num_functions)) {
339 		pos+=configure_function(buf+pos, &function_len);
340 
341 		if (!function_len) {
342 			break;
343 		}
344 		num_func++;
345 		p0 = pos;
346 		pos += configure_choise(buf+pos, &flags);
347 
348 		if (flags & HPEE_FUNCTION_INFO_F_DISABLED) {
349 			/* function disabled, skip silently */
350 			pos = p0 + function_len;
351 			continue;
352 		}
353 		if (flags & HPEE_FUNCTION_INFO_CFG_FREE_FORM) {
354 			/* I have no idea how to handle this */
355 			printk("function %d have free-form configuration, skipping ",
356 				num_func);
357 			pos = p0 + function_len;
358 			continue;
359 		}
360 
361 		/* the ordering of the sections need
362 		 * more investigation.
363 		 * Currently I think that memory comaed before IRQ
364 		 * I assume the order is LSB to MSB in the
365 		 * info flags
366 		 * eg type, memory, irq, dma, port, HPEE_PORT_init
367 		 */
368 
369 		if (flags & HPEE_FUNCTION_INFO_HAVE_TYPE) {
370 			pos += configure_type_string(buf+pos);
371 		}
372 
373 		if (flags & HPEE_FUNCTION_INFO_HAVE_MEMORY) {
374 			id_string_used=1;
375 			pos += configure_memory(buf+pos, mem_parent, board);
376 		}
377 
378 		if (flags & HPEE_FUNCTION_INFO_HAVE_IRQ) {
379 			pos += configure_irq(buf+pos);
380 		}
381 
382 		if (flags & HPEE_FUNCTION_INFO_HAVE_DMA) {
383 			pos += configure_dma(buf+pos);
384 		}
385 
386 		if (flags & HPEE_FUNCTION_INFO_HAVE_PORT) {
387 			id_string_used=1;
388 			pos += configure_port(buf+pos, io_parent, board);
389 		}
390 
391 		if (flags &  HPEE_FUNCTION_INFO_HAVE_PORT_INIT) {
392 			pos += configure_port_init(buf+pos);
393 		}
394 
395 		if (p0 + function_len < pos) {
396 			printk(KERN_ERR "eisa_enumerator: function %d length mis-match "
397 			       "got %d, expected %d\n",
398 			       num_func, pos-p0, function_len);
399 			res=-1;
400 			break;
401 		}
402 		pos = p0 + function_len;
403 	}
404 	pr_cont("\n");
405 	if (!id_string_used) {
406 		kfree(board);
407 	}
408 
409 	if (pos != es->config_data_length) {
410 		printk(KERN_ERR "eisa_enumerator: config data length mis-match got %d, expected %d\n",
411 			pos, es->config_data_length);
412 		res=-1;
413 	}
414 
415 	if (num_func != es->num_functions) {
416 		printk(KERN_ERR "eisa_enumerator: number of functions mis-match got %d, expected %d\n",
417 			num_func, es->num_functions);
418 		res=-2;
419 	}
420 
421 	return res;
422 
423 }
424 
init_slot(int slot,struct eeprom_eisa_slot_info * es)425 static int init_slot(int slot, struct eeprom_eisa_slot_info *es)
426 {
427 	unsigned int id;
428 
429 	char id_string[8];
430 
431 	if (!(es->slot_info&HPEE_SLOT_INFO_NO_READID)) {
432 		/* try to read the id of the board in the slot */
433 		id = le32_to_cpu(inl(SLOT2PORT(slot)+EPI));
434 
435 		if (0xffffffff == id) {
436 			/* Maybe we didn't expect a card to be here... */
437 			if (es->eisa_slot_id == 0xffffffff)
438 				return -1;
439 
440 			/* this board is not here or it does not
441 			 * support readid
442 			 */
443 			printk(KERN_ERR "EISA slot %d a configured board was not detected (",
444 			       slot);
445 
446 			print_eisa_id(id_string, es->eisa_slot_id);
447 			printk(" expected %s)\n", id_string);
448 
449 			return -1;
450 
451 		}
452 		if (es->eisa_slot_id != id) {
453 			print_eisa_id(id_string, id);
454 			printk(KERN_ERR "EISA slot %d id mis-match: got %s",
455 			       slot, id_string);
456 
457 			print_eisa_id(id_string, es->eisa_slot_id);
458 			printk(" expected %s\n", id_string);
459 
460 			return -1;
461 
462 		}
463 	}
464 
465 	/* now: we need to enable the board if
466 	 * it supports enabling and run through
467 	 * the port init sction if present
468 	 * and finally record any interrupt polarity
469 	 */
470 	if (es->slot_features & HPEE_SLOT_FEATURES_ENABLE) {
471 		/* enable board */
472 		outb(0x01| inb(SLOT2PORT(slot)+EPI+4),
473 		     SLOT2PORT(slot)+EPI+4);
474 	}
475 
476 	return 0;
477 }
478 
479 
eisa_enumerator(unsigned long eeprom_addr,struct resource * io_parent,struct resource * mem_parent)480 int eisa_enumerator(unsigned long eeprom_addr,
481 		    struct resource *io_parent, struct resource *mem_parent)
482 {
483 	int i;
484 	struct eeprom_header *eh;
485 	static char eeprom_buf[HPEE_MAX_LENGTH];
486 
487 	for (i=0; i < HPEE_MAX_LENGTH; i++) {
488 		eeprom_buf[i] = gsc_readb(eeprom_addr+i);
489 	}
490 
491 	printk(KERN_INFO "Enumerating EISA bus\n");
492 
493 	eh = (struct eeprom_header*)(eeprom_buf);
494 	for (i=0;i<eh->num_slots;i++) {
495 		struct eeprom_eisa_slot_info *es;
496 
497 		es = (struct eeprom_eisa_slot_info*)
498 			(&eeprom_buf[HPEE_SLOT_INFO(i)]);
499 
500 		if (-1==init_slot(i+1, es)) {
501 			continue;
502 		}
503 
504 		if (es->config_data_offset < HPEE_MAX_LENGTH) {
505 			if (parse_slot_config(i+1, &eeprom_buf[es->config_data_offset],
506 					      es, io_parent, mem_parent)) {
507 				return -1;
508 			}
509 		} else {
510 			printk (KERN_WARNING "EISA EEPROM offset 0x%x out of range\n",es->config_data_offset);
511 			return -1;
512 		}
513 	}
514 	return eh->num_slots;
515 }
516 
517