/*
* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.

* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA 
*/

#define VSM_SIGNATURE		0x204D5356	// 'VSM '
#define VSA_VERSION		0x03B0		// SysMgr Version


#define BYTE_IO                0x01
#define WORD_IO                0x03
#define DWORD_IO               0x0F
#define IO_WRITE               0x80



typedef  unsigned char UCHAR;
typedef  unsigned long ULONG;
typedef  unsigned short USHORT;



#define HIWORD(p)  ((USHORT) ((p) >> 16))

typedef struct {
	unsigned short Alignment: 5;		// 2^(n+5)  (e.g. 00000 = 32-byte boundary)
	unsigned short LoadHi: 1;			// 1 = must load VSM above top of memory
	unsigned short LoadLo: 1;			// 1 = must load VSM below 1 MB
	unsigned short SkipMe: 1;			// 1 = Skip this VSM
	unsigned short Reserved: 8;
} Requirements;






//*********************************************************************
// 			Structures
//*********************************************************************

typedef struct {
  union {
    ULONG  Reg_EAX;
    USHORT Reg_AX;
	struct {
	  UCHAR Reg_AL;
	  UCHAR Reg_AH;
	};
  };
  union {
    ULONG  Reg_EBX;
    USHORT Reg_BX;
	struct {
	  UCHAR Reg_BL;
	  UCHAR Reg_BH;
	};
  };
  union {
    ULONG  Reg_ECX;
    USHORT Reg_CX;
	struct {
	  UCHAR Reg_CL;
	  UCHAR Reg_CH;
	};
  };
  union {
    ULONG  Reg_EDX;
    USHORT Reg_DX;
	struct {
	  UCHAR Reg_DL;
	  UCHAR Reg_DH;
	};
  };
  union {
    ULONG  Reg_EBP;
    USHORT Reg_BP;
  };
  union {
    ULONG  Reg_ESI;
    USHORT Reg_SI;
  };
  union {
    ULONG  Reg_EDI;
    USHORT Reg_DI;
  };
  USHORT Reg_DS;
  USHORT Reg_ES;
  USHORT Flags;
  UCHAR PIC0_Mask;
  UCHAR PIC1_Mask;			
} INT_REGS;



typedef struct {			// Used by SVDC & RSDC instructions
	USHORT	limit_15_0;
	USHORT	base_15_0;
	UCHAR	base_23_16;
	UCHAR	attr;
#define G_BIT				0x80
#define D_BIT				0x40

	UCHAR	limit_19_16;
	UCHAR	base_31_24;
	USHORT	selector;
} Descriptor;


typedef struct {
	ULONG	Reserved;
	ULONG	SMM_CTL_MSR;
	ULONG	write_data;
	USHORT	IO_addr;
	USHORT	data_size;
    union {
  	  struct {
	    USHORT CS_Writable: 1;
	    USHORT IO_Write:    1;
	    USHORT REP_Prefix:  1;
	    USHORT SMINT:       1;

	    USHORT HALT:        1;
	    USHORT Ext_IO_Trap: 1;
	    USHORT External:    1;
	    USHORT IO_Trap:     1;

	    USHORT Nested:      1;
	    USHORT Reserved:    6;
	    USHORT CS_Readable: 1;
	  } SMI_Flags;
	  USHORT SMI_Flags_Ushort;
	};
  
	USHORT SS_Flags;

    struct {
      ULONG limit;
      ULONG	 base;
      USHORT selector;
      USHORT attr;
	} _CS;

    union {
      USHORT Next_IP;
	  ULONG	Next_EIP;
    };
    union {
      USHORT Current_IP;
	  ULONG	Current_EIP;
    };
	ULONG	r_CR0;
	ULONG	EFLAGS;
	ULONG	r_DR7;
} SmiHeader;






typedef USHORT MSG;
typedef USHORT PRIORITY;
typedef USHORT EVENT;
typedef ULONG  VSM;





