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 47struct 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 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; /* 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 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 *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 (__FUNCTION__" - returned %d\n", 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 *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 */ 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 // 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 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 /* initialize our int15 lock */ 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 // 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 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