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 <asm/uaccess.h> 38#include "cpqphp.h" 39#include "cpqphp_nvram.h" 40 41 42#define ROM_INT15_PHY_ADDR 0x0FF859 43#define READ_EV 0xD8A4 44#define WRITE_EV 0xD8A5 45 46struct register_foo { 47 union { 48 unsigned long lword; /* eax */ 49 unsigned short word; /* ax */ 50 51 struct { 52 unsigned char low; /* al */ 53 unsigned char high; /* ah */ 54 } byte; 55 } data; 56 57 unsigned char opcode; /* see below */ 58 unsigned long length; /* if the reg. is a pointer, how much data */ 59} __attribute__ ((packed)); 60 61struct all_reg { 62 struct register_foo eax_reg; 63 struct register_foo ebx_reg; 64 struct register_foo ecx_reg; 65 struct register_foo edx_reg; 66 struct register_foo edi_reg; 67 struct register_foo esi_reg; 68 struct register_foo eflags_reg; 69} __attribute__ ((packed)); 70 71 72struct ev_hrt_header { 73 u8 Version; 74 u8 num_of_ctrl; 75 u8 next; 76}; 77 78struct ev_hrt_ctrl { 79 u8 bus; 80 u8 device; 81 u8 function; 82 u8 mem_avail; 83 u8 p_mem_avail; 84 u8 io_avail; 85 u8 bus_avail; 86 u8 next; 87}; 88 89 90static u8 evbuffer_init; 91static u8 evbuffer_length; 92static u8 evbuffer[1024]; 93 94static void __iomem *compaq_int15_entry_point; 95 96/* lock for ordering int15_bios_call() */ 97static spinlock_t int15_lock; 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 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 * 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 */ 144static int check_for_compaq_ROM (void __iomem *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", __func__, 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 * load_HRT 197 * 198 * Read the hot plug Resource Table from NVRAM 199 */ 200static int load_HRT (void __iomem *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 available = 1024; 211 212 /* Now load the EV */ 213 temp_dword = available; 214 215 rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword); 216 217 evbuffer_length = temp_dword; 218 219 /* We're maintaining the resource lists so write FF to invalidate old 220 * info 221 */ 222 temp_dword = 1; 223 224 rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword); 225 226 return rc; 227} 228 229 230/* 231 * store_HRT 232 * 233 * Save the hot plug Resource Table in NVRAM 234 */ 235static u32 store_HRT (void __iomem *rom_start) 236{ 237 u32 *buffer; 238 u32 *pFill; 239 u32 usedbytes; 240 u32 available; 241 u32 temp_dword; 242 u32 rc; 243 u8 loop; 244 u8 numCtrl = 0; 245 struct controller *ctrl; 246 struct pci_resource *resNode; 247 struct ev_hrt_header *p_EV_header; 248 struct ev_hrt_ctrl *p_ev_ctrl; 249 250 available = 1024; 251 252 if (!check_for_compaq_ROM(rom_start)) 253 return(1); 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, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available); 289 if (rc) 290 return(rc); 291 292 /* The function Number */ 293 rc = add_byte(&pFill, PCI_FUNC(ctrl->pci_dev->devfn), &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 426void compaq_nvram_init (void __iomem *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 438int compaq_nvram_load (void __iomem *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 */ 467 if ((p_EV_header->Version == 2) || 468 ((p_EV_header->Version == 1) && !ctrl->push_flag)) { 469 p_byte = &(p_EV_header->next); 470 471 p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next); 472 473 p_byte += 3; 474 475 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 476 return 2; 477 478 bus = p_ev_ctrl->bus; 479 device = p_ev_ctrl->device; 480 function = p_ev_ctrl->function; 481 482 while ((bus != ctrl->bus) || 483 (device != PCI_SLOT(ctrl->pci_dev->devfn)) || 484 (function != PCI_FUNC(ctrl->pci_dev->devfn))) { 485 nummem = p_ev_ctrl->mem_avail; 486 numpmem = p_ev_ctrl->p_mem_avail; 487 numio = p_ev_ctrl->io_avail; 488 numbus = p_ev_ctrl->bus_avail; 489 490 p_byte += 4; 491 492 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 493 return 2; 494 495 /* Skip forward to the next entry */ 496 p_byte += (nummem + numpmem + numio + numbus) * 8; 497 498 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 499 return 2; 500 501 p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte; 502 503 p_byte += 3; 504 505 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 506 return 2; 507 508 bus = p_ev_ctrl->bus; 509 device = p_ev_ctrl->device; 510 function = p_ev_ctrl->function; 511 } 512 513 nummem = p_ev_ctrl->mem_avail; 514 numpmem = p_ev_ctrl->p_mem_avail; 515 numio = p_ev_ctrl->io_avail; 516 numbus = p_ev_ctrl->bus_avail; 517 518 p_byte += 4; 519 520 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 521 return 2; 522 523 while (nummem--) { 524 mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 525 526 if (!mem_node) 527 break; 528 529 mem_node->base = *(u32*)p_byte; 530 dbg("mem base = %8.8x\n",mem_node->base); 531 p_byte += 4; 532 533 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 534 kfree(mem_node); 535 return 2; 536 } 537 538 mem_node->length = *(u32*)p_byte; 539 dbg("mem length = %8.8x\n",mem_node->length); 540 p_byte += 4; 541 542 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 543 kfree(mem_node); 544 return 2; 545 } 546 547 mem_node->next = ctrl->mem_head; 548 ctrl->mem_head = mem_node; 549 } 550 551 while (numpmem--) { 552 p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 553 554 if (!p_mem_node) 555 break; 556 557 p_mem_node->base = *(u32*)p_byte; 558 dbg("pre-mem base = %8.8x\n",p_mem_node->base); 559 p_byte += 4; 560 561 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 562 kfree(p_mem_node); 563 return 2; 564 } 565 566 p_mem_node->length = *(u32*)p_byte; 567 dbg("pre-mem length = %8.8x\n",p_mem_node->length); 568 p_byte += 4; 569 570 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 571 kfree(p_mem_node); 572 return 2; 573 } 574 575 p_mem_node->next = ctrl->p_mem_head; 576 ctrl->p_mem_head = p_mem_node; 577 } 578 579 while (numio--) { 580 io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 581 582 if (!io_node) 583 break; 584 585 io_node->base = *(u32*)p_byte; 586 dbg("io base = %8.8x\n",io_node->base); 587 p_byte += 4; 588 589 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 590 kfree(io_node); 591 return 2; 592 } 593 594 io_node->length = *(u32*)p_byte; 595 dbg("io length = %8.8x\n",io_node->length); 596 p_byte += 4; 597 598 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 599 kfree(io_node); 600 return 2; 601 } 602 603 io_node->next = ctrl->io_head; 604 ctrl->io_head = io_node; 605 } 606 607 while (numbus--) { 608 bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 609 610 if (!bus_node) 611 break; 612 613 bus_node->base = *(u32*)p_byte; 614 p_byte += 4; 615 616 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 617 kfree(bus_node); 618 return 2; 619 } 620 621 bus_node->length = *(u32*)p_byte; 622 p_byte += 4; 623 624 if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 625 kfree(bus_node); 626 return 2; 627 } 628 629 bus_node->next = ctrl->bus_head; 630 ctrl->bus_head = bus_node; 631 } 632 633 /* If all of the following fail, we don't have any resources for 634 * hot plug add 635 */ 636 rc = 1; 637 rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head)); 638 rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head)); 639 rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head)); 640 rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); 641 642 if (rc) 643 return(rc); 644 } else { 645 if ((evbuffer[0] != 0) && (!ctrl->push_flag)) 646 return 1; 647 } 648 649 return 0; 650} 651 652 653int compaq_nvram_store (void __iomem *rom_start) 654{ 655 int rc = 1; 656 657 if (rom_start == NULL) 658 return -ENODEV; 659 660 if (evbuffer_init) { 661 rc = store_HRT(rom_start); 662 if (rc) 663 err(msg_unable_to_save); 664 } 665 return rc; 666} 667 668