#define MAX_MSG_PARAM       4	// Parameter count
#define MAX_MSG_CNT	 	10 	// # entries in message queue

typedef struct {
   MSG Msg;				// Message code
   PRIORITY Priority;			// Priority
   ULONG From_VSM;				// VSM that sent the message
   ULONG Param[MAX_MSG_PARAM];	// Parameters
   ULONG Timestamp;			// Timestamp when message was entered
} Message;


typedef struct {

  // VSM's state
  SmiHeader State;				// SMM header for this VSM

  // NOTE: Flink field must be immediately after State structure
  ULONG Flink;				// Forward link to next VSM
  ULONG Blink;	 			// Backward link to previous VSM
  ULONG SavedESP;				// VSM's stack pointer
  ULONG SysMgr_Ptr;			// Ptr to SysMgr's InfoStuff structure
  ULONG Southbridge;			// PCI address of Southbridge


  // Statistics
  ULONG Adjustment;			// Clocks used by SMM entry/exit
  ULONG Clocks[2];				// Total clocks used by this VSM
  ULONG NumSMIs[2];			// Total SMI count for this VSM
  ULONG FrozenClocks[2]; 		// Copied from Clocks[]
  ULONG FrozenNumSMIs[2];		// Copied from NumSMIs[]
  ULONG StartTime[2];			// Timestamp @ start of timeslice
  ULONG StartClocks[2];		// Timestamp of last INFO /S

  // Floating Point
  UCHAR FPU_State[108];   		// Saved FPU state
  UCHAR FPU_Flag;              // Non-zero if FPU in use

  UCHAR RunFlag;				// VSM's scheduler state

  USHORT ResumeVector;			// Used by SaveToRAM
  USHORT Pad[5];

  // Message Queue
  USHORT EndMsgQ;	 	 		// Offset of *end* of message queue
  USHORT Qhead;				// Message queue head offset
  USHORT Qtail; 				// Message queue tail offset

  // MsgQueue is variable length, so it must be the last field
  Message MsgQueue[MAX_MSG_CNT];	// The VSM's message queue

} System;



//*********************************************************************
// 			VSM Header
//*********************************************************************

typedef struct  {
	ULONG  Signature;			// 'VSM '
	UCHAR  VSM_Type;   			// Type of VSM
	UCHAR  ForCPU;				// Required CPU  (FFFFh for any)
	USHORT ForChipset;			// Required companion I/O  (FFFFh for any)
	USHORT VSM_Version;			// Version of VSM
	ULONG  VSM_Length; 			// Length of VSM module in bytes
	USHORT EntryPoint;	 		// Offset of entry point
	ULONG  DS_Limit;
	Requirements Flag;			// Special requirements/capabilities
	USHORT VSA_Version;
	Descriptor _SS;				// SS: descriptor for this VSM
	Descriptor _DS;			 	// DS: descriptor for this VSM
	Descriptor _ES;				// ES: descriptor for this VSM
	USHORT AlignSystem;			// SysStuff must be DWORD aligned
	System SysStuff;			// Reserved for use by System Manager

} VSM_Header;






