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