brute-forced more changes from MontaVista's tree. SCSI partition table read still...
[linux-2.4.git] / drivers / 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/config.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/types.h>
33 #include <linux/proc_fs.h>
34 #include <linux/miscdevice.h>
35 #include <linux/slab.h>
36 #include <linux/pci.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 *compaq_int15_entry_point;
96
97 static spinlock_t int15_lock;           /* lock for ordering int15_bios_call() */
98
99
100 /* This is a series of function that deals with
101    setting & getting the hotplug resource table in some environment variable.
102 */
103
104 /*
105  * We really shouldn't be doing this unless there is a _very_ good reason to!!!
106  * greg k-h
107  */
108
109
110 static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)
111 {
112         u8 **tByte;
113
114         if ((*used + 1) > *avail)
115                 return(1);
116         
117         *((u8*)*p_buffer) = value;
118         tByte = (u8**)p_buffer;
119         (*tByte)++;
120         *used+=1;
121         return(0);
122 }
123
124
125 static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail)
126 {
127         if ((*used + 4) > *avail)
128                 return(1);
129
130         **p_buffer = value;
131         (*p_buffer)++;
132         *used+=4;
133         return(0);
134 }
135
136
137 /*
138  * check_for_compaq_ROM
139  *
140  * this routine verifies that the ROM OEM string is 'COMPAQ'
141  *
142  * returns 0 for non-Compaq ROM, 1 for Compaq ROM
143  */
144 static int check_for_compaq_ROM (void *rom_start)
145 {
146         u8 temp1, temp2, temp3, temp4, temp5, temp6;
147         int result = 0;
148
149         temp1 = readb(rom_start + 0xffea + 0);
150         temp2 = readb(rom_start + 0xffea + 1);
151         temp3 = readb(rom_start + 0xffea + 2);
152         temp4 = readb(rom_start + 0xffea + 3);
153         temp5 = readb(rom_start + 0xffea + 4);
154         temp6 = readb(rom_start + 0xffea + 5);
155         if ((temp1 == 'C') &&
156             (temp2 == 'O') &&
157             (temp3 == 'M') &&
158             (temp4 == 'P') &&
159             (temp5 == 'A') &&
160             (temp6 == 'Q')) {
161                 result = 1;
162         }
163         dbg ("%s - returned %d\n",__FUNCTION__, result);
164         return result;
165 }
166
167
168 static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
169 {
170         unsigned long flags;
171         int op = operation;
172         int ret_val;
173         
174         if (!compaq_int15_entry_point)
175                 return -ENODEV;
176         
177         spin_lock_irqsave(&int15_lock, flags);
178         __asm__ (
179                 "xorl   %%ebx,%%ebx \n"
180                 "xorl   %%edx,%%edx \n"
181                 "pushf              \n"
182                 "push    %%cs       \n"
183                 "cli                \n"
184                 "call    *%6        \n"
185                 : "=c" (*buf_size), "=a" (ret_val)
186                 : "a" (op), "c" (*buf_size), "S" (ev_name),
187                 "D" (buffer), "m" (compaq_int15_entry_point)
188                 : "%ebx", "%edx");
189         spin_unlock_irqrestore(&int15_lock, flags);
190         
191         return((ret_val & 0xFF00) >> 8);
192 }
193
194
195 /*
196  * load_HRT
197  *
198  * Read the hot plug Resource Table from NVRAM
199  */
200 static int load_HRT (void *rom_start)
201 {
202         u32 available;
203         u32 temp_dword;
204         u8 temp_byte = 0xFF;
205         u32 rc;
206
207         if (!check_for_compaq_ROM(rom_start)) {
208                 return -ENODEV;
209         }
210
211         available = 1024;
212
213         // Now load the EV
214         temp_dword = available;
215
216         rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
217
218         evbuffer_length = temp_dword;
219
220         // We're maintaining the resource lists so write FF to invalidate old info
221         temp_dword = 1;
222
223         rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
224
225         return rc;
226 }
227
228
229 /*
230  * store_HRT
231  *
232  * Save the hot plug Resource Table in NVRAM
233  */
234 static u32 store_HRT (void *rom_start)
235 {
236         u32 *buffer;
237         u32 *pFill;
238         u32 usedbytes;
239         u32 available;
240         u32 temp_dword;
241         u32 rc;
242         u8 loop;
243         u8 numCtrl = 0;
244         struct controller *ctrl;
245         struct pci_resource *resNode;
246         struct ev_hrt_header *p_EV_header;
247         struct ev_hrt_ctrl *p_ev_ctrl;
248
249         available = 1024;
250
251         if (!check_for_compaq_ROM(rom_start)) {
252                 return(1);
253         }
254
255         buffer = (u32*) evbuffer;
256
257         if (!buffer)
258                 return(1);
259
260         pFill = buffer;
261         usedbytes = 0;
262
263         p_EV_header = (struct ev_hrt_header *) pFill;
264
265         ctrl = cpqhp_ctrl_list;
266         
267         // The revision of this structure
268         rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
269         if (rc)
270                 return(rc);
271
272         // The number of controllers
273         rc = add_byte( &pFill, 1, &usedbytes, &available);
274         if (rc)
275                 return(rc);
276
277         while (ctrl) {
278                 p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
279
280                 numCtrl++;
281
282                 // The bus number
283                 rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
284                 if (rc)
285                         return(rc);
286
287                 // The device Number
288                 rc = add_byte( &pFill, ctrl->device, &usedbytes, &available);
289                 if (rc)
290                         return(rc);
291
292                 // The function Number
293                 rc = add_byte( &pFill, ctrl->function, &usedbytes, &available);
294                 if (rc)
295                         return(rc);
296
297                 // Skip the number of available entries
298                 rc = add_dword( &pFill, 0, &usedbytes, &available);
299                 if (rc)
300                         return(rc);
301
302                 // Figure out memory Available
303
304                 resNode = ctrl->mem_head;
305
306                 loop = 0;
307
308                 while (resNode) {
309                         loop ++;
310
311                         // base
312                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
313                         if (rc)
314                                 return(rc);
315
316                         // length
317                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
318                         if (rc)
319                                 return(rc);
320
321                         resNode = resNode->next;
322                 }
323
324                 // Fill in the number of entries
325                 p_ev_ctrl->mem_avail = loop;
326
327                 // Figure out prefetchable memory Available
328
329                 resNode = ctrl->p_mem_head;
330
331                 loop = 0;
332
333                 while (resNode) {
334                         loop ++;
335
336                         // base
337                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
338                         if (rc)
339                                 return(rc);
340
341                         // length
342                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
343                         if (rc)
344                                 return(rc);
345
346                         resNode = resNode->next;
347                 }
348
349                 // Fill in the number of entries
350                 p_ev_ctrl->p_mem_avail = loop;
351
352                 // Figure out IO Available
353
354                 resNode = ctrl->io_head;
355
356                 loop = 0;
357
358                 while (resNode) {
359                         loop ++;
360
361                         // base
362                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
363                         if (rc)
364                                 return(rc);
365
366                         // length
367                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
368                         if (rc)
369                                 return(rc);
370
371                         resNode = resNode->next;
372                 }
373
374                 // Fill in the number of entries
375                 p_ev_ctrl->io_avail = loop;
376
377                 // Figure out bus Available
378
379                 resNode = ctrl->bus_head;
380
381                 loop = 0;
382
383                 while (resNode) {
384                         loop ++;
385
386                         // base
387                         rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
388                         if (rc)
389                                 return(rc);
390
391                         // length
392                         rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
393                         if (rc)
394                                 return(rc);
395
396                         resNode = resNode->next;
397                 }
398
399                 // Fill in the number of entries
400                 p_ev_ctrl->bus_avail = loop;
401
402                 ctrl = ctrl->next;
403         }
404         
405         p_EV_header->num_of_ctrl = numCtrl;
406
407         // Now store the EV
408
409         temp_dword = usedbytes;
410
411         rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
412
413         dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
414
415         evbuffer_length = temp_dword;
416
417         if (rc) {
418                 err(msg_unable_to_save);
419                 return(1);
420         }
421
422         return(0);
423 }
424
425
426 void compaq_nvram_init (void *rom_start)
427 {
428         if (rom_start) {
429                 compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
430         }
431         dbg("int15 entry  = %p\n", compaq_int15_entry_point);
432
433         /* initialize our int15 lock */
434         spin_lock_init(&int15_lock);
435 }
436
437
438 int compaq_nvram_load (void *rom_start, struct controller *ctrl)
439 {
440         u8 bus, device, function;
441         u8 nummem, numpmem, numio, numbus;
442         u32 rc;
443         u8 *p_byte;
444         struct pci_resource *mem_node;
445         struct pci_resource *p_mem_node;
446         struct pci_resource *io_node;
447         struct pci_resource *bus_node;
448         struct ev_hrt_ctrl *p_ev_ctrl;
449         struct ev_hrt_header *p_EV_header;
450
451         if (!evbuffer_init) {
452                 // Read the resource list information in from NVRAM
453                 if (load_HRT(rom_start))
454                         memset (evbuffer, 0, 1024);
455
456                 evbuffer_init = 1;
457         }
458
459         // If we saved information in NVRAM, use it now
460         p_EV_header = (struct ev_hrt_header *) evbuffer;
461
462         // The following code is for systems where version 1.0 of this
463         // driver has been loaded, but doesn't support the hardware.
464         // In that case, the driver would incorrectly store something
465         // in NVRAM.
466         if ((p_EV_header->Version == 2) ||
467             ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
468                 p_byte = &(p_EV_header->next);
469
470                 p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
471
472                 p_byte += 3;
473
474                 if (p_byte > ((u8*)p_EV_header + evbuffer_length))
475                         return(2);
476
477                 bus = p_ev_ctrl->bus;
478                 device = p_ev_ctrl->device;
479                 function = p_ev_ctrl->function;
480
481                 while ((bus != ctrl->bus) || (device != ctrl->device)
482                        || (function != ctrl->function)) {
483                         nummem = p_ev_ctrl->mem_avail;
484                         numpmem = p_ev_ctrl->p_mem_avail;
485                         numio = p_ev_ctrl->io_avail;
486                         numbus = p_ev_ctrl->bus_avail;
487
488                         p_byte += 4;
489
490                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
491                                 return(2);
492
493                         // Skip forward to the next entry
494                         p_byte += (nummem + numpmem + numio + numbus) * 8;
495
496                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
497                                 return(2);
498
499                         p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
500
501                         p_byte += 3;
502
503                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
504                                 return(2);
505
506                         bus = p_ev_ctrl->bus;
507                         device = p_ev_ctrl->device;
508                         function = p_ev_ctrl->function;
509                 }
510
511                 nummem = p_ev_ctrl->mem_avail;
512                 numpmem = p_ev_ctrl->p_mem_avail;
513                 numio = p_ev_ctrl->io_avail;
514                 numbus = p_ev_ctrl->bus_avail;
515
516                 p_byte += 4;
517
518                 if (p_byte > ((u8*)p_EV_header + evbuffer_length))
519                         return(2);
520
521                 while (nummem--) {
522                         mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
523
524                         if (!mem_node)
525                                 break;
526
527                         mem_node->base = *(u32*)p_byte;
528                         dbg("mem base = %8.8x\n",mem_node->base);
529                         p_byte += 4;
530
531                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
532                                 return(2);
533
534                         mem_node->length = *(u32*)p_byte;
535                         dbg("mem length = %8.8x\n",mem_node->length);
536                         p_byte += 4;
537
538                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
539                                 return(2);
540
541                         mem_node->next = ctrl->mem_head;
542                         ctrl->mem_head = mem_node;
543                 }
544
545                 while (numpmem--) {
546                         p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
547
548                         if (!p_mem_node)
549                                 break;
550
551                         p_mem_node->base = *(u32*)p_byte;
552                         dbg("pre-mem base = %8.8x\n",p_mem_node->base);
553                         p_byte += 4;
554
555                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
556                                 return(2);
557
558                         p_mem_node->length = *(u32*)p_byte;
559                         dbg("pre-mem length = %8.8x\n",p_mem_node->length);
560                         p_byte += 4;
561
562                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
563                                 return(2);
564
565                         p_mem_node->next = ctrl->p_mem_head;
566                         ctrl->p_mem_head = p_mem_node;
567                 }
568
569                 while (numio--) {
570                         io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
571
572                         if (!io_node)
573                                 break;
574
575                         io_node->base = *(u32*)p_byte;
576                         dbg("io base = %8.8x\n",io_node->base);
577                         p_byte += 4;
578
579                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
580                                 return(2);
581
582                         io_node->length = *(u32*)p_byte;
583                         dbg("io length = %8.8x\n",io_node->length);
584                         p_byte += 4;
585
586                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
587                                 return(2);
588
589                         io_node->next = ctrl->io_head;
590                         ctrl->io_head = io_node;
591                 }
592
593                 while (numbus--) {
594                         bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
595
596                         if (!bus_node)
597                                 break;
598
599                         bus_node->base = *(u32*)p_byte;
600                         p_byte += 4;
601
602                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
603                                 return(2);
604
605                         bus_node->length = *(u32*)p_byte;
606                         p_byte += 4;
607
608
609                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
610                                 return(2);
611
612                         bus_node->next = ctrl->bus_head;
613                         ctrl->bus_head = bus_node;
614                 }
615
616                 // If all of the following fail, we don't have any resources for
617                 // hot plug add
618                 rc = 1;
619                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
620                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
621                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
622                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
623
624                 if (rc) {
625                         return(rc);
626                 }
627         } else {
628                 if ((evbuffer[0] != 0) && (!ctrl->push_flag)) {
629                         return(1);
630                 }
631         }
632
633         return 0;
634 }
635
636         
637 int compaq_nvram_store (void *rom_start)
638 {
639         int rc = 1;
640
641         if (rom_start == NULL)
642                 return -ENODEV;
643
644         if (evbuffer_init) {
645                 rc = store_HRT(rom_start);
646                 if (rc) {
647                         err(msg_unable_to_save);
648                 }
649         }
650         return rc;
651 }
652