//*********************************************************************
// 			VSM Types
//*********************************************************************
#define VSM_SYS_MGR        0x00		// System Manager
#define VSM_AUDIO          0x01		// Xpress Audio
#define VSM_VGA            0x02		// SoftVGA
#define VSM_LEGACY         0x03		// Standard AT peripherals
#define VSM_PM             0x04		// Legacy Power Management
#define VSM_OHCI           0x05		// OHCI
#define VSM_i8042          0x06		// 8042 emulator
#define VSM_DEBUGGER       0x07		// SMI based debugger
#define VSM_ACPI           0x08		// Virtual ACPI
#define VSM_APM            0x09		// APM 1.2
#define VSM_OEM_ACPI       0x0A		// OEM ACPI customizations
#define VSM_SMB            0x0B		// System Management Bus
#define VSM_BATTERY        0x0C		// Battery controller
#define VSM_RTC            0x0D		// Virtual RTC
#define VSM_S2D            0x0E		// SaveToDisk
#define VSM_EXT_AMP        0x0F		// External audio amplifier
#define VSM_PCMCIA         0x10		// PCMCIA
#define VSM_SPY            0x11		// Spy. Receives ALL messages first.
#define VSM_NETWORK        0x12		// Network
#define VSM_GPIO           0x13		// GPIO handler
#define VSM_KEYBOARD       0x14		// USB keyboard to PC/AT emulation
#define VSM_MOUSE          0x15		// USB mouse to PS/2 emulation
#define VSM_USB            0x16		// Universal Serial Bus
#define VSM_FLASH          0x17		// FLASH
#define VSM_INFRARED       0x18		// Infrared
#define VSM_THERMAL        0x19		// Thermal monitor
#define VSM_NULL           0x1A		// Unspecified
#define VSM_MPEG           0x1B		// MPEG video decoder (EMMA)
#define VSM_VIP            0x1C		// Video processor (VIDEC)
#define VSM_LPC            0x1D		// Low Pin Count bus
#define VSM_VUART          0x1E		// Virtual UART
#define VSM_MICRO          0x1F		// MicroController
#define VSM_USER1          0x20		// USER 1
#define VSM_USER2          0x21		// USER 2
#define VSM_USER3          0x22		// USER 3
#define VSM_SYSINFO        0x23		// System Information
#define VSM_SUPERIO        0x24		// PM for SuperIO
#define VSM_EHCI           0x25		// EHCI
#define VSM_MAX_TYPE       VSM_EHCI	// Highest valid VSM type

#define VSM_ANY            0xFF		// Wildcard for SYS_BROADCAST
#define VSM_NOT_SELF       0x4000	// Flag used by SYS_BROADCAST
#define VSM_ALL_EXCEPT     0x8000	// Flag used by SYS_BROADCAST


//*********************************************************************
// SMINT codes used by non-VSA components (BIOS, INIT, etc.)
//*********************************************************************
#define SYS_BIOS_INIT          0x00F0   // VSA installation	from POST
#define SYS_DOS_INSTALL        0x00F2   // VSA installation from DOS prompt
#define SYS_VSM_INSTALL        0x00F3   // Install VSM dynamically
#define SYS_REMOVE             0x00F4   // Unregister events belonging to VSM
#define SYS_INT_RETURN         0x00F5   // Return from call to INT vector
#define SYS_RESUME_FROM_RAM    0x6789   // Resume from RAM
#define SYS_END_OF_POST        0x5000   // Issued by GeodeROM at end of POST
#define SYS_INT13_SMI          0x5001   // Issued by Int 13 module (USB floppy)
#define SYS_INT13CDR_SMI       0x5003   // Issued by Int 13 module (USB CD-ROM)
#define SYS_USB_DEVICE_SMI     0x7777   // Issued by USBBOOT.ROM to access device table

//*********************************************************************
//			Event Priorities
//*********************************************************************
#define NORMAL_PRIORITY        0x0000
#define MAX_PRIORITY           0x7FFF
#define BROADCAST_PRIORITY     0x9000
#define UNREGISTER_PRIORITY    0xFFF0

//*********************************************************************
//			Messages
//*********************************************************************

#define MSG_INITIALIZE		   0		// Perform VSM initialization
  #define EARLY_INIT           0
  #define END_OF_POST_INIT     1

#define MSG_SHUTDOWN           1		// Prepare for system shutdown (cold boot)
#define MSG_SAVE_STATE         2		// Save entire state of device(s) controlled by VSM
#define MSG_RESTORE_STATE      3		// Restore saved state of device(s) controlled by VSM
#define MSG_SET_POWER_STATE    4		// Set device(s) to specified power state
#define MSG_EVENT              5		// A registered  event has occurred
#define MSG_QUEUE_OVERFLOW     6		// The message queue is full.
#define MSG_WARM_BOOT          7		// Prepare for a warm boot
#define MSG_SET_POWER_MODE     9		// Restore saved state of device(s) controlled by VSM
#define MSG_ABORT_POWER_STATE  10		// Power state is to be aborted

