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