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