]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/parisc/eisa_enumerator.c
parisc: convert the rest of the irq handlers to simple/percpu
[linux-2.6.git] / drivers / parisc / eisa_enumerator.c
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 <5116@telia.com>
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) {
133                         eisa_make_irq_level(c & HPEE_IRQ_CHANNEL_MASK);
134                 } else {
135                         eisa_make_irq_edge(c & HPEE_IRQ_CHANNEL_MASK);
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)  {
224                  case HPEE_PORT_INIT_WIDTH_BYTE:
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;
237                  case HPEE_PORT_INIT_WIDTH_WORD:
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;
249                  case HPEE_PORT_INIT_WIDTH_DWORD:
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 ?
342                          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          */
475         if (es->slot_features & HPEE_SLOT_FEATURES_ENABLE) {
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