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