source: GPL/lib32/stack.cpp@ 1

Last change on this file since 1 was 1, checked in by vladest, 20 years ago

initial import

File size: 4.9 KB
Line 
1/*
2 * Custom 32 bits stack management
3 *
4 * (C) 2000-2002 InnoTek Systemberatung GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
19 * USA.
20 */
21
22extern "C" {
23#define INCL_NOPMAPI
24#define INCL_DOSERRORS // for ERROR_INVALID_FUNCTION
25#include <os2.h>
26}
27#include <devhelp.h>
28#include <ossidc.h>
29#include <dbgos2.h>
30#include <stacktoflat.h>
31#ifdef KEE
32#include <kee.h>
33#endif
34
35#define MAX_STACK 8
36#define STACKSIZE (16*1024)
37#define TOTAL_STACKSIZE MAX_STACK*(16*1024)
38#define MAX_STACK_SEL TOTAL_STACKSIZE/(64*1024)
39
40#define STACK_FREE 0
41#define STACK_USED 1
42
43typedef struct {
44 int state;
45 LINEAR addr;
46 SEL sel;
47} PDDStack;
48
49static PDDStack Ring0Stack[MAX_STACK] = {0};
50static SEL Ring0StackSel[MAX_STACK_SEL] = {0};
51static LINEAR StackBase = NULL;
52static BOOL fInitialized = FALSE;
53
54//*********************************************************************************************
55//StackAlloc:
56//
57// Allocate stack when called the first time;
58// Return private stack base
59//
60// NOTE: Stack is 16 bits when called
61//*********************************************************************************************
62DWORD StackAlloc();
63#pragma aux StackAlloc "StackAlloc";
64DWORD StackAlloc()
65{
66 int i;
67 DWORD cpuflags;
68 APIRET rc;
69 SEL gdts[MAX_STACK_SEL];
70 SEL FAR48 *gdt;
71
72 cpuflags = DevPushfCli();
73
74 if(fInitialized == FALSE) {
75 fInitialized = TRUE;
76
77 //allocate our private stack
78 rc = DevVMAlloc(VMDHA_USEHIGHMEM|VMDHA_FIXED|VMDHL_CONTIGUOUS, TOTAL_STACKSIZE, (LINEAR)-1, (LINEAR)&StackBase);
79 if(rc) {
80 DebugInt3();
81 return 0;
82 }
83 Ring0Stack[0].addr = StackBase;
84
85 //allocate GDT selectors (so we can map a flat stack address to a 16:16 pointer)
86 rc = DevAllocGDTSel(MAKE_FARPTR16_STACK((LINEAR)&gdts[0]), MAX_STACK_SEL);
87 if(rc) {
88 DebugInt3();
89 return 0;
90 }
91 //and map linear stack addresses to GDT selectors
92 for(i=0;i<MAX_STACK_SEL;i++) {
93 LINEAR addr = (LINEAR)StackBase + i*64*1024;
94
95 gdt = (SEL FAR48 *)MAKE_FARPTR32_STACK((LINEAR)&gdts[i]);
96 if(DevHelp_LinToGDTSelector(*gdt, addr, 64*1024)) {
97 DebugInt3();
98 return 0;
99 }
100 Ring0StackSel[i] = *gdt;
101 }
102
103 for(i=0;i<MAX_STACK;i++) {
104 Ring0Stack[i].addr = StackBase + i*STACKSIZE;
105 Ring0Stack[i].sel = Ring0StackSel[i*STACKSIZE/(64*1024)];
106 }
107 }
108
109 for(i=0;i<MAX_STACK;i++) {
110 if(Ring0Stack[i].state == STACK_FREE) {
111 Ring0Stack[i].state = STACK_USED;
112 DevPopf(cpuflags);
113 return (ULONG)(Ring0Stack[i].addr + STACKSIZE);
114 }
115 }
116 DevPopf(cpuflags);
117 DebugInt3(); //oh, oh!!
118 return 0;
119}
120//*********************************************************************************************
121//*********************************************************************************************
122void StackFree(DWORD stackaddr);
123#pragma aux StackFree "StackFree" parm [eax];
124void StackFree(DWORD stackaddr)
125{
126 int i;
127 DWORD cpuflags;
128
129 cpuflags = DevPushfCli();
130
131 stackaddr -= STACKSIZE;
132 for(i=0;i<MAX_STACK;i++) {
133 if(Ring0Stack[i].addr == (LINEAR)stackaddr) {
134 Ring0Stack[i].state = STACK_FREE;
135 DevPopf(cpuflags);
136 return;
137 }
138 }
139 DevPopf(cpuflags);
140 DebugInt3();
141}
142//*********************************************************************************************
143// FlatToSel:
144// Convert a flat stack address to a 16:16 address
145//
146//*********************************************************************************************
147ULONG FlatToSel(ULONG addr32)
148{
149 ULONG offset;
150
151 offset = addr32 - (ULONG)StackBase;
152
153 if(offset > TOTAL_STACKSIZE) {
154 //bad boy!
155 DebugInt3();
156 return 0;
157 }
158
159 return MAKE_FP16(Ring0StackSel[offset/(64*1024)], offset);
160}
161//*********************************************************************************************
162//*********************************************************************************************
163
Note: See TracBrowser for help on using the repository browser.