11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Compaq Hot Plug Controller Driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995,2001 Compaq Computer Corporation 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 IBM Corp. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NON INFRINGEMENT. See the GNU General Public License for more 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * details. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send feedback to <greg@kroah.com> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/workqueue.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 367a54f25cef6c763f16c9fd49ae382de162147873Greg Kroah-Hartman#include <linux/pci_hotplug.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cpqphp.h" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cpqphp_nvram.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ROM_INT15_PHY_ADDR 0x0FF859 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_EV 0xD8A4 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_EV 0xD8A5 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct register_foo { 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union { 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long lword; /* eax */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short word; /* ax */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct { 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char low; /* al */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char high; /* ah */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } byte; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } data; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char opcode; /* see below */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long length; /* if the reg. is a pointer, how much data */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} __attribute__ ((packed)); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct all_reg { 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo eax_reg; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo ebx_reg; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo ecx_reg; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo edx_reg; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo edi_reg; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo esi_reg; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct register_foo eflags_reg; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} __attribute__ ((packed)); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ev_hrt_header { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 Version; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 num_of_ctrl; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 next; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ev_hrt_ctrl { 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 bus; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 device; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 function; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 mem_avail; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 p_mem_avail; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 io_avail; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 bus_avail; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 next; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 evbuffer_init; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 evbuffer_length; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 evbuffer[1024]; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __iomem *compaq_int15_entry_point; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 97427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang/* lock for ordering int15_bios_call() */ 98427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiangstatic spinlock_t int15_lock; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is a series of function that deals with 102427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang * setting & getting the hotplug resource table in some environment variable. 103427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang */ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We really shouldn't be doing this unless there is a _very_ good reason to!!! 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * greg k-h 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 **tByte; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*used + 1) > *avail) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 117861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *((u8*)*p_buffer) = value; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tByte = (u8**)p_buffer; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*tByte)++; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *used+=1; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*used + 4) > *avail) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **p_buffer = value; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*p_buffer)++; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *used+=4; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * check_for_compaq_ROM 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine verifies that the ROM OEM string is 'COMPAQ' 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns 0 for non-Compaq ROM, 1 for Compaq ROM 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_for_compaq_ROM (void __iomem *rom_start) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 temp1, temp2, temp3, temp4, temp5, temp6; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result = 0; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp1 = readb(rom_start + 0xffea + 0); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp2 = readb(rom_start + 0xffea + 1); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp3 = readb(rom_start + 0xffea + 2); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp4 = readb(rom_start + 0xffea + 3); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp5 = readb(rom_start + 0xffea + 4); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp6 = readb(rom_start + 0xffea + 5); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((temp1 == 'C') && 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (temp2 == 'O') && 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (temp3 == 'M') && 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (temp4 == 'P') && 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (temp5 == 'A') && 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (temp6 == 'Q')) { 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = 1; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16466bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison dbg ("%s - returned %d\n", __func__, result); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int op = operation; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret_val; 174861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!compaq_int15_entry_point) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 177861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&int15_lock, flags); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ ( 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "xorl %%ebx,%%ebx\n" \ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "xorl %%edx,%%edx\n" \ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pushf\n" \ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "push %%cs\n" \ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "cli\n" \ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "call *%6\n" 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=c" (*buf_size), "=a" (ret_val) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "a" (op), "c" (*buf_size), "S" (ev_name), 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "D" (buffer), "m" (compaq_int15_entry_point) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "%ebx", "%edx"); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&int15_lock, flags); 191861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return((ret_val & 0xFF00) >> 8); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * load_HRT 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read the hot plug Resource Table from NVRAM 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int load_HRT (void __iomem *rom_start) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 available; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 temp_dword; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 temp_byte = 0xFF; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rc; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!check_for_compaq_ROM(rom_start)) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds available = 1024; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 214427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Now load the EV */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_dword = available; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evbuffer_length = temp_dword; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* We're maintaining the resource lists so write FF to invalidate old 222427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang * info 223427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_dword = 1; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * store_HRT 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save the hot plug Resource Table in NVRAM 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 store_HRT (void __iomem *rom_start) 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 *buffer; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 *pFill; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 usedbytes; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 available; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 temp_dword; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rc; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 loop; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 numCtrl = 0; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct controller *ctrl; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_resource *resNode; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ev_hrt_header *p_EV_header; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ev_hrt_ctrl *p_ev_ctrl; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds available = 1024; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!check_for_compaq_ROM(rom_start)) { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer = (u32*) evbuffer; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!buffer) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pFill = buffer; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usedbytes = 0; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_EV_header = (struct ev_hrt_header *) pFill; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl = cpqhp_ctrl_list; 269861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 270427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* The revision of this structure */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 275427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* The number of controllers */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_byte( &pFill, 1, &usedbytes, &available); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (ctrl) { 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl = (struct ev_hrt_ctrl *) pFill; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numCtrl++; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* The bus number */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 290427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* The device Number */ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 295427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* The function Number */ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 300427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Skip the number of available entries */ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, 0, &usedbytes, &available); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 305427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Figure out memory Available */ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = ctrl->mem_head; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop = 0; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (resNode) { 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop ++; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 314427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* base */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->base, &usedbytes, &available); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 319427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* length */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->length, &usedbytes, &available); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = resNode->next; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 327427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Fill in the number of entries */ 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl->mem_avail = loop; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 330427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Figure out prefetchable memory Available */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = ctrl->p_mem_head; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop = 0; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (resNode) { 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop ++; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 339427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* base */ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->base, &usedbytes, &available); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 344427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* length */ 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->length, &usedbytes, &available); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = resNode->next; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 352427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Fill in the number of entries */ 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl->p_mem_avail = loop; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 355427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Figure out IO Available */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = ctrl->io_head; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop = 0; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (resNode) { 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop ++; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 364427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* base */ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->base, &usedbytes, &available); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 369427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* length */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->length, &usedbytes, &available); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = resNode->next; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 377427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Fill in the number of entries */ 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl->io_avail = loop; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 380427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Figure out bus Available */ 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = ctrl->bus_head; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop = 0; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (resNode) { 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loop ++; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 389427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* base */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->base, &usedbytes, &available); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 394427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* length */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = add_dword( &pFill, resNode->length, &usedbytes, &available); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resNode = resNode->next; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 402427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Fill in the number of entries */ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl->bus_avail = loop; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl = ctrl->next; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 407861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_EV_header->num_of_ctrl = numCtrl; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Now store the EV */ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_dword = usedbytes; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evbuffer_length = temp_dword; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err(msg_unable_to_save); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(1); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid compaq_nvram_init (void __iomem *rom_start) 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rom_start) { 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("int15 entry = %p\n", compaq_int15_entry_point); 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize our int15 lock */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&int15_lock); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 bus, device, function; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 nummem, numpmem, numio, numbus; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rc; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *p_byte; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_resource *mem_node; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_resource *p_mem_node; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_resource *io_node; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_resource *bus_node; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ev_hrt_ctrl *p_ev_ctrl; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ev_hrt_header *p_EV_header; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!evbuffer_init) { 455427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Read the resource list information in from NVRAM */ 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (load_HRT(rom_start)) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset (evbuffer, 0, 1024); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds evbuffer_init = 1; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 462427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* If we saved information in NVRAM, use it now */ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_EV_header = (struct ev_hrt_header *) evbuffer; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 465427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* The following code is for systems where version 1.0 of this 466427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang * driver has been loaded, but doesn't support the hardware. 467427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang * In that case, the driver would incorrectly store something 468427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang * in NVRAM. 469427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang */ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((p_EV_header->Version == 2) || 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((p_EV_header->Version == 1) && !ctrl->push_flag)) { 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte = &(p_EV_header->next); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 3; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus = p_ev_ctrl->bus; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device = p_ev_ctrl->device; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds function = p_ev_ctrl->function; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((bus != ctrl->bus) || 486861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang (device != PCI_SLOT(ctrl->pci_dev->devfn)) || 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (function != PCI_FUNC(ctrl->pci_dev->devfn))) { 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nummem = p_ev_ctrl->mem_avail; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numpmem = p_ev_ctrl->p_mem_avail; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numio = p_ev_ctrl->io_avail; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numbus = p_ev_ctrl->bus_avail; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 498427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* Skip forward to the next entry */ 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += (nummem + numpmem + numio + numbus) * 8; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 3; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus = p_ev_ctrl->bus; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device = p_ev_ctrl->device; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds function = p_ev_ctrl->function; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nummem = p_ev_ctrl->mem_avail; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numpmem = p_ev_ctrl->p_mem_avail; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numio = p_ev_ctrl->io_avail; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds numbus = p_ev_ctrl->bus_avail; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (nummem--) { 5275cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mem_node) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem_node->base = *(u32*)p_byte; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("mem base = %8.8x\n",mem_node->base); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(mem_node); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem_node->length = *(u32*)p_byte; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("mem length = %8.8x\n",mem_node->length); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(mem_node); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem_node->next = ctrl->mem_head; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl->mem_head = mem_node; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (numpmem--) { 5555cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p_mem_node) 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_mem_node->base = *(u32*)p_byte; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("pre-mem base = %8.8x\n",p_mem_node->base); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(p_mem_node); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_mem_node->length = *(u32*)p_byte; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("pre-mem length = %8.8x\n",p_mem_node->length); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(p_mem_node); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_mem_node->next = ctrl->p_mem_head; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl->p_mem_head = p_mem_node; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (numio--) { 5835cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!io_node) 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds io_node->base = *(u32*)p_byte; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("io base = %8.8x\n",io_node->base); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(io_node); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds io_node->length = *(u32*)p_byte; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("io length = %8.8x\n",io_node->length); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(io_node); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds io_node->next = ctrl->io_head; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl->io_head = io_node; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (numbus--) { 6115cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bus_node) 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_node->base = *(u32*)p_byte; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bus_node); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_node->length = *(u32*)p_byte; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p_byte += 4; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p_byte > ((u8*)p_EV_header + evbuffer_length)) { 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bus_node); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_node->next = ctrl->bus_head; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctrl->bus_head = bus_node; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 636427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang /* If all of the following fail, we don't have any resources for 637427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang * hot plug add 638427438c61b0083a60bb953cb36cfdc5841f0bb03Alex Chiang */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = 1; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head)); 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head)); 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head)); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(rc); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 648861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang if ((evbuffer[0] != 0) && (!ctrl->push_flag)) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 655861fefbf550d41e7a4f44584f3ec35977fa08bf1Alex Chiang 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint compaq_nvram_store (void __iomem *rom_start) 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = 1; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rom_start == NULL) 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (evbuffer_init) { 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = store_HRT(rom_start); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err(msg_unable_to_save); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 672