Merge branch 'fix/misc' into for-linus
[linux-2.6] / drivers / pci / hotplug / cpqphp_nvram.c
1 /*
2  * Compaq Hot Plug Controller Driver
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001 IBM Corp.
7  *
8  * All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18  * NON INFRINGEMENT.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * Send feedback to <greg@kroah.com>
26  *
27  */
28
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/types.h>
32 #include <linux/proc_fs.h>
33 #include <linux/slab.h>
34 #include <linux/workqueue.h>
35 #include <linux/pci.h>
36 #include <linux/pci_hotplug.h>
37 #include <linux/init.h>
38 #include <asm/uaccess.h>
39 #include "cpqphp.h"
40 #include "cpqphp_nvram.h"
41
42
43 #define ROM_INT15_PHY_ADDR              0x0FF859
44 #define READ_EV                         0xD8A4
45 #define WRITE_EV                        0xD8A5
46
47 struct register_foo {
48         union {
49                 unsigned long lword;            /* eax */
50                 unsigned short word;            /* ax */
51
52                 struct {
53                         unsigned char low;      /* al */
54                         unsigned char high;     /* ah */
55                 } byte;
56         } data;
57
58         unsigned char opcode;   /* see below */
59         unsigned long length;   /* if the reg. is a pointer, how much data */
60 } __attribute__ ((packed));
61
62 struct all_reg {
63         struct register_foo eax_reg;
64         struct register_foo ebx_reg;
65         struct register_foo ecx_reg;
66         struct register_foo edx_reg;
67         struct register_foo edi_reg;
68         struct register_foo esi_reg;
69         struct register_foo eflags_reg;
70 } __attribute__ ((packed));
71
72
73 struct ev_hrt_header {
74         u8 Version;
75         u8 num_of_ctrl;
76         u8 next;
77 };
78
79 struct ev_hrt_ctrl {
80         u8 bus;
81         u8 device;
82         u8 function;
83         u8 mem_avail;
84         u8 p_mem_avail;
85         u8 io_avail;
86         u8 bus_avail;
87         u8 next;
88 };
89
90
91 static u8 evbuffer_init;
92 static u8 evbuffer_length;
93 static u8 evbuffer[1024];
94
95 static void __iomem *compaq_int15_entry_point;
96
97 /* lock for ordering int15_bios_call() */
98 static spinlock_t int15_lock;
99
100
101 /* This is a series of function that deals with
102  * setting & getting the hotplug resource table in some environment variable.
103  */
104
105 /*
106  * We really shouldn't be doing this unless there is a _very_ good reason to!!!
107  * greg k-h
108  */
109
110
111 static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
112 {
113         u8 **tByte;
114
115         if ((*used + 1) > *avail)
116                 return(1);
117
118         *((u8*)*p_buffer) = value;
119         tByte = (u8**)p_buffer;
120         (*tByte)++;
121         *used+=1;
122         return(0);
123 }
124
125
126 static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail)
127 {
128         if ((*used + 4) > *avail)
129                 return(1);
130
131         **p_buffer = value;
132         (*p_buffer)++;
133         *used+=4;
134         return(0);
135 }
136
137
138 /*
139  * check_for_compaq_ROM
140  *
141  * this routine verifies that the ROM OEM string is 'COMPAQ'
142  *
143  * returns 0 for non-Compaq ROM, 1 for Compaq ROM
144  */
145 static int check_for_compaq_ROM (void __iomem *rom_start)
146 {
147         u8 temp1, temp2, temp3, temp4, temp5, temp6;
148         int result = 0;
149
150         temp1 = readb(rom_start + 0xffea + 0);
151         temp2 = readb(rom_start + 0xffea + 1);
152         temp3 = readb(rom_start + 0xffea + 2);
153         temp4 = readb(rom_start + 0xffea + 3);
154         temp5 = readb(rom_start + 0xffea + 4);
155         temp6 = readb(rom_start + 0xffea + 5);
156         if ((temp1 == 'C') &&
157             (temp2 == 'O') &&
158             (temp3 == 'M') &&
159             (temp4 == 'P') &&
160             (temp5 == 'A') &&
161             (temp6 == 'Q')) {
162                 result = 1;
163         }
164         dbg ("%s - returned %d\n", __func__, result);
165         return result;
166 }
167
168
169 static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
170 {
171         unsigned long flags;
172         int op = operation;
173         int ret_val;
174
175         if (!compaq_int15_entry_point)
176                 return -ENODEV;
177
178         spin_lock_irqsave(&int15_lock, flags);
179         __asm__ (
180                 "xorl   %%ebx,%%ebx\n" \
181                 "xorl    %%edx,%%edx\n" \
182                 "pushf\n" \
183                 "push %%cs\n" \
184                 "cli\n" \
185                 "call *%6\n"
186                 : "=c" (*buf_size), "=a" (ret_val)
187                 : "a" (op), "c" (*buf_size), "S" (ev_name),
188                 "D" (buffer), "m" (compaq_int15_entry_point)
189                 : "%ebx", "%edx");
190         spin_unlock_irqrestore(&int15_lock, flags);
191
192         return((ret_val & 0xFF00) >> 8);
193 }
194
195
196 /*
197  * load_HRT
198  *
199  * Read the hot plug Resource Table from NVRAM
200  */
201 static int load_HRT (void __iomem *rom_start)
202 {
203         u32 available;
204         u32 temp_dword;
205         u8 temp_byte = 0xFF;
206         u32 rc;
207
208         if (!check_for_compaq_ROM(rom_start)) {
209                 return -ENODEV;
210         }
211
212         available = 1024;
213
214         /* Now load the EV */
215         temp_dword = available;
216
217         rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
218
219         evbuffer_length = temp_dword;
220
221         /* We're maintaining the resource lists so write FF to invalidate old
222          * info
223          */
224         temp_dword = 1;
225
226         rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
227
228         return rc;
229 }
230
231
232 /*
233  * store_HRT
234  *
235  * Save the hot plug Resource Table in NVRAM
236  */
237 static u32 store_HRT (void __iomem *rom_start)
238 {
239         u32 *buffer;
240         u32 *pFill;
241         u32 usedbytes;
242         u32 available;
243         u32 temp_dword;
244         u32 rc;
245         u8 loop;
246         u8 numCtrl = 0;
247         struct controller *ctrl;
248         struct pci_resource *resNode;
249         struct ev_hrt_header *p_EV_header;
250         struct ev_hrt_ctrl *p_ev_ctrl;
251
252         available = 1024;
253
254         if (!check_for_compaq_ROM(rom_start)) {
255                 return(1);
256         }
257
258         buffer = (u32*) evbuffer;
259
260         if (!buffer)
261                 return(1);
262
263         pFill = buffer;
264         usedbytes = 0;
265
266         p_EV_header = (struct ev_hrt_header *) pFill;
267
268         ctrl = cpqhp_ctrl_list;
269
270         /* The revision of this structure */
271         rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
272         if (rc)
273                 return(rc);
274
275         /* The number of controllers */
276         rc = add_byte( &pFill, 1, &usedbytes, &available);
277         if (rc)
278                 return(rc);
279
280         while (ctrl) {
281                 p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
282
283                 numCtrl++;
284
285                 /* The bus number */
286                 rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
287                 if (rc)
288                         return(rc);
289
290                 /* The device Number */
291                 rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
292                 if (rc)
293                         return(rc);
294
295                 /* The function Number */
296                 rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
297                 if (rc)
298                         return(rc);
299
300                 /* Skip the number of available entries */
301                 rc = add_dword( &pFill, 0, &usedbytes, &available);
302                 if (rc)
303                         return(rc);
304
305                 /* Figure out memory Available */
306
307                 resNode = ctrl->mem_head;
308
309                 loop = 0;
310
311                 while (resNode) {
312                         loop ++;
313
314                         /* base */
315                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
316                         if (rc)
317                                 return(rc);
318
319                         /* length */
320                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
321                         if (rc)
322                                 return(rc);
323
324                         resNode = resNode->next;
325                 }
326
327                 /* Fill in the number of entries */
328                 p_ev_ctrl->mem_avail = loop;
329
330                 /* Figure out prefetchable memory Available */
331
332                 resNode = ctrl->p_mem_head;
333
334                 loop = 0;
335
336                 while (resNode) {
337                         loop ++;
338
339                         /* base */
340                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
341                         if (rc)
342                                 return(rc);
343
344                         /* length */
345                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
346                         if (rc)
347                                 return(rc);
348
349                         resNode = resNode->next;
350                 }
351
352                 /* Fill in the number of entries */
353                 p_ev_ctrl->p_mem_avail = loop;
354
355                 /* Figure out IO Available */
356
357                 resNode = ctrl->io_head;
358
359                 loop = 0;
360
361                 while (resNode) {
362                         loop ++;
363
364                         /* base */
365                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
366                         if (rc)
367                                 return(rc);
368
369                         /* length */
370                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
371                         if (rc)
372                                 return(rc);
373
374                         resNode = resNode->next;
375                 }
376
377                 /* Fill in the number of entries */
378                 p_ev_ctrl->io_avail = loop;
379
380                 /* Figure out bus Available */
381
382                 resNode = ctrl->bus_head;
383
384                 loop = 0;
385
386                 while (resNode) {
387                         loop ++;
388
389                         /* base */
390                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
391                         if (rc)
392                                 return(rc);
393
394                         /* length */
395                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
396                         if (rc)
397                                 return(rc);
398
399                         resNode = resNode->next;
400                 }
401
402                 /* Fill in the number of entries */
403                 p_ev_ctrl->bus_avail = loop;
404
405                 ctrl = ctrl->next;
406         }
407
408         p_EV_header->num_of_ctrl = numCtrl;
409
410         /* Now store the EV */
411
412         temp_dword = usedbytes;
413
414         rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
415
416         dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
417
418         evbuffer_length = temp_dword;
419
420         if (rc) {
421                 err(msg_unable_to_save);
422                 return(1);
423         }
424
425         return(0);
426 }
427
428
429 void compaq_nvram_init (void __iomem *rom_start)
430 {
431         if (rom_start) {
432                 compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
433         }
434         dbg("int15 entry  = %p\n", compaq_int15_entry_point);
435
436         /* initialize our int15 lock */
437         spin_lock_init(&int15_lock);
438 }
439
440
441 int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
442 {
443         u8 bus, device, function;
444         u8 nummem, numpmem, numio, numbus;
445         u32 rc;
446         u8 *p_byte;
447         struct pci_resource *mem_node;
448         struct pci_resource *p_mem_node;
449         struct pci_resource *io_node;
450         struct pci_resource *bus_node;
451         struct ev_hrt_ctrl *p_ev_ctrl;
452         struct ev_hrt_header *p_EV_header;
453
454         if (!evbuffer_init) {
455                 /* Read the resource list information in from NVRAM */
456                 if (load_HRT(rom_start))
457                         memset (evbuffer, 0, 1024);
458
459                 evbuffer_init = 1;
460         }
461
462         /* If we saved information in NVRAM, use it now */
463         p_EV_header = (struct ev_hrt_header *) evbuffer;
464
465         /* The following code is for systems where version 1.0 of this
466          * driver has been loaded, but doesn't support the hardware.
467          * In that case, the driver would incorrectly store something
468          * in NVRAM.
469          */
470         if ((p_EV_header->Version == 2) ||
471             ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
472                 p_byte = &(p_EV_header->next);
473
474                 p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
475
476                 p_byte += 3;
477
478                 if (p_byte > ((u8*)p_EV_header + evbuffer_length))
479                         return 2;
480
481                 bus = p_ev_ctrl->bus;
482                 device = p_ev_ctrl->device;
483                 function = p_ev_ctrl->function;
484
485                 while ((bus != ctrl->bus) ||
486                        (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
487                        (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
488                         nummem = p_ev_ctrl->mem_avail;
489                         numpmem = p_ev_ctrl->p_mem_avail;
490                         numio = p_ev_ctrl->io_avail;
491                         numbus = p_ev_ctrl->bus_avail;
492
493                         p_byte += 4;
494
495                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
496                                 return 2;
497
498                         /* Skip forward to the next entry */
499                         p_byte += (nummem + numpmem + numio + numbus) * 8;
500
501                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
502                                 return 2;
503
504                         p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
505
506                         p_byte += 3;
507
508                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
509                                 return 2;
510
511                         bus = p_ev_ctrl->bus;
512                         device = p_ev_ctrl->device;
513                         function = p_ev_ctrl->function;
514                 }
515
516                 nummem = p_ev_ctrl->mem_avail;
517                 numpmem = p_ev_ctrl->p_mem_avail;
518                 numio = p_ev_ctrl->io_avail;
519                 numbus = p_ev_ctrl->bus_avail;
520
521                 p_byte += 4;
522
523                 if (p_byte > ((u8*)p_EV_header + evbuffer_length))
524                         return 2;
525
526                 while (nummem--) {
527                         mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
528
529                         if (!mem_node)
530                                 break;
531
532                         mem_node->base = *(u32*)p_byte;
533                         dbg("mem base = %8.8x\n",mem_node->base);
534                         p_byte += 4;
535
536                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
537                                 kfree(mem_node);
538                                 return 2;
539                         }
540
541                         mem_node->length = *(u32*)p_byte;
542                         dbg("mem length = %8.8x\n",mem_node->length);
543                         p_byte += 4;
544
545                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
546                                 kfree(mem_node);
547                                 return 2;
548                         }
549
550                         mem_node->next = ctrl->mem_head;
551                         ctrl->mem_head = mem_node;
552                 }
553
554                 while (numpmem--) {
555                         p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
556
557                         if (!p_mem_node)
558                                 break;
559
560                         p_mem_node->base = *(u32*)p_byte;
561                         dbg("pre-mem base = %8.8x\n",p_mem_node->base);
562                         p_byte += 4;
563
564                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
565                                 kfree(p_mem_node);
566                                 return 2;
567                         }
568
569                         p_mem_node->length = *(u32*)p_byte;
570                         dbg("pre-mem length = %8.8x\n",p_mem_node->length);
571                         p_byte += 4;
572
573                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
574                                 kfree(p_mem_node);
575                                 return 2;
576                         }
577
578                         p_mem_node->next = ctrl->p_mem_head;
579                         ctrl->p_mem_head = p_mem_node;
580                 }
581
582                 while (numio--) {
583                         io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
584
585                         if (!io_node)
586                                 break;
587
588                         io_node->base = *(u32*)p_byte;
589                         dbg("io base = %8.8x\n",io_node->base);
590                         p_byte += 4;
591
592                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
593                                 kfree(io_node);
594                                 return 2;
595                         }
596
597                         io_node->length = *(u32*)p_byte;
598                         dbg("io length = %8.8x\n",io_node->length);
599                         p_byte += 4;
600
601                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
602                                 kfree(io_node);
603                                 return 2;
604                         }
605
606                         io_node->next = ctrl->io_head;
607                         ctrl->io_head = io_node;
608                 }
609
610                 while (numbus--) {
611                         bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
612
613                         if (!bus_node)
614                                 break;
615
616                         bus_node->base = *(u32*)p_byte;
617                         p_byte += 4;
618
619                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
620                                 kfree(bus_node);
621                                 return 2;
622                         }
623
624                         bus_node->length = *(u32*)p_byte;
625                         p_byte += 4;
626
627                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
628                                 kfree(bus_node);
629                                 return 2;
630                         }
631
632                         bus_node->next = ctrl->bus_head;
633                         ctrl->bus_head = bus_node;
634                 }
635
636                 /* If all of the following fail, we don't have any resources for
637                  * hot plug add
638                  */
639                 rc = 1;
640                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
641                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
642                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
643                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
644
645                 if (rc)
646                         return(rc);
647         } else {
648                 if ((evbuffer[0] != 0) && (!ctrl->push_flag))
649                         return 1;
650         }
651
652         return 0;
653 }
654
655
656 int compaq_nvram_store (void __iomem *rom_start)
657 {
658         int rc = 1;
659
660         if (rom_start == NULL)
661                 return -ENODEV;
662
663         if (evbuffer_init) {
664                 rc = store_HRT(rom_start);
665                 if (rc) {
666                         err(msg_unable_to_save);
667                 }
668         }
669         return rc;
670 }
671