Subversion Repositories shark

Rev

Rev 301 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/* Project:     OSLib
2
 * Description: The OS Construction Kit
3
 * Date:                1.6.2000
4
 * Idea by:             Luca Abeni & Gerardo Lamastra
5
 *
6
 * OSLib is an SO project aimed at developing a common, easy-to-use
7
 * low-level infrastructure for developing OS kernels and Embedded
8
 * Applications; it partially derives from the HARTIK project but it
9
 * currently is independently developed.
10
 *
11
 * OSLib is distributed under GPL License, and some of its code has
12
 * been derived from the Linux kernel source; also some important
13
 * ideas come from studying the DJGPP go32 extender.
14
 *
15
 * We acknowledge the Linux Community, Free Software Foundation,
16
 * D.J. Delorie and all the other developers who believe in the
17
 * freedom of software and ideas.
18
 *
19
 * For legalese, check out the included GPL license.
20
 */
21
 
22
/*	Safe abort routine & timer asm handler	*/
23
 
24
.title	"Timer.S"
25
 
26
#include <ll/i386/sel.h>
27
#include <ll/i386/linkage.h>
28
#include <ll/i386/defs.h>
29
 
30
#include <ll/sys/ll/exc.h>
31
 
32
.data
33
 
34
ASMFILE(TimerHandler)
35
 
36
.extern JmpSel
37
.extern JmpZone
38
.globl SYMBOL_NAME(ll_clock)
39
.globl SYMBOL_NAME(last_handler)
40
 
41
		/* Used as JMP entry point to check if a real	*/
42
		/* context switch is necessary			*/
43
 
44
SYMBOL_NAME_LABEL(ll_clock)	.int	0
45
SYMBOL_NAME_LABEL(last_handler)	.long   0
46
 
47
.extern  SYMBOL_NAME(periodic_wake_up)
48
.extern  SYMBOL_NAME(oneshot_wake_up)
49
 
50
.text
299 giacomo 51
		.globl SYMBOL_NAME(ll_apic_timer)
52
/* APIC ll_timer */
53
 
54
SYMBOL_NAME_LABEL(ll_apic_timer)
55
			pushal
56
			pushw	%ds
57
			pushw	%es
58
			pushw	%fs
59
			pushw	%gs
305 giacomo 60
 
61
			cli
62
 
63
			/* Send ACK to APIC		*/
64
			movl    $0xFEE000B0,%ebx
65
                        movl    $0,(%ebx)
66
 
299 giacomo 67
			movw    $(X_FLATDATA_SEL),%ax
68
			movw    %ax,%ds
69
			movw    %ax,%es
70
 
71
			/* Call wake_up(actual_context) */
72
 
73
			movl	SYMBOL_NAME(ll_clock),%eax
74
			incl 	%eax
75
			movl	%eax,SYMBOL_NAME(ll_clock)
76
 
77
			/* The following could be optimized a little... */
78
			xorl %ebx, %ebx
79
			movw %ss, %bx
80
			/* We must switch to a ``safe stack'' */
81
	/*
82
	 * OK, this is the idea: in %esp we have the address of the
83
	 * stack pointer in the APPLICATION address space...
84
	 * We assume that address spaces are implemented through segments...
85
	 * What we have to do is to add the segment base to %esp:
86
	 *	- Load the GDT base in a register
87
	 *	- Add DS * 8 to that value
88
	 *	- Read the corresponding GDT entry (the segment descriptor)
89
	 *	- Compute the base...
90
	 *	It is (*p & 0xFC) | (*(p +1)  & 0x0F) << 16) | *(p + 2)
91
	 */
92
			movl SYMBOL_NAME(GDT_base), %edi
93
			addl %ebx, %edi
94
			xorl %ebx, %ebx
95
			movb 7(%edi), %bh
96
			movb 4(%edi), %bl
97
			shl $16, %ebx
98
			movw 2(%edi), %bx
99
			/* Is it correct? I think so... Test it!!! */
100
			addl %ebx, %esp
101
			/* Save EBX for returning to our stack... */
102
			movw %ds, %cx
103
			movw %ss, %dx
104
			movw %cx, %ss
105
			pushl %ebx
106
			pushl %edx
107
			cld
108
			movl	SYMBOL_NAME(timermode), %eax
109
			cmpl	$1, %eax
110
			je	apic_oneshot
111
			call    SYMBOL_NAME(periodic_wake_up)
112
			jmp	apic_Timer_OK
113
apic_oneshot:		call    SYMBOL_NAME(oneshot_wake_up)
114
apic_Timer_OK:
115
			/* Restore ESP */
116
			popl	%edx
117
			popl	%ebx	/* We must subtract it from ESP...*/
118
			subl	%ebx, %esp
119
			movw	%dx, %ss
120
 
121
#ifdef __VIRCSW__
122
 
123
			movw	SYMBOL_NAME(currCtx), %ax
124
			cmpw    %ax,JmpSel
125
			je      apic_NoPreempt2
126
			movw    %ax,JmpSel