//*********************************************************************
//			Events
//*********************************************************************

#define EVENT_GRAPHICS         1		// Video event
#define EVENT_AUDIO            2		// Audio event
#define EVENT_USB              3		// USB event
#define EVENT_ACPI             4		// ACPI register access
#define EVENT_ACPI_TIMER       5		// The ACPI timer expired
#define EVENT_IO_TRAP          6		// I/O trap
#define EVENT_IO_TIMEOUT       7		// I/O timeout
#define EVENT_PME              8		// Power Management
#define EVENT_KEL              9		// KEL
#define EVENT_VIDEO_INACTIVITY 0x0A	// Not supported in GX2
#define EVENT_GPIO             0x0B	// GPIO transition
  #define FALLING_EDGE          (1 << 0)
  #define RISING_EDGE           (1 << 1)
  #define BOTH_EDGES            (FALLING_EDGE | RISING_EDGE) 
  #define PME                   (1 << 2)
  #define DEBOUNCE              (1 << 3)
  #define PULLDOWN              (1 << 4)
  #define PULLUP                (1 << 5)
  #define INVERT                (1 << 6)
  #define OUTPUT                (1 << 7)
  #define OPEN_DRAIN            (1 << 8)
  // INPUT may be removed as if it is not OUTPUT it is assumed to be INPUT
  // this will have almost no impact on the code
  // Do Not use INPUT
  #define INPUT                 (1 << 9) 
  #define AUX1                  (1 << 10)
  #define AUX2                  (1 << 11)
  #define NO_ASMI               (1 << 12)
  #define PM1                   (1 << 13)
  #define GPE                   (1 << 14)
  #define NO_ENABLE             (1L << 15) // do not enable in GPE0_EN or PM1_EN
                                          // when using EVENT_PME
#define EVENT_SOFTWARE_SMI      0x0C	// Software SMI
#define EVENT_PCI_TRAP          0x0D	// PCI trap
#define EVENT_VIRTUAL_REGISTER  0x0E	// Virtual register access
#define EVENT_NMI               0x0F	// NMI
#define EVENT_TIMER             0x10	// Millisecond timer
#define EVENT_DEVICE_TIMEOUT    0x11	// Device timeout
#define EVENT_SEMAPHORE         0x12	// ACPI global lock
#define EVENT_VBLANK            0x13    // Vertical blank
#define EVENT_A20               0x14	// A20 mask toggled
#define EVENT_SMB               0x15	// SMB Controller
#define EVENT_RTC               0x16	// RTC Alarm
#define EVENT_THERMAL           0x17    // THRM pin
#define EVENT_LPC               0x18    // Low Pin Count bus
#define EVENT_UART              0x19
#define EVENT_BLOCKIO           0x1A
#define EVENT_PWM               0x1B
#define MAX_EVENT               EVENT_PWM

// Flags for event registration
#define WRITES_ONLY            (1L << 16)
#define READS_ONLY             (1L << 17)
#define GLIU_ID                (1L << 19)
#define NOT_GLIU0              (1L << 20)
#define NOT_GLIU1              (1L << 21)
#define NOT_GLIU2              (1L << 22)
#define ALL_GLIUS              (NOT_GLIU0 | NOT_GLIU1 | NOT_GLIU2)
// Flags used for EVENT_TIMER must be >= bit 24
#define ONE_SHOT               (1L << 24)
#define FOR_STANDBY            (1L << 25)


//*********************************************************************
//			Resources
//*********************************************************************
#define RESOURCE_MEMORY        0		// Physical Memory
#define RESOURCE_MMIO          1		// Memory mapped I/O
#define RESOURCE_IO            2		// I/O space
#define RESOURCE_SCIO          3		// Swiss-cheese I/O
#define RESOURCE_GPIO          4		// General-purpose I/O pin
#define RESOURCE_IRQ           5		// IRQ


  
//*********************************************************************
//			Macros
//*********************************************************************

