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);
}
[Back: Appendix A]
[Next: Entry stub]