127
			ljmp    JmpZone /* DISPATCH! */
128
#endif
129
apic_NoPreempt2:
130
 
131
			cmpl	$0, SYMBOL_NAME(last_handler)
132
			je	apic_nohandler
133
			movl	SYMBOL_NAME(last_handler), %ebx
134
			call	*%ebx
135
apic_nohandler:
305 giacomo 136
 
137
			sti
138
 
299 giacomo 139
			popw	%gs
140
			popw	%fs
141
			popw	%es
142
			popw	%ds
143
			popal
144
			iret
145
 
2 pj 146
		.globl SYMBOL_NAME(ll_timer)
147
/* This is the timer handler; it reloads for safety the DS register; this   */
148
/* prevents from mess when timer interrupts linear access to memory (not in */
149
/* ELF address space); then EOI is sent in order to detect timer overrun    */
150
/* The high level kernel procedure wake_up() is called to perform the 	    */
151
/* preeption at higher level (process descriptos); the resulting context    */
152
/* if different from the old one is used to trigger the task activation.    */
153
 
154
SYMBOL_NAME_LABEL(ll_timer)
155
			pushal
156
			pushw	%ds
157
			pushw	%es
158
			pushw	%fs
159
			pushw	%gs
305 giacomo 160
 
161
			cli
162
 
163
			/* Send ACK to master PIC		*/
164
			movb    $0x20,%al
165
			movl	$0x20,%edx
166
			outb    %al,%dx
2 pj 167
 
168
			movw    $(X_FLATDATA_SEL),%ax
169
			movw    %ax,%ds
170
			movw    %ax,%es
171
 
172
			/* Call wake_up(actual_context) */
173
 
174
			movl	SYMBOL_NAME(ll_clock),%eax
175
			incl 	%eax
176
			movl	%eax,SYMBOL_NAME(ll_clock)
177
 
178
			/* The following could be optimized a little... */
179
			xorl %ebx, %ebx
180
			movw %ss, %bx
181
			/* We must switch to a ``safe stack'' */
182
	/*
183
	 * OK, this is the idea: in %esp we have the address of the
184
	 * stack pointer in the APPLICATION address space...
185
	 * We assume that address spaces are implemented through segments...
186
	 * What we have to do is to add the segment base to %esp:
187
	 *	- Load the GDT base in a register
188
	 *	- Add DS * 8 to that value
189
	 *	- Read the corresponding GDT entry (the segment descriptor)
190
	 *	- Compute the base...
191
	 *	It is (*p & 0xFC) | (*(p +1)  & 0x0F) << 16) | *(p + 2)
192
	 */
193
			movl SYMBOL_NAME(GDT_base), %edi
194
			addl %ebx, %edi
195
			xorl %ebx, %ebx
196
			movb 7(%edi), %bh
197
			movb 4(%edi), %bl
198
			shl $16, %ebx
199
			movw 2(%edi), %bx
200
			/* Is it correct? I think so... Test it!!! */
201
			addl %ebx, %esp
202
			/* Save EBX for returning to our stack... */
203
			movw %ds, %cx
204
			movw %ss, %dx
205
			movw %cx, %ss
206
			pushl %ebx
207
			pushl %edx
208
			cld
209
			movl	SYMBOL_NAME(timermode), %eax
210
			cmpl	$1, %eax
211
			je	oneshot
212
			call    SYMBOL_NAME(periodic_wake_up)
213
			jmp	goon
214
oneshot:		call    SYMBOL_NAME(oneshot_wake_up)
227 giacomo 215
                        jmp     Timer_OK
2 pj 216
goon:
217
			/* This is the overrun test		 */
218
			/* Do it after sending EOI to master PIC */
219
 
220
			movb    $0x0A,%al
221
			movl	$0x020,%edx
222
			outb    %al,%dx
223
			inb     %dx,%al
224
			testb   $1,%al
225
			jz      Timer_OK
226
			movl    $(CLOCK_OVERRUN),%eax
227
			pushl	%eax
228
			call    SYMBOL_NAME(ll_abort)
229
 
230
Timer_OK:
231
			/* Restore ESP */
232
			popl	%edx
233
			popl	%ebx	/* We must subtract it from ESP...*/
234
			subl	%ebx, %esp
235
			movw	%dx, %ss
40 pj 236
 
2 pj 237
#ifdef __VIRCSW__
238
 
239
			movw	SYMBOL_NAME(currCtx), %ax
240
			cmpw    %ax,JmpSel
241
			je      NoPreempt2
242
			movw    %ax,JmpSel
243
			ljmp    JmpZone  /* DISPATCH! */
244
#endif
245
NoPreempt2:
246
 
247
			cmpl	$0, SYMBOL_NAME(last_handler)
248
			je	nohandler
249
			movl	SYMBOL_NAME(last_handler), %ebx
250
			call	*%ebx
251
nohandler:
305 giacomo 252
 
253
			sti
254
 
2 pj 255
			popw	%gs
256
			popw	%fs
257
			popw	%es
258
			popw	%ds
259
			popal
260
			iret