#define SYS_GET_NEXT_MSG(p)                 sys_get_next_msg(p)
#define SYS_QUERY_MSG_QUEUE(p)              sys_query_msg_queue(p)
#define SYS_UNREGISTER_EVENT(e, p1, p2)     sys_register_event(e, p1, p2, UNREGISTER_PRIORITY)
#define SYS_REGISTER_EVENT(e, p1, p2, p)    sys_register_event(e, p1, p2, p)
#define SYS_PASS_EVENT(e, p1, p2, p3) 		 // no longer needed
#define SYS_VSM_PRESENT(vsm)                sys_vsm_present(vsm)
#define SYS_YIELD_CONTROL(p1)               sys_yield_control(p1)
#define SYS_SW_INTERRUPT(interrupt, regs)   sys_software_interrupt(interrupt, regs)
#define SYS_BROADCAST_MSG(msg, p, vsm)      sys_broadcast_msg(msg, p, vsm)
#define SYS_GET_SYSTEM_INFO(buffer)         sys_get_system_info(buffer)
#define SYS_REPORT_ERROR(err, info1, info2) sys_report_error(err, info1, info2)
#define SYS_GENERATE_IRQ(irq)               sys_generate_IRQ(irq)
#define SYS_UNLOAD_VSM()                    sys_unload_vsm()
#define SYS_LOGICAL_TO_PHYSICAL(addr)       sys_logical_to_physical(addr)
#define SYS_ALLOCATE_RESOURCE(f,p,q,r,s)    sys_resource(f, p, q, r, s)
#define SYS_DEALLOCATE_RESOURCE(f,p,q,r,s)  sys_resource((UCHAR)(f|0x80), p, q, r, s)
#define SYS_MBUS_DESCRIPTOR(addr, p)        sys_mbus_descriptor(addr, p, 0)
#define SYS_IO_DESCRIPTOR(addr, p)          sys_mbus_descriptor(addr, p, 3)
#define SYS_LOOKUP_DEVICE(id, i)            sys_lookup_device(id, i)
#define SYS_SAVE_STATE(buffer)              sys_state(0, buffer)
#define SYS_RESTORE_STATE(buffer)           sys_state(1, buffer)
#define SYS_SET_DECODE(addr, flag)          sys_address_decode(addr, flag)
#define SYS_MAP_IRQ(Source, Irq)            sys_map_irq(Source, Irq)
#define SYS_RETURN_RESULT(Data)             sys_return_result(Data)
#define SYS_DUPLICATE_VSM(MemModel)         sys_duplicate_vsm(MemModel)

#define READ_PCI_BYTE(addr)                 read_PCI_byte(addr)
#define READ_PCI_WORD(addr)                 read_PCI_word(addr)
#define READ_PCI_DWORD(addr)                read_PCI_dword(addr)
#define WRITE_PCI_BYTE(addr, data)          write_PCI_byte(addr, data)
#define WRITE_PCI_WORD(addr, data)          write_PCI_word(addr, data)
#define WRITE_PCI_DWORD(addr, data)         write_PCI_dword(addr, data)

#define WRITE_PCI_BYTE_NO_TRAP(addr, data)  write_PCI_no_trap(addr, (ULONG)data, BYTE_IO)
#define WRITE_PCI_WORD_NO_TRAP(addr, data)  write_PCI_no_trap(addr, (ULONG)data, WORD_IO)
#define WRITE_PCI_DWORD_NO_TRAP(addr, data) write_PCI_no_trap(addr, data, DWORD_IO)
#define READ_PCI_BYTE_NO_TRAP(addr)         ((UCHAR)read_PCI_no_trap(addr, BYTE_IO))
#define READ_PCI_WORD_NO_TRAP(addr)         ((USHORT)read_PCI_no_trap(addr, WORD_IO))
#define READ_PCI_DWORD_NO_TRAP(addr)        read_PCI_no_trap(addr, DWORD_IO)

