1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
47struct register_foo {
48 union {
49 unsigned long lword;
50 unsigned short word;
51
52 struct {
53 unsigned char low;
54 unsigned char high;
55 } byte;
56 } data;
57
58 unsigned char opcode;
59 unsigned long length;
60} __attribute__ ((packed));
61
62struct 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
73struct ev_hrt_header {
74 u8 Version;
75 u8 num_of_ctrl;
76 u8 next;
77};
78
79struct 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
91static u8 evbuffer_init;
92static u8 evbuffer_length;
93static u8 evbuffer[1024];
94
95static void *compaq_int15_entry_point;
96
97static spinlock_t int15_lock;
98
99
100
101
102
103
104
105
106
107
108
109
110static 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
125static 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
139
140
141
142
143
144static 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
168static 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
197
198
199
200static 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
214 temp_dword = available;
215
216 rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
217
218 evbuffer_length = temp_dword;
219
220
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
231
232
233
234static 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
268 rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available);
269 if (rc)
270 return(rc);
271
272
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
283 rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available);
284 if (rc)
285 return(rc);
286
287
288 rc = add_byte( &pFill, ctrl->device, &usedbytes, &available);
289 if (rc)
290 return(rc);
291
292
293 rc = add_byte( &pFill, ctrl->function, &usedbytes, &available);
294 if (rc)
295 return(rc);
296
297
298 rc = add_dword( &pFill, 0, &usedbytes, &available);
299 if (rc)
300 return(rc);
301
302
303
304 resNode = ctrl->mem_head;
305
306 loop = 0;
307
308 while (resNode) {
309 loop ++;
310
311
312 rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
313 if (rc)
314 return(rc);
315
316
317 rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
318 if (rc)
319 return(rc);
320
321 resNode = resNode->next;
322 }
323
324
325 p_ev_ctrl->mem_avail = loop;
326
327
328
329 resNode = ctrl->p_mem_head;
330
331 loop = 0;
332
333 while (resNode) {
334 loop ++;
335
336
337 rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
338 if (rc)
339 return(rc);
340
341
342 rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
343 if (rc)
344 return(rc);
345
346 resNode = resNode->next;
347 }
348
349
350 p_ev_ctrl->p_mem_avail = loop;
351
352
353
354 resNode = ctrl->io_head;
355
356 loop = 0;
357
358 while (resNode) {
359 loop ++;
360
361
362 rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
363 if (rc)
364 return(rc);
365
366
367 rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
368 if (rc)
369 return(rc);
370
371 resNode = resNode->next;
372 }
373
374
375 p_ev_ctrl->io_avail = loop;
376
377
378
379 resNode = ctrl->bus_head;
380
381 loop = 0;
382
383 while (resNode) {
384 loop ++;
385
386
387 rc = add_dword( &pFill, resNode->base, &usedbytes, &available);
388 if (rc)
389 return(rc);
390
391
392 rc = add_dword( &pFill, resNode->length, &usedbytes, &available);
393 if (rc)
394 return(rc);
395
396 resNode = resNode->next;
397 }
398
399
400 p_ev_ctrl->bus_avail = loop;
401
402 ctrl = ctrl->next;
403 }
404
405 p_EV_header->num_of_ctrl = numCtrl;
406
407
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
426void 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
434 spin_lock_init(&int15_lock);
435}
436
437
438int 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
453 if (load_HRT(rom_start))
454 memset (evbuffer, 0, 1024);
455
456 evbuffer_init = 1;
457 }
458
459
460 p_EV_header = (struct ev_hrt_header *) evbuffer;
461
462
463
464
465
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
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
617
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
637int 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
653