SMPV211 - Appendix A: Difference between revisions
Appearance
Created page with "The following is the source code for an actual PSD." |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
{{SMPV211}} | |||
The following is the source code for an actual PSD. | The following is the source code for an actual PSD. | ||
==Main program== | |||
<PRE> | |||
#define INCL_ERROR_H | |||
#include <os2.h> | |||
#include <psd.h> | |||
#include <alr.h> | |||
extern ulong_t RMP2Available(void); | |||
/* | |||
* Global Variables | |||
*/ | |||
P_F_2 router = 0; | |||
char *pParmString = 0; | |||
int IODelayCount = 30; | |||
PLMA *pPSDPLMA = 0; | |||
ulong_t sizePLMA = 0; | |||
/*** Disable - Disable interrupts | |||
* | |||
* This function disables interrupts, and returns | |||
* the original state of eflags | |||
* | |||
* ENTRY None | |||
* | |||
* EXIT EFLAGS | |||
* | |||
*/ | |||
ulong_t Disable(void) { | |||
ulong_t eflags; | |||
_asm { | |||
pushfd | |||
pop eax | |||
mov eflags,eax | |||
cli | |||
}; | |||
return (eflags); | |||
} | |||
/*** Enable - Restore the state of eflags | |||
* | |||
* This function restores the state of eflags | |||
* | |||
* ENTRY eflags - state of eflags to restore | |||
* | |||
* EXIT None | |||
* | |||
*/ | |||
void Enable(ulong_t eflags) { | |||
_asm { | |||
push eflags | |||
popfd | |||
}; | |||
return; | |||
} | |||
/*** InByte - Read a byte from a port | |||
* | |||
* This function reads a byte from a specified port | |||
* | |||
* ENTRY port - port number to read from | |||
* | |||
* EXIT data read | |||
* | |||
*/ | |||
ulong_t InByte(ulong_t port) { | |||
ulong_t data; | |||
_asm { | |||
mov dx,port | |||
in al,dx | |||
movzx eax,al | |||
mov data,eax | |||
}; | |||
return (data); | |||
} | |||
/*** OutByte - Writes a byte to a port | |||
* | |||
* This function writes a byte to a specified port | |||
* | |||
* ENTRY port - port number to read from | |||
* data - data to write | |||
* | |||
* EXIT None | |||
* | |||
*/ | |||
void OutByte(ulong_t port, ulong_t data) { | |||
_asm { | |||
mov dx,port | |||
mov al,byte ptr data | |||
out dx,al | |||
}; | |||
return; | |||
} | |||
/*** SendEOI - Send an end of interrupt | |||
* | |||
* This function sends an end of interrupt. | |||
* | |||
* ENTRY irq - irq level to end | |||
* | |||
* EXIT None | |||
* | |||
*/ | |||
ulong_t SendEOI(ulong_t irq) { | |||
ulong_t flags; | |||
flags = Disable(); | |||
if (irq < NUM_IRQ_PER_PIC) | |||
OutByte(PIC1_PORT0, OCW2_NON_SPECIFIC_EOI); | |||
else { | |||
OutByte(PIC2_PORT0, OCW2_NON_SPECIFIC_EOI); | |||
IODelay; | |||
OutByte(PIC1_PORT0, OCW2_NON_SPECIFIC_EOI); | |||
} | |||
Enable(flags); | |||
} | |||
/*** WHO_AM_I - Returns the current processor number | |||
* | |||
* This function returns the current processor number | |||
* | |||
* ENTRY NONE | |||
* | |||
* EXIT Current processor number (P1 or P2) | |||
* | |||
*/ | |||
ulong_t WHO_AM_I (void) { | |||
return(InByte(WHO_AM_I_PORT)); | |||
} | |||
/*** IPIPresent - Detects the presence of an IPI | |||
* | |||
* This function detects the presence of an IPI on the current | |||
* processor | |||
* | |||
* ENTRY None | |||
* | |||
* EXIT NO_ERROR - IPI present | |||
* -1 - IPI not present | |||
* | |||
*/ | |||
ulong_t IPIPresent (void) { | |||
ulong_t rc = 0; | |||
struct control_s ctrl; | |||
ulong_t port; | |||
port = pPSDPLMA->controlport; | |||
ctrl.b_all = InByte(port); | |||
if (ctrl.b_387err) | |||
{ | |||
OutByte (0xf0, 0); // The busy latch for NPX must be cleared. | |||
// When we call the interrupt handler | |||
// (w/ Call16bitDD int.asm), ints. are 1st enabled. | |||
// If the busy latch is not cleared, then we | |||
// will take this interrupt in again and will | |||
// eventually nest until the interrupt stack is | |||
// overrun. | |||
rc = -1; | |||
} | |||
return (rc); | |||
} | |||
/*** Install - Install PSD | |||
* | |||
* This function checks to see if this PSD is installable on the | |||
* current platform. | |||
* | |||
* ENTRY pinstall - pointer to an INSTALL structure | |||
* | |||
* EXIT NO_ERROR - PSD Installed | |||
* -1 - PSD not valid for this platform | |||
* | |||
*/ | |||
ulong_t Install(INSTALL *pinstall) { | |||
VMALLOC vmac; | |||
int i; | |||
char *p; | |||
ulong_t rc = 0; | |||
char ALR_String = "PROVEISA"; | |||
// _asm int 3; | |||
/* Setup Global variables */ | |||
router = pinstall->pPSDHlpRouter; | |||
pParmString = pinstall->pParmString; | |||
pPSDPLMA = (void *)pinstall->pPSDPLMA; | |||
sizePLMA = pinstall->sizePLMA; | |||
vmac.addr = BIOS_SEG << 4; | |||
vmac.cbsize = _64K; | |||
vmac.flags = VMALLOC_PHYS; | |||
/* Map BIOS area */ | |||
if ((rc = PSDHelp(router, PSDHLP_VMALLOC, &vmac)) == NO_ERROR) { | |||
/* Check for ALR string */ | |||
p = (char *)vmac.addr + ALR_STRING_OFFSET; | |||
for (i = 0; ALR_String i != '\0'; i++) | |||
if (p i != ALR_String i) { | |||
rc = -1; | |||
break; | |||
} | |||
/* Free BIOS mapping */ | |||
PSDHelp(router, PSDHLP_VMFREE, vmac.addr); | |||
} | |||
return (rc); | |||
} | |||
/*** DeInstall - DeInstall PSD | |||
* | |||
* This function deinstalls the PSD. | |||
* | |||
* ENTRY None | |||
* | |||
* EXIT NO_ERROR | |||
* | |||
*/ | |||
ulong_t DeInstall(void) { | |||
return (NO_ERROR); | |||
} | |||
/*** Init - Initialize the PSD | |||
* | |||
* This function initializes the PSD. | |||
* | |||
* ENTRY None | |||
* | |||
* EXIT NO_ERROR - PSD initialized | |||
* -1 - PSD not initialized | |||
* | |||
*/ | |||
ulong_t Init(INIT *pinit) { | |||
struct control_s ctrl; | |||
SET_IRQ set_irq; | |||
/* Initialize P1 control port */ | |||
ctrl.b_all = 0; | |||
ctrl.b_cacheon = 1; | |||
OutByte(P1_PROCESSOR_CONTROL_PORT, ctrl.b_all); | |||
/* Setup P2 interrupt vector */ | |||
OutByte(P2_INTERRUPT_VECTOR_CONTROL_PORT, IPI_VECTOR); | |||
/* Setup IPI info */ | |||
set_irq.irq = 13; | |||
set_irq.flags = IRQf_IPI; | |||
set_irq.vector = 0; | |||
set_irq.handler = (P_F_2)IPIPresent; | |||
PSDHelp(router, PSDHLP_SET_IRQ, &set_irq); | |||
/* Fill init structure */ | |||
pinit->flags = INIT_EOI_IRQ13_ON_CPU0; //76422 | |||
pinit->version = VERSION; | |||
return (NO_ERROR); | |||
} | |||
/*** ProcInit - Processor initialization | |||
* | |||
* This function initializes per processor items. | |||
* | |||
* NOTE: This function is called once on each processor | |||
* in the system. | |||
* | |||
* ENTRY None | |||
* | |||
* EXIT NO_ERROR - Processor initialized | |||
* -1 - Processor not initialized | |||
* | |||
*/ | |||
ulong_t ProcInit(void) { | |||
if (WHO_AM_I() == P1) { | |||
pPSDPLMA->procnum = 0; | |||
pPSDPLMA->controlport = P1_PROCESSOR_CONTROL_PORT; | |||
} | |||
else { | |||
pPSDPLMA->procnum = 1; | |||
pPSDPLMA->controlport = P2_PROCESSOR_CONTROL_PORT; | |||
} | |||
return (NO_ERROR); | |||
} | |||
/*** StartProcessor - Start a processor | |||
* | |||
* This function starts a processor. | |||
* | |||
* ENTRY procnum - processor number to start (0-based) | |||
* | |||
* EXIT Return Code | |||
* | |||
*/ | |||
ulong_t StartProcessor(ulong_t procnum) { | |||
CALL_REAL_MODE rm; | |||
struct control_s ctrl; | |||
ulong_t rc = -1; | |||
if (procnum == 1) { | |||
rm.function = (ulong_t)&RMP2Available; | |||
rm.pdata = 0; | |||
rc = PSDHelp(router, PSDHLP_CALL_REAL_MODE, &rm); | |||
if (rc & P2_AVAILABLE) { | |||
/* Dispatch P2 */ | |||
ctrl.b_all = 0; | |||
ctrl.b_cacheon = 1; | |||
OutByte(P2_PROCESSOR_CONTROL_PORT, ctrl.b_all); | |||
rc = NO_ERROR; | |||
} | |||
else | |||
rc = -1; | |||
} | |||
return (rc); | |||
} | |||
/*** GetNumOfProcs - Get number of processors | |||
* | |||
* This function gets the number of processors which exist on this | |||
* platform. | |||
* | |||
* ENTRY None | |||
* | |||
* EXIT Number of processors | |||
* | |||
*/ | |||
ulong_t GetNumOfProcs(void) { | |||
ulong_t cprocs = 2; | |||
return (cprocs); | |||
} | |||
/*** GenIPI - Generate an inter-processor interrupt | |||
* | |||
* This function generates an IPI. | |||
* | |||
* ENTRY procnum - processor number to interrupt (0-based) | |||
* | |||
* EXIT NO_ERROR | |||
* | |||
*/ | |||
ulong_t GenIPI(ulong_t procnum) { | |||
struct control_s ctrl; | |||
ulong_t port; | |||
if (procnum == 0) | |||
port = P1_PROCESSOR_CONTROL_PORT; | |||
else | |||
port = P2_PROCESSOR_CONTROL_PORT; | |||
ctrl.b_all = InByte(port); | |||
ctrl.b_pint = 1; | |||
OutByte(port, ctrl.b_all); | |||
return (NO_ERROR); | |||
} | |||
/*** EndIPI - End an inter-processor interrupt | |||
* | |||
* This function ends an IPI. | |||
* | |||
* ENTRY procnum - processor number to end interrupt on (0-based) | |||
* | |||
* EXIT NO_ERROR | |||
* | |||
*/ | |||
ulong_t EndIPI(ulong_t procnum) { | |||
struct control_s ctrl; | |||
ulong_t port; | |||
if (procnum == 0) | |||
port = P1_PROCESSOR_CONTROL_PORT; | |||
else | |||
port = P2_PROCESSOR_CONTROL_PORT; | |||
ctrl.b_all = InByte(port); | |||
ctrl.b_pint = 0; | |||
OutByte(port, ctrl.b_all); | |||
if (procnum == 0) | |||
SendEOI(IPI_IRQ); | |||
return (NO_ERROR); | |||
} | |||
</PRE> | |||
==Entry stub== | |||
<PRE> | |||
.386 | |||
_TEXT SEGMENT | |||
ASSUME CS:_TEXT,DS:NOTHING | |||
PUBLIC _RMP2Available | |||
_RMP2Available PROC | |||
mov ah,0E2h | |||
mov al,0 | |||
int 15h | |||
movzx eax,ax | |||
retf | |||
_RMP2Available ENDP | |||
_TEXT ENDS | |||
END | |||
</PRE> | |||
==PSD.H== | |||
<PRE> | |||
/*static char *SCCSID = "@(#)psd.h 1.0 93/18/08";*/ | |||
// XLATOFF | |||
#ifndef ulong_t | |||
typedef unsigned long ulong_t; | |||
typedef unsigned short ushort_t; | |||
typedef unsigned char uchar_t; | |||
#endif | |||
typedef int (*P_F_1)(ulong_t arg); | |||
typedef int (*P_F_2)(ulong_t arg1, ulong_t arg2); | |||
#define PSDHelp(router, function, arg) \ | |||
((*router)((function), (ulong_t)(arg))) | |||
// XLATON | |||
/* ASM | |||
P_F_1 struc | |||
dd ? | |||
P_F_1 ends | |||
P_F_2 struc | |||
dd ? | |||
P_F_2 ends | |||
*/ | |||
#define WARM_REBOOT_VECTOR_SEG 0x40 | |||
#define WARM_REBOOT_VECTOR_OFF 0x67 | |||
/* PSD Info structure */ | |||
typedef struct info_s { /* psd */ | |||
ulong_t flags; /* PSD flags */ | |||
ulong_t version; /* PSD version */ | |||
ulong_t hmte; /* MTE handle of PSD */ | |||
uchar_t *pParmString; /* Pointer to ASCIIZ PSD parameter*/ | |||
ulong_t IRQ_IPI; /* IRQ for IPI */ | |||
ulong_t IRQ_LSI; /* IRQ for LSI */ | |||
ulong_t IRQ_SPI; /* IRQ for SPI */ | |||
} PSDINFO; | |||
/* PSD flags definition */ | |||
#define PSD_ADV_INT_MODE 0x20000000 /* PSD is in adv int mode #81531 */ | |||
#define PSD_INSTALLED 0x40000000 /* PSD has been installed */ | |||
#define PSD_INITIALIZED 0x80000000 /* PSD has been initialized */ | |||
/* PSD function numbers-structures */ | |||
#define PSD_INSTALL 0x00000000 /* Install PSD */ | |||
typedef struct install_s { /* install */ | |||
P_F_2 pPSDHlpRouter; /* Address of PSDHlpRouter */ | |||
char *pParmString; /* Pointer to parameter string */ | |||
void *pPSDPLMA; /* Pointer to PSD's PLMA */ | |||
ulong_t sizePLMA; /* Size of PLMA in bytes */ | |||
} INSTALL; | |||
#define PSD_DEINSTALL 0x00000001 /* DeInstall PSD */ | |||
#define PSD_INIT 0x00000002 /* Initialize PSD */ | |||
typedef struct init_s { /* init */ | |||
ulong_t flags; /* Init flags */ | |||
ulong_t version; /* PSD Version number */ | |||
} INIT; | |||
#define INIT_GLOBAL_IRQ_ACCESS 0x00000001 /* Platform has global IRQ access */ | |||
#define INIT_USE_FPERR_TRAP 0x00000002 /* Use Trap 16 to report FP err's */ | |||
#define INIT_EOI_IRQ13_ON_CPU0 0x00000004 /* eoi IRQ 13 only if on cpu 0 */ | |||
#define INIT_TIMER_CPU0 0x00000008 /* system timer is on CPU 0 */ | |||
#define PSD_PROC_INIT 0x00000003 /* Initialize processor */ | |||
#define PSD_START_PROC 0x00000004 /* Start processor */ | |||
#define PSD_GET_NUM_OF_PROCS 0x00000005 /* Get number of processors */ | |||
#define PSD_GEN_IPI 0x00000006 /* Generate an IPI */ | |||
#define PSD_END_IPI 0x00000007 /* End an IPI */ | |||
#define PSD_PORT_IO 0x00000008 /* Port I/O */ | |||
typedef struct port_io_s { /* port_io */ | |||
ulong_t port; /* Port number to access */ | |||
ulong_t data; /* Data read, or data to write */ | |||
ulong_t flags; /* IO Flags */ | |||
} PORT_IO; | |||
#define IO_READ_BYTE 0x0000 /* Read a byte from the port */ | |||
#define IO_READ_WORD 0x0001 /* Read a word from the port */ | |||
#define IO_READ_DWORD 0x0002 /* Read a dword from the port */ | |||
#define IO_WRITE_BYTE 0x0003 /* Write a byte to the port */ | |||
#define IO_WRITE_WORD 0x0004 /* Write a word to the port */ | |||
#define IO_WRITE_DWORD 0x0005 /* Write a dword to the port */ | |||
#define IO_FLAGMASK 0x0007 /* Flag mask */ | |||
#define PSD_IRQ_MASK 0x00000009 /* Mask/Unmask IRQ levels */ | |||
typedef struct psd_irq_s { /* psd_irq */ | |||
ulong_t flags; /* IRQ flags */ | |||
ulong_t data; /* IRQ data */ | |||
/* depending on type of irq */ | |||
/* operation, the data field */ | |||
/* can contain any of the */ | |||
/* following info: */ | |||
/* 1) Mask or UNMasking data */ | |||
/* 2) IRR or ISR reg values */ | |||
/* 3) IRQ # for EOI operations */ | |||
ulong_t procnum; /* Processor number */ | |||
} PSD_IRQ; | |||
#define PSD_IRQ_REG 0x0000000A /* Access IRQ related regs */ | |||
#define PSD_IRQ_EOI 0x0000000B /* Issue an EOI */ | |||
#define IRQ_MASK 0x00000001 /* Turn on IRQ mask bits */ | |||
#define IRQ_UNMASK 0x00000002 /* Turn off IRQ mask bits */ | |||
#define IRQ_GETMASK 0x00000004 /* Get IRQ mask bits */ | |||
#define IRQ_NEWMASK 0x00000010 /* Set and/or Reset all masks */ | |||
#define IRQ_READ_IRR 0x00000100 /* Read the IRR reg */ | |||
#define IRQ_READ_ISR 0x00000200 /* Read the ISR reg */ | |||
#define PSD_APP_COMM 0x0000000C /* PSD/APP Communication */ | |||
#define PSD_SET_ADV_INT_MODE 0x0000000D /* Set advanced int mode */ | |||
#define PSD_SET_PROC_STATE 0x0000000E /* Set proc state; idle, or busy */ | |||
#define PROC_STATE_IDLE 0x00000000 /* Processor is idle */ | |||
#define PROC_STATE_BUSY 0x00000001 /* Processor is busy */ | |||
#define PSD_QUERY_SYSTEM_TIMER 0x0000000F /* Query Value of System Timer 0 */ | |||
typedef struct psd_qrytmr_s { /* psd_qrytmr */ | |||
ulong_t qw_ulLo_psd; /* Timer count */ | |||
ulong_t qw_ulHi_psd; /* Timer count */ | |||
ulong_t pqwTmr; /* 16:16 ptr to qwTmr */ | |||
} PSD_QRYTMR; | |||
#define PSD_SET_SYSTEM_TIMER 0x00000010 /* Set System Timer 0 counter */ | |||
typedef struct psd_settmr_s { /* psd_settmr */ | |||
ulong_t NewRollOver; /* NewRollover*/ | |||
ulong_t pqwTmrRollover; /* 16:16 ptr to qwTmrRollover */ | |||
} PSD_SETTMR; | |||
/* PSD helper function numbers-structures */ | |||
#define PSDHLP_VMALLOC 0x00000000 /* Allocate memory */ | |||
typedef struct vmalloc_s { /* vmalloc */ | |||
ulong_t addr; /* Physical address to map */ | |||
/* if VMALLOC_PHYS */ | |||
/* Lin addr to alloc at */ | |||
/* if VMALLOC_LOCSPECIFIC */ | |||
/* on return, addr of allocation */ | |||
ulong_t cbsize; /* Size of mapping in bytes */ | |||
ulong_t flags; /* Allocation flags */ | |||
} VMALLOC; | |||
#define VMALLOC_FIXED 0x00000001 /* Allocate resident memory */ | |||
#define VMALLOC_CONTIG 0x00000002 /* Allocate contiguous memory */ | |||
#define VMALLOC_LOCSPECIFIC 0x00000004 /* Alloc at a specific lin address */ | |||
#define VMALLOC_PHYS 0x00000008 /* Map physical address */ | |||
#define VMALLOC_1M 0x00000010 /* Allocate below 1M */ | |||
#define VMALLOC_FLAGMASK 0x0000001f /* Valid flag mask */ | |||
#define PSDHLP_VMFREE 0x00000001 /* Free memory */ | |||
#define PSDHLP_SET_IRQ 0x00000002 /* Set up an IRQ */ | |||
typedef struct set_irq_s { /* set_irq */ | |||
ushort_t irq; /* IRQ level */ | |||
ushort_t flags; /* Set IRQ flags */ | |||
ulong_t vector; /* IRQ interrupt vector */ | |||
P_F_2 handler; /* IRQ handler */ | |||
} SET_IRQ; | |||
#define IRQf_IPI 0x0020 /* IRQ for IPI */ | |||
#define IRQf_LSI 0x0040 /* IRQ for LSI */ | |||
#define IRQf_SPI 0x0080 /* IRQ for SPI */ | |||
#define PSDHLP_CALL_REAL_MODE 0x00000003 /* Call a function in real mode */ | |||
typedef struct call_real_mode_s { /* call_real_mode */ | |||
ulong_t function; /* Function address */ | |||
ulong_t pdata; /* Pointer to data area */ | |||
} CALL_REAL_MODE; | |||
#define PSDHLP_VMLINTOPHYS 0x00000004 /* Convert linear addr to phys */ | |||
#define PSDHLP_ADJ_PG_RANGES 0x00000005 /* Adjust page ranges */ | |||
typedef struct _pagerange_s { /* pagerange */ | |||
ulong_t lastframe; /* Last valid page in range */ | |||
ulong_t firstframe; /* First valid page in range */ | |||
}; | |||
typedef struct adj_pg_ranges_s{ /* adj_pg_ranges */ | |||
struct _pagerange_s *pprt; /* Pointer to page range table */ | |||
ulong_t nranges; /* Num of ranges in range table */ | |||
} ADJ_PG_RANGES; | |||
/* PSD function prototypes */ | |||
extern void PSDEnter (ulong_t function, ulong_t arg, P_F_2 altEntry); | |||
</PRE> | |||
==Specific header== | |||
<PRE> | |||
/* | |||
* Miscellaneous | |||
*/ | |||
#define VERSION 0x00000010 | |||
#define _64K (64 * 1024) | |||
#define BIOS_SEG 0xF000 | |||
#define ALR_STRING_OFFSET 0xEC47 | |||
#define P2_AVAILABLE 0x00008000 | |||
/* | |||
* PLMA structure | |||
*/ | |||
typedef struct plma_s { | |||
ulong_t procnum; /* Current processor number (0-based) */ | |||
ulong_t controlport; /* Control port for current processor */ | |||
} PLMA; | |||
/* | |||
* Generate delay between I/O instructions | |||
*/ | |||
#define IODelay {int i; for(i = 0; i < IODelayCount; i++); } | |||
/* | |||
* IPI info | |||
*/ | |||
#define IPI_IRQ 0x0d /* IRQ level for IPI */ | |||
#define IPI_VECTOR 0x75 /* Vector number for IPI */ | |||
/* | |||
* PIC Info | |||
*/ | |||
#define NUM_IRQ_PER_PIC 0x08 | |||
#define OCW2_NON_SPECIFIC_EOI 0x20 | |||
#define PIC1_PORT0 0x20 | |||
#define PIC1_PORT1 0x21 | |||
#define PIC2_PORT0 0xA0 | |||
#define PIC2_PORT1 0xA1 | |||
/* | |||
* The contents of the WHO_AM_I port (read-only) can be used | |||
* by code to determine which processor we are currently on | |||
*/ | |||
#define WHO_AM_I_PORT 0xC70 | |||
#define P1 0x00 | |||
#define P2 0xF0 | |||
/* | |||
* The processor control port contains the bits used to control | |||
* various functions of the associated processor | |||
*/ | |||
#define P1_PROCESSOR_CONTROL_PORT 0x0C6A | |||
#define P2_PROCESSOR_CONTROL_PORT 0xFC6A | |||
struct _b_control_s { | |||
ulong_t _reset:1, /* RESET - (Not implemented for P1) */ | |||
/* 1 = Resets processor */ | |||
_387pres:1, /* 387PRES - (Read only) */ | |||
/* 0 = 80387 is not installed */ | |||
/* 1 = 80387 is installed */ | |||
_cacheon:1, /* CACHEON - (Not implemented for P1) */ | |||
/* 0 = Disables cache */ | |||
/* 1 = Enables cache */ | |||
_mbusaccess:1, /* M Bus Access (Not implemented for P1) */ | |||
/* 0 = Allows the processor to gain */ | |||
/* control of the memory bus */ | |||
/* 1 = Prohibits the processor from gaining */ | |||
/* access to the memory bus. The */ | |||
/* processor can execute instructions */ | |||
/* from its cache; however, cache read */ | |||
/* misses, I/O, and writes cause the */ | |||
/* processor to cease executing */ | |||
/* instructions until the bit becomes */ | |||
/* a "0" */ | |||
_flush:1, /* FLUSH */ | |||
/* Writing a "1" to this bit followed by a "0" */ | |||
/* causes invalidation of all cache address */ | |||
/* information */ | |||
_387err:1, /* 387ERR */ | |||
/* 0 = No 80387 error */ | |||
/* 0 = An 80387 error has occurred. This bit */ | |||
/* must be cleared by software */ | |||
_pint:1, /* PINT */ | |||
/* A low-to-high transition of this bit causes */ | |||
/* an interrupt. This bit must be cleared by */ | |||
/* software, preferably by the interrupt service */ | |||
/* routine. On P2, the value stored in FC68h */ | |||
/* contains the interrupt number. P1 is always */ | |||
/* interrupted with IRQ13 */ | |||
_intdis:1, /* INTDIS */ | |||
/* When set to "1", this bit disables interrupts */ | |||
/* sent to the processor by way of the PINT bit. */ | |||
/* The PINT bit can still be changed when */ | |||
/* interrupts are disabled; however, the */ | |||
/* low-to-high transition is not seen by the */ | |||
/* processor until the INTDIS bit is made inactive */ | |||
_pad:24; | |||
}; | |||
struct _l_control_s { /* to treat control as an unsigned long */ | |||
unsigned long _long; | |||
}; | |||
union _control_u { | |||
struct _b_control_s b_control_s; | |||
struct _l_control_s l_control_s; | |||
}; | |||
struct control_s { | |||
union _control_u control_u; | |||
}; | |||
#define b_reset control_u.b_control_s._reset | |||
#define b_387pres control_u.b_control_s._387pres | |||
#define b_cacheon control_u.b_control_s._cacheon | |||
#define b_mbusaccess control_u.b_control_s._mbusaccess | |||
#define b_flush control_u.b_control_s._flush | |||
#define b_387err control_u.b_control_s._387err | |||
#define b_pint control_u.b_control_s._pint | |||
#define b_intdis control_u.b_control_s._intdis | |||
#define b_all control_u.l_control_s._long | |||
/* | |||
* The interrupt vector control port contains the 8-bit interrupt | |||
* number that is executed when the PINT bit transitions from "0" | |||
* to "1". This vector is only used for P2. P1 is always interrupted | |||
* with IRQ 13. | |||
*/ | |||
#define P2_INTERRUPT_VECTOR_CONTROL_PORT 0xFC68 | |||
/* | |||
* The following ports contain the EISA identification of the | |||
* system processor boards | |||
*/ | |||
#define COMPAQ_ID1 0x0000000E | |||
#define COMPAQ_ID2 0x00000011 | |||
#define P1_EISA_PRODUCT_ID_PORT1 0x0C80 /* Compressed COMPAQ ID - OEh */ | |||
#define P1_EISA_PRODUCT_ID_PORT2 0x0C81 /* 11h */ | |||
#define P1_EISA_PRODUCT_ID_PORT3 0x0C82 /* Product code for the proc board */ | |||
#define P1_EISA_PRODUCT_ID_PORT4 0x0C83 /* Revision number */ | |||
#define P2_EISA_PRODUCT_ID_PORT1 0xFC80 /* Compressed COMPAQ ID - OEh */ | |||
#define P2_EISA_PRODUCT_ID_PORT2 0xFC81 /* 11h */ | |||
#define P2_EISA_PRODUCT_ID_PORT3 0xFC82 /* Product code for the proc board */ | |||
#define P2_EISA_PRODUCT_ID_PORT4 0xFC83 /* Revision number */ | |||
/* | |||
* Any write to The RAM Relocation Register (memory mapped) | |||
* will flush the caches of both P1 and P2 | |||
*/ | |||
#define RAM_RELOCATION_REGISTER 0x80C00000 | |||
/* | |||
* The P1 Cache Control Register (memory mapped) | |||
*/ | |||
#define P1_CACHE_CONTROL_REGISTER 0x80C00002 | |||
struct p1cache_s { | |||
ulong_t _reserved1:6, | |||
_p1cc:1, /* P1 Cache Control */ | |||
/* 0 = Disables P1 cache */ | |||
/* 1 = Enables P1 cache */ | |||
_reserved2:9; | |||
}; | |||
/* | |||
* Expanision board control ports | |||
*/ | |||
#define P1_EISA_EXPANSION_BOARD_CONTROL 0x0C84 | |||
#define P2_EISA_EXPANSION_BOARD_CONTROL 0xFC84 | |||
</PRE> | |||
==Makefile == | |||
<PRE> | |||
# SCCSID = @(#)makefile 6.7 92/06/03 | |||
#/***********************************************************************/ | |||
#/* */ | |||
#/* PSD Name: ALR.PSD - ALR PSD */ | |||
#/* ----------------------------------- */ | |||
#/* */ | |||
#/* Source File Name: MAKEFILE */ | |||
#/* */ | |||
#/* Descriptive Name: MAKEFILE for the ALR PSD */ | |||
#/* */ | |||
#/* Function: */ | |||
#/* */ | |||
#/* */ | |||
#/*---------------------------------------------------------------------*/ | |||
#/* */ | |||
#/* Copyright (C) 1992 IBM Corporation */ | |||
#/* */ | |||
#/* DISCLAIMER OF WARRANTIES. The following enclosed code is */ | |||
#/* provided to you solely for the purpose of assisting you in */ | |||
#/* the development of your applications. The code is provided */ | |||
#/* "AS IS", without warranty of any kind. IBM shall not be liable */ | |||
#/* for any damages arising out of your use of this code, even if */ | |||
#/* they have been advised of the possibility of such damages. */ | |||
#/* */ | |||
#/*---------------------------------------------------------------------*/ | |||
#/* */ | |||
#/* Change Log */ | |||
#/* */ | |||
#/* Mark Date Programmer Comment */ | |||
#/* ---- ---- ---------- ------- */ | |||
#/* @nnnn mm/dd/yy NNN */ | |||
#/* */ | |||
#/* */ | |||
#/***********************************************************************/ | |||
# ****** NOTE ****** | |||
# | |||
# If you are using a SED command with TAB characters, many editors | |||
# will expand tabs causing unpredictable results in other programs. | |||
# | |||
# Documentation: | |||
# | |||
# Using SED command with TABS. Besure to invoke set tab save option | |||
# on your editor. If you don't, the program 'xyz' will not work | |||
# correctly. | |||
# | |||
#**************************************************************************** | |||
# Dot directive definition area (usually just suffixes) | |||
#**************************************************************************** | |||
.SUFFIXES: | |||
.SUFFIXES: .com .sys .exe .obj .mbj .asm .inc .def .lnk .lrf .crf .ref | |||
.SUFFIXES: .lst .sym .map .c .h .lib | |||
#**************************************************************************** | |||
# Environment Setup for the component(s). | |||
#**************************************************************************** | |||
# | |||
# Conditional Setup Area and User Defined Macros | |||
# | |||
# | |||
# Compiler Location w/ includes, libs and tools | |||
# | |||
INC = ..\..\..\inc | |||
H = ..\..\..\h | |||
LIB = ..\..\..\lib386;..\..\..\lib | |||
TOOLSPATH = ..\..\..\tools | |||
# | |||
# Because the compiler/linker and other tools use environment | |||
# variables ( INCLUDE, LIB, etc ) in order to get the location of files, | |||
# the following line will check the environment for the LIFE of the | |||
# makefile and will be specific to this set of instructions. All MAKEFILES | |||
# are requested to use this format to insure that they are using the correct | |||
# level of files and tools. | |||
# | |||
!if set INCLUDE=$(INC) || \ | |||
set LIB=$(LIB) || set PATH=$(TOOLSPATH);$(DK_TOOLS) | |||
!endif | |||
# | |||
# Compiler/tools Macros | |||
# | |||
AS=masm | |||
CC=cl386 | |||
IMPLIB=implib | |||
IPF=ipfc | |||
LIBUTIL=lib | |||
LINK=link386 | |||
MAPSYM=mapsym | |||
RC=rc | |||
# | |||
# Compiler and Linker Options | |||
# | |||
AFLAGS = -MX -T -Z $(ENV) | |||
AINC = -I. -I$(INC) | |||
CINC = -I$(H) -I$(MAKEDIR) | |||
CFLAGS = /c /Zp /Gs /AS $(ENV) | |||
LFLAGS = /map /nod /exepack | |||
LIBS = os2386.lib | |||
DEF = ALR.def | |||
#**************************************************************************** | |||
# Set up Macros that will contain all the different dependencies for the | |||
# executables and dlls etc. that are generated. | |||
#**************************************************************************** | |||
# | |||
# | |||
# | |||
OBJ1 = entry.obj main.obj | |||
# | |||
# LIST Files | |||
# | |||
LIST = | |||
OBJS = $(OBJ1) | |||
#**************************************************************************** | |||
# Setup the inference rules for compiling and assembling source code to | |||
# object code. | |||
#**************************************************************************** | |||
.asm.obj: | |||
$(AS) $(AFLAGS) $(AINC) $*.asm; | |||
.asm.mbj: | |||
$(AS) $(AFLAGS) -DMMIOPH $(AINC) $*.asm $*.mbj; | |||
.asm.lst: | |||
$(AS) -l -n $(AFLAGS) $(AINC) $*.asm; | |||
.c.obj: | |||
$(CC) $(CFLAGS) $(CINC) $*.c | |||
.c.lst: | |||
$(CC) $(CFLAGS) /Fc $(CINC) $*.c | |||
copy $*.cod $*.lst | |||
del $*.cod | |||
#**************************************************************************** | |||
# Target Information | |||
#**************************************************************************** | |||
# | |||
# This is a very important step. The following small amount of code MUST | |||
# NOT be removed from the program. The following directive will do | |||
# dependency checking every time this component is built UNLESS the | |||
# following is performed: | |||
# A specific tag is used -- ie. all | |||
# | |||
# This allows the developer as well as the B & I group to perform incremental | |||
# build with a degree of accuracy that has not been used before. | |||
# There are some instances where certain types of INCLUDE files must be | |||
# created first. This type of format will allow the developer to require | |||
# that file to be created first. In order to achieve that, all that has to | |||
# be done is to make the DEPEND.MAK tag have your required target. Below is | |||
# an example: | |||
# | |||
# depend.mak: { your file(s) } dephold | |||
# | |||
# Please DON'T remove the following line | |||
# | |||
!include "$(H)\common.mak" | |||
!include "$(H)\version.mak" | |||
# | |||
# Should be the default tag for all general processing | |||
# | |||
all: ALR.psd | |||
list: $(LIST) | |||
clean: | |||
if exist *.lnk del *.lnk | |||
if exist *.obj del *.obj | |||
if exist *.mbj del *.mbj | |||
if exist *.map del *.map | |||
if exist *.old del *.old | |||
if exist *.lst del *.lst | |||
if exist *.lsd del *.lsd | |||
if exist *.sym del *.sym | |||
if exist *.sys del *.sys | |||
#***************************************************************************** | |||
# Specific Description Block Information | |||
#***************************************************************************** | |||
# This section would only be for specific direction as to how to create | |||
# unique elements that are necessary to the build process. This could | |||
# be compiling or assembling, creation of DEF files and other unique | |||
# files. | |||
# If all compiler and assembly rules are the same, use an inference rule to | |||
# perform the compilation. | |||
# | |||
alr.psd: $(OBJS) makefile | |||
Rem Create DEF file <<$(DEF) | |||
LIBRARY ALR | |||
EXPORTS | |||
PSD_INSTALL = _Install | |||
PSD_DEINSTALL = _DeInstall | |||
PSD_INIT = _Init | |||
PSD_PROC_INIT = _ProcInit | |||
PSD_START_PROC = _StartProcessor | |||
PSD_GET_NUM_OF_PROCS = _GetNumOfProcs | |||
PSD_GEN_IPI = _GenIPI | |||
PSD_END_IPI = _EndIPI | |||
<<keep | |||
$(LINK) $(LFLAGS) @<<$(@B).lnk | |||
$(OBJ1) | |||
$*.psd | |||
$*.map | |||
$(LIBS) | |||
$(DEF) | |||
<<keep | |||
$(MAPSYM) $*.map | |||
#**************************************************************************** | |||
# Dependency generation and Checking | |||
#**************************************************************************** | |||
depend.mak: dephold | |||
touch depchk | |||
includes -e -sobj -llst -I. -I$(H) -I$(DISKH) -I$(INC) -P$$(H)=$(H) *.c *.asm >$@ | |||
-del depchk | |||
dephold: | |||
touch $@ | |||
!include depend.mak | |||
</PRE> |
Latest revision as of 19:38, 24 May 2025
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
The following is the source code for an actual PSD.
Main program
#define INCL_ERROR_H #include <os2.h> #include <psd.h> #include <alr.h> extern ulong_t RMP2Available(void); /* * Global Variables */ P_F_2 router = 0; char *pParmString = 0; int IODelayCount = 30; PLMA *pPSDPLMA = 0; ulong_t sizePLMA = 0; /*** Disable - Disable interrupts * * This function disables interrupts, and returns * the original state of eflags * * ENTRY None * * EXIT EFLAGS * */ ulong_t Disable(void) { ulong_t eflags; _asm { pushfd pop eax mov eflags,eax cli }; return (eflags); } /*** Enable - Restore the state of eflags * * This function restores the state of eflags * * ENTRY eflags - state of eflags to restore * * EXIT None * */ void Enable(ulong_t eflags) { _asm { push eflags popfd }; return; } /*** InByte - Read a byte from a port * * This function reads a byte from a specified port * * ENTRY port - port number to read from * * EXIT data read * */ ulong_t InByte(ulong_t port) { ulong_t data; _asm { mov dx,port in al,dx movzx eax,al mov data,eax }; return (data); } /*** OutByte - Writes a byte to a port * * This function writes a byte to a specified port * * ENTRY port - port number to read from * data - data to write * * EXIT None * */ void OutByte(ulong_t port, ulong_t data) { _asm { mov dx,port mov al,byte ptr data out dx,al }; return; } /*** SendEOI - Send an end of interrupt * * This function sends an end of interrupt. * * ENTRY irq - irq level to end * * EXIT None * */ ulong_t SendEOI(ulong_t irq) { ulong_t flags; flags = Disable(); if (irq < NUM_IRQ_PER_PIC) OutByte(PIC1_PORT0, OCW2_NON_SPECIFIC_EOI); else { OutByte(PIC2_PORT0, OCW2_NON_SPECIFIC_EOI); IODelay; OutByte(PIC1_PORT0, OCW2_NON_SPECIFIC_EOI); } Enable(flags); } /*** WHO_AM_I - Returns the current processor number * * This function returns the current processor number * * ENTRY NONE * * EXIT Current processor number (P1 or P2) * */ ulong_t WHO_AM_I (void) { return(InByte(WHO_AM_I_PORT)); } /*** IPIPresent - Detects the presence of an IPI * * This function detects the presence of an IPI on the current * processor * * ENTRY None * * EXIT NO_ERROR - IPI present * -1 - IPI not present * */ ulong_t IPIPresent (void) { ulong_t rc = 0; struct control_s ctrl; ulong_t port; port = pPSDPLMA->controlport; ctrl.b_all = InByte(port); if (ctrl.b_387err) { OutByte (0xf0, 0); // The busy latch for NPX must be cleared. // When we call the interrupt handler // (w/ Call16bitDD int.asm), ints. are 1st enabled. // If the busy latch is not cleared, then we // will take this interrupt in again and will // eventually nest until the interrupt stack is // overrun. rc = -1; } return (rc); } /*** Install - Install PSD * * This function checks to see if this PSD is installable on the * current platform. * * ENTRY pinstall - pointer to an INSTALL structure * * EXIT NO_ERROR - PSD Installed * -1 - PSD not valid for this platform * */ ulong_t Install(INSTALL *pinstall) { VMALLOC vmac; int i; char *p; ulong_t rc = 0; char ALR_String = "PROVEISA"; // _asm int 3; /* Setup Global variables */ router = pinstall->pPSDHlpRouter; pParmString = pinstall->pParmString; pPSDPLMA = (void *)pinstall->pPSDPLMA; sizePLMA = pinstall->sizePLMA; vmac.addr = BIOS_SEG << 4; vmac.cbsize = _64K; vmac.flags = VMALLOC_PHYS; /* Map BIOS area */ if ((rc = PSDHelp(router, PSDHLP_VMALLOC, &vmac)) == NO_ERROR) { /* Check for ALR string */ p = (char *)vmac.addr + ALR_STRING_OFFSET; for (i = 0; ALR_String i != '\0'; i++) if (p i != ALR_String i) { rc = -1; break; } /* Free BIOS mapping */ PSDHelp(router, PSDHLP_VMFREE, vmac.addr); } return (rc); } /*** DeInstall - DeInstall PSD * * This function deinstalls the PSD. * * ENTRY None * * EXIT NO_ERROR * */ ulong_t DeInstall(void) { return (NO_ERROR); } /*** Init - Initialize the PSD * * This function initializes the PSD. * * ENTRY None * * EXIT NO_ERROR - PSD initialized * -1 - PSD not initialized * */ ulong_t Init(INIT *pinit) { struct control_s ctrl; SET_IRQ set_irq; /* Initialize P1 control port */ ctrl.b_all = 0; ctrl.b_cacheon = 1; OutByte(P1_PROCESSOR_CONTROL_PORT, ctrl.b_all); /* Setup P2 interrupt vector */ OutByte(P2_INTERRUPT_VECTOR_CONTROL_PORT, IPI_VECTOR); /* Setup IPI info */ set_irq.irq = 13; set_irq.flags = IRQf_IPI; set_irq.vector = 0; set_irq.handler = (P_F_2)IPIPresent; PSDHelp(router, PSDHLP_SET_IRQ, &set_irq); /* Fill init structure */ pinit->flags = INIT_EOI_IRQ13_ON_CPU0; //76422 pinit->version = VERSION; return (NO_ERROR); } /*** ProcInit - Processor initialization * * This function initializes per processor items. * * NOTE: This function is called once on each processor * in the system. * * ENTRY None * * EXIT NO_ERROR - Processor initialized * -1 - Processor not initialized * */ ulong_t ProcInit(void) { if (WHO_AM_I() == P1) { pPSDPLMA->procnum = 0; pPSDPLMA->controlport = P1_PROCESSOR_CONTROL_PORT; } else { pPSDPLMA->procnum = 1; pPSDPLMA->controlport = P2_PROCESSOR_CONTROL_PORT; } return (NO_ERROR); } /*** StartProcessor - Start a processor * * This function starts a processor. * * ENTRY procnum - processor number to start (0-based) * * EXIT Return Code * */ ulong_t StartProcessor(ulong_t procnum) { CALL_REAL_MODE rm; struct control_s ctrl; ulong_t rc = -1; if (procnum == 1) { rm.function = (ulong_t)&RMP2Available; rm.pdata = 0; rc = PSDHelp(router, PSDHLP_CALL_REAL_MODE, &rm); if (rc & P2_AVAILABLE) { /* Dispatch P2 */ ctrl.b_all = 0; ctrl.b_cacheon = 1; OutByte(P2_PROCESSOR_CONTROL_PORT, ctrl.b_all); rc = NO_ERROR; } else rc = -1; } return (rc); } /*** GetNumOfProcs - Get number of processors * * This function gets the number of processors which exist on this * platform. * * ENTRY None * * EXIT Number of processors * */ ulong_t GetNumOfProcs(void) { ulong_t cprocs = 2; return (cprocs); } /*** GenIPI - Generate an inter-processor interrupt * * This function generates an IPI. * * ENTRY procnum - processor number to interrupt (0-based) * * EXIT NO_ERROR * */ ulong_t GenIPI(ulong_t procnum) { struct control_s ctrl; ulong_t port; if (procnum == 0) port = P1_PROCESSOR_CONTROL_PORT; else port = P2_PROCESSOR_CONTROL_PORT; ctrl.b_all = InByte(port); ctrl.b_pint = 1; OutByte(port, ctrl.b_all); return (NO_ERROR); } /*** EndIPI - End an inter-processor interrupt * * This function ends an IPI. * * ENTRY procnum - processor number to end interrupt on (0-based) * * EXIT NO_ERROR * */ ulong_t EndIPI(ulong_t procnum) { struct control_s ctrl; ulong_t port; if (procnum == 0) port = P1_PROCESSOR_CONTROL_PORT; else port = P2_PROCESSOR_CONTROL_PORT; ctrl.b_all = InByte(port); ctrl.b_pint = 0; OutByte(port, ctrl.b_all); if (procnum == 0) SendEOI(IPI_IRQ); return (NO_ERROR); }
Entry stub
.386 _TEXT SEGMENT ASSUME CS:_TEXT,DS:NOTHING PUBLIC _RMP2Available _RMP2Available PROC mov ah,0E2h mov al,0 int 15h movzx eax,ax retf _RMP2Available ENDP _TEXT ENDS END
PSD.H
/*static char *SCCSID = "@(#)psd.h 1.0 93/18/08";*/ // XLATOFF #ifndef ulong_t typedef unsigned long ulong_t; typedef unsigned short ushort_t; typedef unsigned char uchar_t; #endif typedef int (*P_F_1)(ulong_t arg); typedef int (*P_F_2)(ulong_t arg1, ulong_t arg2); #define PSDHelp(router, function, arg) \ ((*router)((function), (ulong_t)(arg))) // XLATON /* ASM P_F_1 struc dd ? P_F_1 ends P_F_2 struc dd ? P_F_2 ends */ #define WARM_REBOOT_VECTOR_SEG 0x40 #define WARM_REBOOT_VECTOR_OFF 0x67 /* PSD Info structure */ typedef struct info_s { /* psd */ ulong_t flags; /* PSD flags */ ulong_t version; /* PSD version */ ulong_t hmte; /* MTE handle of PSD */ uchar_t *pParmString; /* Pointer to ASCIIZ PSD parameter*/ ulong_t IRQ_IPI; /* IRQ for IPI */ ulong_t IRQ_LSI; /* IRQ for LSI */ ulong_t IRQ_SPI; /* IRQ for SPI */ } PSDINFO; /* PSD flags definition */ #define PSD_ADV_INT_MODE 0x20000000 /* PSD is in adv int mode #81531 */ #define PSD_INSTALLED 0x40000000 /* PSD has been installed */ #define PSD_INITIALIZED 0x80000000 /* PSD has been initialized */ /* PSD function numbers-structures */ #define PSD_INSTALL 0x00000000 /* Install PSD */ typedef struct install_s { /* install */ P_F_2 pPSDHlpRouter; /* Address of PSDHlpRouter */ char *pParmString; /* Pointer to parameter string */ void *pPSDPLMA; /* Pointer to PSD's PLMA */ ulong_t sizePLMA; /* Size of PLMA in bytes */ } INSTALL; #define PSD_DEINSTALL 0x00000001 /* DeInstall PSD */ #define PSD_INIT 0x00000002 /* Initialize PSD */ typedef struct init_s { /* init */ ulong_t flags; /* Init flags */ ulong_t version; /* PSD Version number */ } INIT; #define INIT_GLOBAL_IRQ_ACCESS 0x00000001 /* Platform has global IRQ access */ #define INIT_USE_FPERR_TRAP 0x00000002 /* Use Trap 16 to report FP err's */ #define INIT_EOI_IRQ13_ON_CPU0 0x00000004 /* eoi IRQ 13 only if on cpu 0 */ #define INIT_TIMER_CPU0 0x00000008 /* system timer is on CPU 0 */ #define PSD_PROC_INIT 0x00000003 /* Initialize processor */ #define PSD_START_PROC 0x00000004 /* Start processor */ #define PSD_GET_NUM_OF_PROCS 0x00000005 /* Get number of processors */ #define PSD_GEN_IPI 0x00000006 /* Generate an IPI */ #define PSD_END_IPI 0x00000007 /* End an IPI */ #define PSD_PORT_IO 0x00000008 /* Port I/O */ typedef struct port_io_s { /* port_io */ ulong_t port; /* Port number to access */ ulong_t data; /* Data read, or data to write */ ulong_t flags; /* IO Flags */ } PORT_IO; #define IO_READ_BYTE 0x0000 /* Read a byte from the port */ #define IO_READ_WORD 0x0001 /* Read a word from the port */ #define IO_READ_DWORD 0x0002 /* Read a dword from the port */ #define IO_WRITE_BYTE 0x0003 /* Write a byte to the port */ #define IO_WRITE_WORD 0x0004 /* Write a word to the port */ #define IO_WRITE_DWORD 0x0005 /* Write a dword to the port */ #define IO_FLAGMASK 0x0007 /* Flag mask */ #define PSD_IRQ_MASK 0x00000009 /* Mask/Unmask IRQ levels */ typedef struct psd_irq_s { /* psd_irq */ ulong_t flags; /* IRQ flags */ ulong_t data; /* IRQ data */ /* depending on type of irq */ /* operation, the data field */ /* can contain any of the */ /* following info: */ /* 1) Mask or UNMasking data */ /* 2) IRR or ISR reg values */ /* 3) IRQ # for EOI operations */ ulong_t procnum; /* Processor number */ } PSD_IRQ; #define PSD_IRQ_REG 0x0000000A /* Access IRQ related regs */ #define PSD_IRQ_EOI 0x0000000B /* Issue an EOI */ #define IRQ_MASK 0x00000001 /* Turn on IRQ mask bits */ #define IRQ_UNMASK 0x00000002 /* Turn off IRQ mask bits */ #define IRQ_GETMASK 0x00000004 /* Get IRQ mask bits */ #define IRQ_NEWMASK 0x00000010 /* Set and/or Reset all masks */ #define IRQ_READ_IRR 0x00000100 /* Read the IRR reg */ #define IRQ_READ_ISR 0x00000200 /* Read the ISR reg */ #define PSD_APP_COMM 0x0000000C /* PSD/APP Communication */ #define PSD_SET_ADV_INT_MODE 0x0000000D /* Set advanced int mode */ #define PSD_SET_PROC_STATE 0x0000000E /* Set proc state; idle, or busy */ #define PROC_STATE_IDLE 0x00000000 /* Processor is idle */ #define PROC_STATE_BUSY 0x00000001 /* Processor is busy */ #define PSD_QUERY_SYSTEM_TIMER 0x0000000F /* Query Value of System Timer 0 */ typedef struct psd_qrytmr_s { /* psd_qrytmr */ ulong_t qw_ulLo_psd; /* Timer count */ ulong_t qw_ulHi_psd; /* Timer count */ ulong_t pqwTmr; /* 16:16 ptr to qwTmr */ } PSD_QRYTMR; #define PSD_SET_SYSTEM_TIMER 0x00000010 /* Set System Timer 0 counter */ typedef struct psd_settmr_s { /* psd_settmr */ ulong_t NewRollOver; /* NewRollover*/ ulong_t pqwTmrRollover; /* 16:16 ptr to qwTmrRollover */ } PSD_SETTMR; /* PSD helper function numbers-structures */ #define PSDHLP_VMALLOC 0x00000000 /* Allocate memory */ typedef struct vmalloc_s { /* vmalloc */ ulong_t addr; /* Physical address to map */ /* if VMALLOC_PHYS */ /* Lin addr to alloc at */ /* if VMALLOC_LOCSPECIFIC */ /* on return, addr of allocation */ ulong_t cbsize; /* Size of mapping in bytes */ ulong_t flags; /* Allocation flags */ } VMALLOC; #define VMALLOC_FIXED 0x00000001 /* Allocate resident memory */ #define VMALLOC_CONTIG 0x00000002 /* Allocate contiguous memory */ #define VMALLOC_LOCSPECIFIC 0x00000004 /* Alloc at a specific lin address */ #define VMALLOC_PHYS 0x00000008 /* Map physical address */ #define VMALLOC_1M 0x00000010 /* Allocate below 1M */ #define VMALLOC_FLAGMASK 0x0000001f /* Valid flag mask */ #define PSDHLP_VMFREE 0x00000001 /* Free memory */ #define PSDHLP_SET_IRQ 0x00000002 /* Set up an IRQ */ typedef struct set_irq_s { /* set_irq */ ushort_t irq; /* IRQ level */ ushort_t flags; /* Set IRQ flags */ ulong_t vector; /* IRQ interrupt vector */ P_F_2 handler; /* IRQ handler */ } SET_IRQ; #define IRQf_IPI 0x0020 /* IRQ for IPI */ #define IRQf_LSI 0x0040 /* IRQ for LSI */ #define IRQf_SPI 0x0080 /* IRQ for SPI */ #define PSDHLP_CALL_REAL_MODE 0x00000003 /* Call a function in real mode */ typedef struct call_real_mode_s { /* call_real_mode */ ulong_t function; /* Function address */ ulong_t pdata; /* Pointer to data area */ } CALL_REAL_MODE; #define PSDHLP_VMLINTOPHYS 0x00000004 /* Convert linear addr to phys */ #define PSDHLP_ADJ_PG_RANGES 0x00000005 /* Adjust page ranges */ typedef struct _pagerange_s { /* pagerange */ ulong_t lastframe; /* Last valid page in range */ ulong_t firstframe; /* First valid page in range */ }; typedef struct adj_pg_ranges_s{ /* adj_pg_ranges */ struct _pagerange_s *pprt; /* Pointer to page range table */ ulong_t nranges; /* Num of ranges in range table */ } ADJ_PG_RANGES; /* PSD function prototypes */ extern void PSDEnter (ulong_t function, ulong_t arg, P_F_2 altEntry);
Specific header
/* * Miscellaneous */ #define VERSION 0x00000010 #define _64K (64 * 1024) #define BIOS_SEG 0xF000 #define ALR_STRING_OFFSET 0xEC47 #define P2_AVAILABLE 0x00008000 /* * PLMA structure */ typedef struct plma_s { ulong_t procnum; /* Current processor number (0-based) */ ulong_t controlport; /* Control port for current processor */ } PLMA; /* * Generate delay between I/O instructions */ #define IODelay {int i; for(i = 0; i < IODelayCount; i++); } /* * IPI info */ #define IPI_IRQ 0x0d /* IRQ level for IPI */ #define IPI_VECTOR 0x75 /* Vector number for IPI */ /* * PIC Info */ #define NUM_IRQ_PER_PIC 0x08 #define OCW2_NON_SPECIFIC_EOI 0x20 #define PIC1_PORT0 0x20 #define PIC1_PORT1 0x21 #define PIC2_PORT0 0xA0 #define PIC2_PORT1 0xA1 /* * The contents of the WHO_AM_I port (read-only) can be used * by code to determine which processor we are currently on */ #define WHO_AM_I_PORT 0xC70 #define P1 0x00 #define P2 0xF0 /* * The processor control port contains the bits used to control * various functions of the associated processor */ #define P1_PROCESSOR_CONTROL_PORT 0x0C6A #define P2_PROCESSOR_CONTROL_PORT 0xFC6A struct _b_control_s { ulong_t _reset:1, /* RESET - (Not implemented for P1) */ /* 1 = Resets processor */ _387pres:1, /* 387PRES - (Read only) */ /* 0 = 80387 is not installed */ /* 1 = 80387 is installed */ _cacheon:1, /* CACHEON - (Not implemented for P1) */ /* 0 = Disables cache */ /* 1 = Enables cache */ _mbusaccess:1, /* M Bus Access (Not implemented for P1) */ /* 0 = Allows the processor to gain */ /* control of the memory bus */ /* 1 = Prohibits the processor from gaining */ /* access to the memory bus. The */ /* processor can execute instructions */ /* from its cache; however, cache read */ /* misses, I/O, and writes cause the */ /* processor to cease executing */ /* instructions until the bit becomes */ /* a "0" */ _flush:1, /* FLUSH */ /* Writing a "1" to this bit followed by a "0" */ /* causes invalidation of all cache address */ /* information */ _387err:1, /* 387ERR */ /* 0 = No 80387 error */ /* 0 = An 80387 error has occurred. This bit */ /* must be cleared by software */ _pint:1, /* PINT */ /* A low-to-high transition of this bit causes */ /* an interrupt. This bit must be cleared by */ /* software, preferably by the interrupt service */ /* routine. On P2, the value stored in FC68h */ /* contains the interrupt number. P1 is always */ /* interrupted with IRQ13 */ _intdis:1, /* INTDIS */ /* When set to "1", this bit disables interrupts */ /* sent to the processor by way of the PINT bit. */ /* The PINT bit can still be changed when */ /* interrupts are disabled; however, the */ /* low-to-high transition is not seen by the */ /* processor until the INTDIS bit is made inactive */ _pad:24; }; struct _l_control_s { /* to treat control as an unsigned long */ unsigned long _long; }; union _control_u { struct _b_control_s b_control_s; struct _l_control_s l_control_s; }; struct control_s { union _control_u control_u; }; #define b_reset control_u.b_control_s._reset #define b_387pres control_u.b_control_s._387pres #define b_cacheon control_u.b_control_s._cacheon #define b_mbusaccess control_u.b_control_s._mbusaccess #define b_flush control_u.b_control_s._flush #define b_387err control_u.b_control_s._387err #define b_pint control_u.b_control_s._pint #define b_intdis control_u.b_control_s._intdis #define b_all control_u.l_control_s._long /* * The interrupt vector control port contains the 8-bit interrupt * number that is executed when the PINT bit transitions from "0" * to "1". This vector is only used for P2. P1 is always interrupted * with IRQ 13. */ #define P2_INTERRUPT_VECTOR_CONTROL_PORT 0xFC68 /* * The following ports contain the EISA identification of the * system processor boards */ #define COMPAQ_ID1 0x0000000E #define COMPAQ_ID2 0x00000011 #define P1_EISA_PRODUCT_ID_PORT1 0x0C80 /* Compressed COMPAQ ID - OEh */ #define P1_EISA_PRODUCT_ID_PORT2 0x0C81 /* 11h */ #define P1_EISA_PRODUCT_ID_PORT3 0x0C82 /* Product code for the proc board */ #define P1_EISA_PRODUCT_ID_PORT4 0x0C83 /* Revision number */ #define P2_EISA_PRODUCT_ID_PORT1 0xFC80 /* Compressed COMPAQ ID - OEh */ #define P2_EISA_PRODUCT_ID_PORT2 0xFC81 /* 11h */ #define P2_EISA_PRODUCT_ID_PORT3 0xFC82 /* Product code for the proc board */ #define P2_EISA_PRODUCT_ID_PORT4 0xFC83 /* Revision number */ /* * Any write to The RAM Relocation Register (memory mapped) * will flush the caches of both P1 and P2 */ #define RAM_RELOCATION_REGISTER 0x80C00000 /* * The P1 Cache Control Register (memory mapped) */ #define P1_CACHE_CONTROL_REGISTER 0x80C00002 struct p1cache_s { ulong_t _reserved1:6, _p1cc:1, /* P1 Cache Control */ /* 0 = Disables P1 cache */ /* 1 = Enables P1 cache */ _reserved2:9; }; /* * Expanision board control ports */ #define P1_EISA_EXPANSION_BOARD_CONTROL 0x0C84 #define P2_EISA_EXPANSION_BOARD_CONTROL 0xFC84
Makefile
# SCCSID = @(#)makefile 6.7 92/06/03 #/***********************************************************************/ #/* */ #/* PSD Name: ALR.PSD - ALR PSD */ #/* ----------------------------------- */ #/* */ #/* Source File Name: MAKEFILE */ #/* */ #/* Descriptive Name: MAKEFILE for the ALR PSD */ #/* */ #/* Function: */ #/* */ #/* */ #/*---------------------------------------------------------------------*/ #/* */ #/* Copyright (C) 1992 IBM Corporation */ #/* */ #/* DISCLAIMER OF WARRANTIES. The following enclosed code is */ #/* provided to you solely for the purpose of assisting you in */ #/* the development of your applications. The code is provided */ #/* "AS IS", without warranty of any kind. IBM shall not be liable */ #/* for any damages arising out of your use of this code, even if */ #/* they have been advised of the possibility of such damages. */ #/* */ #/*---------------------------------------------------------------------*/ #/* */ #/* Change Log */ #/* */ #/* Mark Date Programmer Comment */ #/* ---- ---- ---------- ------- */ #/* @nnnn mm/dd/yy NNN */ #/* */ #/* */ #/***********************************************************************/ # ****** NOTE ****** # # If you are using a SED command with TAB characters, many editors # will expand tabs causing unpredictable results in other programs. # # Documentation: # # Using SED command with TABS. Besure to invoke set tab save option # on your editor. If you don't, the program 'xyz' will not work # correctly. # #**************************************************************************** # Dot directive definition area (usually just suffixes) #**************************************************************************** .SUFFIXES: .SUFFIXES: .com .sys .exe .obj .mbj .asm .inc .def .lnk .lrf .crf .ref .SUFFIXES: .lst .sym .map .c .h .lib #**************************************************************************** # Environment Setup for the component(s). #**************************************************************************** # # Conditional Setup Area and User Defined Macros # # # Compiler Location w/ includes, libs and tools # INC = ..\..\..\inc H = ..\..\..\h LIB = ..\..\..\lib386;..\..\..\lib TOOLSPATH = ..\..\..\tools # # Because the compiler/linker and other tools use environment # variables ( INCLUDE, LIB, etc ) in order to get the location of files, # the following line will check the environment for the LIFE of the # makefile and will be specific to this set of instructions. All MAKEFILES # are requested to use this format to insure that they are using the correct # level of files and tools. # !if set INCLUDE=$(INC) || \ set LIB=$(LIB) || set PATH=$(TOOLSPATH);$(DK_TOOLS) !endif # # Compiler/tools Macros # AS=masm CC=cl386 IMPLIB=implib IPF=ipfc LIBUTIL=lib LINK=link386 MAPSYM=mapsym RC=rc # # Compiler and Linker Options # AFLAGS = -MX -T -Z $(ENV) AINC = -I. -I$(INC) CINC = -I$(H) -I$(MAKEDIR) CFLAGS = /c /Zp /Gs /AS $(ENV) LFLAGS = /map /nod /exepack LIBS = os2386.lib DEF = ALR.def #**************************************************************************** # Set up Macros that will contain all the different dependencies for the # executables and dlls etc. that are generated. #**************************************************************************** # # # OBJ1 = entry.obj main.obj # # LIST Files # LIST = OBJS = $(OBJ1) #**************************************************************************** # Setup the inference rules for compiling and assembling source code to # object code. #**************************************************************************** .asm.obj: $(AS) $(AFLAGS) $(AINC) $*.asm; .asm.mbj: $(AS) $(AFLAGS) -DMMIOPH $(AINC) $*.asm $*.mbj; .asm.lst: $(AS) -l -n $(AFLAGS) $(AINC) $*.asm; .c.obj: $(CC) $(CFLAGS) $(CINC) $*.c .c.lst: $(CC) $(CFLAGS) /Fc $(CINC) $*.c copy $*.cod $*.lst del $*.cod #**************************************************************************** # Target Information #**************************************************************************** # # This is a very important step. The following small amount of code MUST # NOT be removed from the program. The following directive will do # dependency checking every time this component is built UNLESS the # following is performed: # A specific tag is used -- ie. all # # This allows the developer as well as the B & I group to perform incremental # build with a degree of accuracy that has not been used before. # There are some instances where certain types of INCLUDE files must be # created first. This type of format will allow the developer to require # that file to be created first. In order to achieve that, all that has to # be done is to make the DEPEND.MAK tag have your required target. Below is # an example: # # depend.mak: { your file(s) } dephold # # Please DON'T remove the following line # !include "$(H)\common.mak" !include "$(H)\version.mak" # # Should be the default tag for all general processing # all: ALR.psd list: $(LIST) clean: if exist *.lnk del *.lnk if exist *.obj del *.obj if exist *.mbj del *.mbj if exist *.map del *.map if exist *.old del *.old if exist *.lst del *.lst if exist *.lsd del *.lsd if exist *.sym del *.sym if exist *.sys del *.sys #***************************************************************************** # Specific Description Block Information #***************************************************************************** # This section would only be for specific direction as to how to create # unique elements that are necessary to the build process. This could # be compiling or assembling, creation of DEF files and other unique # files. # If all compiler and assembly rules are the same, use an inference rule to # perform the compilation. # alr.psd: $(OBJS) makefile Rem Create DEF file <<$(DEF) LIBRARY ALR EXPORTS PSD_INSTALL = _Install PSD_DEINSTALL = _DeInstall PSD_INIT = _Init PSD_PROC_INIT = _ProcInit PSD_START_PROC = _StartProcessor PSD_GET_NUM_OF_PROCS = _GetNumOfProcs PSD_GEN_IPI = _GenIPI PSD_END_IPI = _EndIPI <<keep $(LINK) $(LFLAGS) @<<$(@B).lnk $(OBJ1) $*.psd $*.map $(LIBS) $(DEF) <<keep $(MAPSYM) $*.map #**************************************************************************** # Dependency generation and Checking #**************************************************************************** depend.mak: dephold touch depchk includes -e -sobj -llst -I. -I$(H) -I$(DISKH) -I$(INC) -P$$(H)=$(H) *.c *.asm >$@ -del depchk dephold: touch $@ !include depend.mak