#define WRITE_MEMORY(addr, data)            write_flat(addr, data)
#define READ_MEMORY(addr)                   read_flat(addr)

#define ENTER_CRITICAL_SECTION              EnterCriticalSection();
#define EXIT_CRITICAL_SECTION               ExitCriticalSection();



void __pascal sys_register_event(EVENT, ULONG, ULONG, USHORT);
void __pascal sys_software_interrupt(USHORT, INT_REGS *);
void __pascal sys_broadcast_msg(MSG, void *, USHORT);
void __pascal sys_yield_control(ULONG);
void __pascal sys_get_system_info(void *);
void __pascal sys_generate_IRQ(USHORT);
void __pascal sys_state(USHORT, void *);
void __pascal sys_address_decode(USHORT, USHORT);
void __pascal sys_map_irq(UCHAR, UCHAR); 
void __pascal sys_return_result(ULONG);
void __pascal sys_get_descriptor(USHORT, void *);
void __pascal sys_set_descriptor(USHORT, void *);
void __pascal sys_set_header_data(USHORT, ULONG);
void __pascal sys_set_register(USHORT, ULONG);
void __pascal sys_set_virtual_register(USHORT, USHORT);
void __pascal sys_report_error(USHORT, ULONG, ULONG);

void __pascal write_PCI_byte(ULONG, UCHAR);
void __pascal write_PCI_word(ULONG, USHORT);
void __pascal write_PCI_dword(ULONG, ULONG);
void __pascal write_PCI_no_trap(ULONG, ULONG, USHORT);

void EnterCriticalSection(void);
void ExitCriticalSection(void);
void sys_fast_path_return(void);
void sys_unload_vsm(void);
void __pascal sys_duplicate_vsm(USHORT);

void __pascal write_flat(ULONG, ULONG);
ULONG __pascal read_flat(ULONG);
UCHAR  __pascal sys_vsm_present(UCHAR);
USHORT __pascal sys_get_virtual_register(USHORT);
ULONG  __pascal sys_get_header_data(USHORT);
ULONG  __pascal sys_get_register(USHORT);
UCHAR  __pascal read_PCI_byte(ULONG);
USHORT __pascal read_PCI_word(ULONG);
ULONG  __pascal read_PCI_dword(ULONG);
ULONG  __pascal read_PCI_no_trap(ULONG, USHORT);
ULONG  __pascal sys_logical_to_physical(void *);
ULONG  __pascal sys_resource(UCHAR, USHORT, ULONG, USHORT, USHORT);
ULONG  __pascal sys_mbus_descriptor(USHORT, ULONG *, USHORT);
ULONG  __pascal sys_lookup_device(USHORT, USHORT);
MSG    sys_get_next_msg(void *);
MSG    sys_query_msg_queue(void *);

// Macros for use by VSMs to access the non-SMM context
#define SET_HEADER_DATA(reg, data)   sys_set_header_data(reg, data)
#define GET_HEADER_DATA(reg)         (ULONG)sys_get_header_data(reg)
#define GET_DESCRIPTOR(reg, buffer)  sys_get_descriptor(reg, buffer);
#define SET_DESCRIPTOR(reg, buffer)  sys_set_descriptor(reg, buffer);
#define GET_REGISTER(reg)            (ULONG)sys_get_register(reg)
#define SET_REGISTER(reg, data)      sys_set_register(reg, data)
#define SET_EAX(data)                SET_REGISTER(R_EAX, (ULONG) (data))
#define SET_AX(data)                 SET_REGISTER(R_AX,  (USHORT)(data))
#define SET_AL(data)                 SET_REGISTER(R_AL,  (UCHAR) (data))
#define SET_AH(data)                 SET_REGISTER(R_AH,  (UCHAR) (data))
#define SET_EFLAGS(data)             SET_HEADER_DATA(R_EFLAGS, data)
#define GET_EAX()                    ((ULONG) GET_REGISTER(R_EAX))
#define GET_AX()                     ((USHORT)GET_REGISTER(R_AX))
#define GET_AL()                     ((UCHAR) GET_REGISTER(R_AL))
#define GET_AH()                     ((UCHAR) GET_REGISTER(R_AH))
#define GET_EFLAGS()                 (GET_HEADER_DATA(R_EFLAGS))


