0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/types.h>
0018 #include <linux/proc_fs.h>
0019 #include <linux/slab.h>
0020 #include <linux/workqueue.h>
0021 #include <linux/pci.h>
0022 #include <linux/pci_hotplug.h>
0023 #include <linux/uaccess.h>
0024 #include "cpqphp.h"
0025 #include "cpqphp_nvram.h"
0026
0027
0028 #define ROM_INT15_PHY_ADDR 0x0FF859
0029 #define READ_EV 0xD8A4
0030 #define WRITE_EV 0xD8A5
0031
0032 struct register_foo {
0033 union {
0034 unsigned long lword;
0035 unsigned short word;
0036
0037 struct {
0038 unsigned char low;
0039 unsigned char high;
0040 } byte;
0041 } data;
0042
0043 unsigned char opcode;
0044 unsigned long length;
0045 } __attribute__ ((packed));
0046
0047 struct all_reg {
0048 struct register_foo eax_reg;
0049 struct register_foo ebx_reg;
0050 struct register_foo ecx_reg;
0051 struct register_foo edx_reg;
0052 struct register_foo edi_reg;
0053 struct register_foo esi_reg;
0054 struct register_foo eflags_reg;
0055 } __attribute__ ((packed));
0056
0057
0058 struct ev_hrt_header {
0059 u8 Version;
0060 u8 num_of_ctrl;
0061 u8 next;
0062 };
0063
0064 struct ev_hrt_ctrl {
0065 u8 bus;
0066 u8 device;
0067 u8 function;
0068 u8 mem_avail;
0069 u8 p_mem_avail;
0070 u8 io_avail;
0071 u8 bus_avail;
0072 u8 next;
0073 };
0074
0075
0076 static u8 evbuffer_init;
0077 static u8 evbuffer_length;
0078 static u8 evbuffer[1024];
0079
0080 static void __iomem *compaq_int15_entry_point;
0081
0082
0083 static DEFINE_SPINLOCK(int15_lock);
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static u32 add_byte(u32 **p_buffer, u8 value, u32 *used, u32 *avail)
0097 {
0098 u8 **tByte;
0099
0100 if ((*used + 1) > *avail)
0101 return(1);
0102
0103 *((u8 *)*p_buffer) = value;
0104 tByte = (u8 **)p_buffer;
0105 (*tByte)++;
0106 *used += 1;
0107 return(0);
0108 }
0109
0110
0111 static u32 add_dword(u32 **p_buffer, u32 value, u32 *used, u32 *avail)
0112 {
0113 if ((*used + 4) > *avail)
0114 return(1);
0115
0116 **p_buffer = value;
0117 (*p_buffer)++;
0118 *used += 4;
0119 return(0);
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 static int check_for_compaq_ROM(void __iomem *rom_start)
0131 {
0132 u8 temp1, temp2, temp3, temp4, temp5, temp6;
0133 int result = 0;
0134
0135 temp1 = readb(rom_start + 0xffea + 0);
0136 temp2 = readb(rom_start + 0xffea + 1);
0137 temp3 = readb(rom_start + 0xffea + 2);
0138 temp4 = readb(rom_start + 0xffea + 3);
0139 temp5 = readb(rom_start + 0xffea + 4);
0140 temp6 = readb(rom_start + 0xffea + 5);
0141 if ((temp1 == 'C') &&
0142 (temp2 == 'O') &&
0143 (temp3 == 'M') &&
0144 (temp4 == 'P') &&
0145 (temp5 == 'A') &&
0146 (temp6 == 'Q')) {
0147 result = 1;
0148 }
0149 dbg("%s - returned %d\n", __func__, result);
0150 return result;
0151 }
0152
0153
0154 static u32 access_EV(u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
0155 {
0156 unsigned long flags;
0157 int op = operation;
0158 int ret_val;
0159
0160 if (!compaq_int15_entry_point)
0161 return -ENODEV;
0162
0163 spin_lock_irqsave(&int15_lock, flags);
0164 __asm__ (
0165 "xorl %%ebx,%%ebx\n" \
0166 "xorl %%edx,%%edx\n" \
0167 "pushf\n" \
0168 "push %%cs\n" \
0169 "cli\n" \
0170 "call *%6\n"
0171 : "=c" (*buf_size), "=a" (ret_val)
0172 : "a" (op), "c" (*buf_size), "S" (ev_name),
0173 "D" (buffer), "m" (compaq_int15_entry_point)
0174 : "%ebx", "%edx");
0175 spin_unlock_irqrestore(&int15_lock, flags);
0176
0177 return((ret_val & 0xFF00) >> 8);
0178 }
0179
0180
0181
0182
0183
0184
0185
0186 static int load_HRT(void __iomem *rom_start)
0187 {
0188 u32 available;
0189 u32 temp_dword;
0190 u8 temp_byte = 0xFF;
0191 u32 rc;
0192
0193 if (!check_for_compaq_ROM(rom_start))
0194 return -ENODEV;
0195
0196 available = 1024;
0197
0198
0199 temp_dword = available;
0200
0201 rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
0202
0203 evbuffer_length = temp_dword;
0204
0205
0206
0207
0208 temp_dword = 1;
0209
0210 rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
0211
0212 return rc;
0213 }
0214
0215
0216
0217
0218
0219
0220
0221 static u32 store_HRT(void __iomem *rom_start)
0222 {
0223 u32 *buffer;
0224 u32 *pFill;
0225 u32 usedbytes;
0226 u32 available;
0227 u32 temp_dword;
0228 u32 rc;
0229 u8 loop;
0230 u8 numCtrl = 0;
0231 struct controller *ctrl;
0232 struct pci_resource *resNode;
0233 struct ev_hrt_header *p_EV_header;
0234 struct ev_hrt_ctrl *p_ev_ctrl;
0235
0236 available = 1024;
0237
0238 if (!check_for_compaq_ROM(rom_start))
0239 return(1);
0240
0241 buffer = (u32 *) evbuffer;
0242
0243 if (!buffer)
0244 return(1);
0245
0246 pFill = buffer;
0247 usedbytes = 0;
0248
0249 p_EV_header = (struct ev_hrt_header *) pFill;
0250
0251 ctrl = cpqhp_ctrl_list;
0252
0253
0254 rc = add_byte(&pFill, 1 + ctrl->push_flag, &usedbytes, &available);
0255 if (rc)
0256 return(rc);
0257
0258
0259 rc = add_byte(&pFill, 1, &usedbytes, &available);
0260 if (rc)
0261 return(rc);
0262
0263 while (ctrl) {
0264 p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
0265
0266 numCtrl++;
0267
0268
0269 rc = add_byte(&pFill, ctrl->bus, &usedbytes, &available);
0270 if (rc)
0271 return(rc);
0272
0273
0274 rc = add_byte(&pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
0275 if (rc)
0276 return(rc);
0277
0278
0279 rc = add_byte(&pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
0280 if (rc)
0281 return(rc);
0282
0283
0284 rc = add_dword(&pFill, 0, &usedbytes, &available);
0285 if (rc)
0286 return(rc);
0287
0288
0289
0290 resNode = ctrl->mem_head;
0291
0292 loop = 0;
0293
0294 while (resNode) {
0295 loop++;
0296
0297
0298 rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
0299 if (rc)
0300 return(rc);
0301
0302
0303 rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
0304 if (rc)
0305 return(rc);
0306
0307 resNode = resNode->next;
0308 }
0309
0310
0311 p_ev_ctrl->mem_avail = loop;
0312
0313
0314
0315 resNode = ctrl->p_mem_head;
0316
0317 loop = 0;
0318
0319 while (resNode) {
0320 loop++;
0321
0322
0323 rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
0324 if (rc)
0325 return(rc);
0326
0327
0328 rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
0329 if (rc)
0330 return(rc);
0331
0332 resNode = resNode->next;
0333 }
0334
0335
0336 p_ev_ctrl->p_mem_avail = loop;
0337
0338
0339
0340 resNode = ctrl->io_head;
0341
0342 loop = 0;
0343
0344 while (resNode) {
0345 loop++;
0346
0347
0348 rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
0349 if (rc)
0350 return(rc);
0351
0352
0353 rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
0354 if (rc)
0355 return(rc);
0356
0357 resNode = resNode->next;
0358 }
0359
0360
0361 p_ev_ctrl->io_avail = loop;
0362
0363
0364
0365 resNode = ctrl->bus_head;
0366
0367 loop = 0;
0368
0369 while (resNode) {
0370 loop++;
0371
0372
0373 rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
0374 if (rc)
0375 return(rc);
0376
0377
0378 rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
0379 if (rc)
0380 return(rc);
0381
0382 resNode = resNode->next;
0383 }
0384
0385
0386 p_ev_ctrl->bus_avail = loop;
0387
0388 ctrl = ctrl->next;
0389 }
0390
0391 p_EV_header->num_of_ctrl = numCtrl;
0392
0393
0394
0395 temp_dword = usedbytes;
0396
0397 rc = access_EV(WRITE_EV, "CQTHPS", (u8 *) buffer, &temp_dword);
0398
0399 dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
0400
0401 evbuffer_length = temp_dword;
0402
0403 if (rc) {
0404 err(msg_unable_to_save);
0405 return(1);
0406 }
0407
0408 return(0);
0409 }
0410
0411
0412 void compaq_nvram_init(void __iomem *rom_start)
0413 {
0414 if (rom_start)
0415 compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
0416
0417 dbg("int15 entry = %p\n", compaq_int15_entry_point);
0418 }
0419
0420
0421 int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl)
0422 {
0423 u8 bus, device, function;
0424 u8 nummem, numpmem, numio, numbus;
0425 u32 rc;
0426 u8 *p_byte;
0427 struct pci_resource *mem_node;
0428 struct pci_resource *p_mem_node;
0429 struct pci_resource *io_node;
0430 struct pci_resource *bus_node;
0431 struct ev_hrt_ctrl *p_ev_ctrl;
0432 struct ev_hrt_header *p_EV_header;
0433
0434 if (!evbuffer_init) {
0435
0436 if (load_HRT(rom_start))
0437 memset(evbuffer, 0, 1024);
0438
0439 evbuffer_init = 1;
0440 }
0441
0442
0443 p_EV_header = (struct ev_hrt_header *) evbuffer;
0444
0445
0446
0447
0448
0449
0450 if ((p_EV_header->Version == 2) ||
0451 ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
0452 p_byte = &(p_EV_header->next);
0453
0454 p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
0455
0456 p_byte += 3;
0457
0458 if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
0459 return 2;
0460
0461 bus = p_ev_ctrl->bus;
0462 device = p_ev_ctrl->device;
0463 function = p_ev_ctrl->function;
0464
0465 while ((bus != ctrl->bus) ||
0466 (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
0467 (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
0468 nummem = p_ev_ctrl->mem_avail;
0469 numpmem = p_ev_ctrl->p_mem_avail;
0470 numio = p_ev_ctrl->io_avail;
0471 numbus = p_ev_ctrl->bus_avail;
0472
0473 p_byte += 4;
0474
0475 if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
0476 return 2;
0477
0478
0479 p_byte += (nummem + numpmem + numio + numbus) * 8;
0480
0481 if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
0482 return 2;
0483
0484 p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
0485
0486 p_byte += 3;
0487
0488 if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
0489 return 2;
0490
0491 bus = p_ev_ctrl->bus;
0492 device = p_ev_ctrl->device;
0493 function = p_ev_ctrl->function;
0494 }
0495
0496 nummem = p_ev_ctrl->mem_avail;
0497 numpmem = p_ev_ctrl->p_mem_avail;
0498 numio = p_ev_ctrl->io_avail;
0499 numbus = p_ev_ctrl->bus_avail;
0500
0501 p_byte += 4;
0502
0503 if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
0504 return 2;
0505
0506 while (nummem--) {
0507 mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
0508
0509 if (!mem_node)
0510 break;
0511
0512 mem_node->base = *(u32 *)p_byte;
0513 dbg("mem base = %8.8x\n", mem_node->base);
0514 p_byte += 4;
0515
0516 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0517 kfree(mem_node);
0518 return 2;
0519 }
0520
0521 mem_node->length = *(u32 *)p_byte;
0522 dbg("mem length = %8.8x\n", mem_node->length);
0523 p_byte += 4;
0524
0525 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0526 kfree(mem_node);
0527 return 2;
0528 }
0529
0530 mem_node->next = ctrl->mem_head;
0531 ctrl->mem_head = mem_node;
0532 }
0533
0534 while (numpmem--) {
0535 p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
0536
0537 if (!p_mem_node)
0538 break;
0539
0540 p_mem_node->base = *(u32 *)p_byte;
0541 dbg("pre-mem base = %8.8x\n", p_mem_node->base);
0542 p_byte += 4;
0543
0544 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0545 kfree(p_mem_node);
0546 return 2;
0547 }
0548
0549 p_mem_node->length = *(u32 *)p_byte;
0550 dbg("pre-mem length = %8.8x\n", p_mem_node->length);
0551 p_byte += 4;
0552
0553 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0554 kfree(p_mem_node);
0555 return 2;
0556 }
0557
0558 p_mem_node->next = ctrl->p_mem_head;
0559 ctrl->p_mem_head = p_mem_node;
0560 }
0561
0562 while (numio--) {
0563 io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
0564
0565 if (!io_node)
0566 break;
0567
0568 io_node->base = *(u32 *)p_byte;
0569 dbg("io base = %8.8x\n", io_node->base);
0570 p_byte += 4;
0571
0572 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0573 kfree(io_node);
0574 return 2;
0575 }
0576
0577 io_node->length = *(u32 *)p_byte;
0578 dbg("io length = %8.8x\n", io_node->length);
0579 p_byte += 4;
0580
0581 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0582 kfree(io_node);
0583 return 2;
0584 }
0585
0586 io_node->next = ctrl->io_head;
0587 ctrl->io_head = io_node;
0588 }
0589
0590 while (numbus--) {
0591 bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
0592
0593 if (!bus_node)
0594 break;
0595
0596 bus_node->base = *(u32 *)p_byte;
0597 p_byte += 4;
0598
0599 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0600 kfree(bus_node);
0601 return 2;
0602 }
0603
0604 bus_node->length = *(u32 *)p_byte;
0605 p_byte += 4;
0606
0607 if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
0608 kfree(bus_node);
0609 return 2;
0610 }
0611
0612 bus_node->next = ctrl->bus_head;
0613 ctrl->bus_head = bus_node;
0614 }
0615
0616
0617
0618
0619 rc = 1;
0620 rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
0621 rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
0622 rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
0623 rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
0624
0625 if (rc)
0626 return(rc);
0627 } else {
0628 if ((evbuffer[0] != 0) && (!ctrl->push_flag))
0629 return 1;
0630 }
0631
0632 return 0;
0633 }
0634
0635
0636 int compaq_nvram_store(void __iomem *rom_start)
0637 {
0638 int rc = 1;
0639
0640 if (rom_start == NULL)
0641 return -ENODEV;
0642
0643 if (evbuffer_init) {
0644 rc = store_HRT(rom_start);
0645 if (rc)
0646 err(msg_unable_to_save);
0647 }
0648 return rc;
0649 }
0650