// Macros for accessing virtual registers
#define GET_VIRTUAL_REGISTER(reg)          (USHORT)sys_get_virtual_register(reg)
#define SET_VIRTUAL_REGISTER(reg, data)    sys_set_virtual_register(reg, data)


//*********************************************************************
//			Error Codes
//*********************************************************************

#define ERR_UNDEF_EVENT		1		// Attempt to register an undefined event
//#define ERR_SCHEDULER		2		// Scheduler error
#define ERR_BAD_PARAMETER		3		// Illegal system call parameter
#define ERR_RESOURCE_CONFLICT	4		// Multiple VSMs requested conflicting resources
#define ERR_UNHANDLED_EVENT	5		// An event occurred that no VSM handled
#define ERR_INVALID_EVENT		6		// SysMgr attempted to send an invalid event
//#define ERR_TIME_LIMIT		7		// A VSM exceeded its allotted runtime
#define ERR_REGISTRATION_LOST	8		// A registered event is lost due to too many event registrations
#define ERR_HW_MISMATCH		9		// A VSM could not find the correct hardware (e.g. OHCI)
#define ERR_BAD_DESCRIPTOR		0x0A	// A descriptor in a VSM header is not valid
//#define ERR_MSG_QUEUE_FULL	0x0B	// A VSM's message queue is full
//#define ERR_MULTIPLE_EVENT   0x0C	// A VSM attempted to register the same event twice
#define ERR_UNREGISTRATION     0x0D	// A VSM attempted to unregister an event for which it was not registered
#define ERR_UNREGISTERED_EVENT 0x0E	// An event occurred for which no VSM is registered
#define ERR_MISALIGNED_IO		0x0F	// An misaligned I/O access occurred
//#define ERR_UNEXPECTED_EVENT 0x10    // A handler routine was passed an unexpected SMI event
//#define ERR_BAD_VSM			0x11	// A VSM header doesn't look right (no signature, etc.)
#define ERR_NESTED_ACCESS		0x12	// A VSM directly accessed a ACPI or virtual register
//#define ERR_BAD_MSG			0x13	// An attempt was made to send an illegal message code
//#define ERR_UNHANDLED_VIRTUAL 0x14	// An access was made by a VSM to an unhandled virtual register
#define ERR_BAD_INTERRUPT      0x15    // A VSM attempted to call an illegal INT vector
#define ERR_ILLEGAL_MACRO      0x16    // Illegal use of GET/SET_REGISTER or GET/SET_HEADER_DATA macros
#define ERR_UNDEF_SYS_CALL		0x17	// Undefined system call
//#define ERR_BAD_POWER_STATE	0x18	// Invalid power state
#define ERR_BAD_VR_ACCESS      0x19	// Access to undefined VR class by an application
#define ERR_UNDEF_VIRTUAL_REG	0x1A	// Access to undefined VR class by a VSM
//#define ERR_UNSUPPORTED_CHIPSET 0x1B // This chipset is not supported
#define ERR_PCI_TRAP           0x1C    // A VSM requested an unsupported PCI trap
#define ERR_RESOURCE_NOT_FOUND 0x1D    // A VSM requested an unsupported resource
#define ERR_NO_MORE_DESCRIPTORS 0x1E   // Out of MBIU descriptors
//#define ERR_INTERNAL_ERROR    0x1F   // System error, e.g. inconsistent data structure
#define ERR_DATA_STRUCTURE      0x20	// A system structure is too small






// Used as 2nd parameter to SYS_SET_DECODE macro:
#define POSITIVE_DECODE			1
#define SUBTRACTIVE_DECODE		0




//****************************************************************************************************
#define FROM_HEADER            0x2000
#define WORD_SIZE              0x4000
#define DWORD_SIZE             0x8000




// Field names for GET_REGISTER and SET_REGISTER macros
// These offsets must match the register order on the stack (PUSHAD)

#define R_DI			 0   + WORD_SIZE 
#define R_EDI			 0   + DWORD_SIZE
				
#define R_SI			 4   + WORD_SIZE
#define R_ESI			 4   + DWORD_SIZE

#define R_BP			 8   + WORD_SIZE
#define R_EBP			 8   + DWORD_SIZE
				
#define R_BL			16
#define R_BH			R_BL + 1
#define R_BX			R_BL + WORD_SIZE
#define R_EBX			R_BL + DWORD_SIZE

#define R_DL			20
#define R_DH			R_DL + 1
#define R_DX			R_DL + WORD_SIZE
#define R_EDX			R_DL + DWORD_SIZE
		
#define R_CL			24
#define R_CH			R_CL + 1
#define R_CX			R_CL + WORD_SIZE
#define R_ECX			R_CL + DWORD_SIZE

#define R_AL			28
#define R_AH			R_AL + 1
#define R_AX			R_AL + WORD_SIZE
#define R_EAX			R_AL + DWORD_SIZE

#define R_SP			32   + WORD_SIZE
#define R_ESP			32   + DWORD_SIZE


// Segment registers
// NOTE: offset points to .selector field
#define DESCRIPTOR_SIZE 10 // sizeof(Descriptor)
#define R_SS			36-2 + DESCRIPTOR_SIZE + WORD_SIZE
#define R_DS			R_SS + DESCRIPTOR_SIZE
#define R_ES			R_DS + DESCRIPTOR_SIZE
#define R_FS			R_ES + DESCRIPTOR_SIZE
#define R_GS			R_FS + DESCRIPTOR_SIZE

// Fields from SMM header
#define WRITE_DATA		0x08 + DWORD_SIZE + FROM_HEADER
#define IO_ADDRESS		0x0C + WORD_SIZE  + FROM_HEADER
#define DATA_SIZE		0x0E              + FROM_HEADER
#define SMM_FLAGS		0x10 + WORD_SIZE  + FROM_HEADER
#define CS_LIMIT		0x14 + DWORD_SIZE + FROM_HEADER
#define CS_BASE	   	0x18 + DWORD_SIZE + FROM_HEADER
#define CS_SELECTOR	0x1C + WORD_SIZE  + FROM_HEADER
#define CS_ATTR		0x1E + WORD_SIZE  + FROM_HEADER 
#define R_CS		0x1C + WORD_SIZE  + FROM_HEADER
#define R_IP		0x20 + WORD_SIZE  + FROM_HEADER
#define R_EIP		0x20 + DWORD_SIZE + FROM_HEADER
#define CURRENT_EIP  	0x24 + DWORD_SIZE + FROM_HEADER
#define R_CR0		0x28 + DWORD_SIZE + FROM_HEADER
#define R_EFLAGS   	0x2C + DWORD_SIZE + FROM_HEADER
  #define EFLAGS_CF    0x0001
  #define EFLAGS_ZF    0x0040
  #define EFLAGS_IF	0x0200
  #define EFLAGS_DF    0x0400
#define R_DR7 	   	0x30 + DWORD_SIZE + FROM_HEADER






typedef struct {
  ULONG  Chipset_Base;
  USHORT Chipset_ID;
  USHORT Chipset_Rev;
  USHORT CPU_ID;
  USHORT CPU_Revision;
  USHORT CPU_MHz;
  ULONG  SystemMemory;		// Units = bytes
  ULONG  VSA_Location;		// Physical location
  USHORT VSA_Size;			// Units = KB
  USHORT PCI_MHz;
  USHORT DRAM_MHz;
} Hardware;




