Subversion Repositories shark

Rev

Rev 305 | Go to most recent revision | 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
			/* Send ACK to APIC		*/
62
			movl    $0xFEE000B0,%ebx
63
                        movl    $0,(%ebx)
64
 
299 giacomo 65
			movw    $(X_FLATDATA_SEL),%ax
66
			movw    %ax,%ds
67
			movw    %ax,%es
68
 
69
			/* Call wake_up(actual_context) */
70
 
71
			movl	SYMBOL_NAME(ll_clock),%eax
72
			incl 	%eax
73
			movl	%eax,SYMBOL_NAME(ll_clock)
74
 
75
			/* The following could be optimized a little... */
76
			xorl %ebx, %ebx
77
			movw %ss, %bx
78
			/* We must switch to a ``safe stack'' */
79
	/*
80
	 * OK, this is the idea: in %esp we have the address of the
81
	 * stack pointer in the APPLICATION address space...
82
	 * We assume that address spaces are implemented through segments...
83
	 * What we have to do is to add the segment base to %esp:
84
	 *	- Load the GDT base in a register
85
	 *	- Add DS * 8 to that value
86
	 *	- Read the corresponding GDT entry (the segment descriptor)
87
	 *	- Compute the base...
88
	 *	It is (*p & 0xFC) | (*(p +1)  & 0x0F) << 16) | *(p + 2)
89
	 */
90
			movl SYMBOL_NAME(GDT_base), %edi
91
			addl %ebx, %edi
92
			xorl %ebx, %ebx
93
			movb 7(%edi), %bh
94
			movb 4(%edi), %bl
95
			shl $16, %ebx
96
			movw 2(%edi), %bx
97
			/* Is it correct? I think so... Test it!!! */
98
			addl %ebx, %esp
99
			/* Save EBX for returning to our stack... */
100
			movw %ds, %cx
101
			movw %ss, %dx
102
			movw %cx, %ss
103
			pushl %ebx
104
			pushl %edx
105
			cld
106
			movl	SYMBOL_NAME(timermode), %eax
107
			cmpl	$1, %eax
108
			je	apic_oneshot
109
			call    SYMBOL_NAME(periodic_wake_up)
110
			jmp	apic_Timer_OK
111
apic_oneshot:		call    SYMBOL_NAME(oneshot_wake_up)
112
apic_Timer_OK:
113
			/* Restore ESP */
114
			popl	%edx
115
			popl	%ebx	/* We must subtract it from ESP...*/
116
			subl	%ebx, %esp
117
			movw	%dx, %ss
118
 
119
#ifdef __VIRCSW__
120
 
121
			movw	SYMBOL_NAME(currCtx), %ax
122
			cmpw    %ax,JmpSel
123
			je      apic_NoPreempt2
124
			movw    %ax,JmpSel
125
			ljmp    JmpZone /* DISPATCH! */
126
#endif
127
apic_NoPreempt2:
128
 
129
			cmpl	$0, SYMBOL_NAME(last_handler)
130
			je	apic_nohandler
131
			movl	SYMBOL_NAME(last_handler), %ebx
132
			call	*%ebx
133
apic_nohandler:
305 giacomo 134
 
299 giacomo 135
			popw	%gs
136
			popw	%fs
137
			popw	%es
138
			popw	%ds
139
			popal
140
			iret
141
 
2 pj 142
		.globl SYMBOL_NAME(ll_timer)
143
/* This is the timer handler; it reloads for safety the DS register; this   */
144
/* prevents from mess when timer interrupts linear access to memory (not in */
145
/* ELF address space); then EOI is sent in order to detect timer overrun    */
146
/* The high level kernel procedure wake_up() is called to perform the 	    */
147
/* preeption at higher level (process descriptos); the resulting context    */
148
/* if different from the old one is used to trigger the task activation.    */
149
 
150
SYMBOL_NAME_LABEL(ll_timer)
151
			pushal
152
			pushw	%ds
153
			pushw	%es
154
			pushw	%fs
155
			pushw	%gs
305 giacomo 156
 
157
			/* Send ACK to master PIC		*/
158
			movb    $0x20,%al
159
			movl	$0x20,%edx
160
			outb    %al,%dx
2 pj 161
 
162
			movw    $(X_FLATDATA_SEL),%ax
163
			movw    %ax,%ds
164
			movw    %ax,%es
165
 
166
			/* Call wake_up(actual_context) */
167
 
168
			movl	SYMBOL_NAME(ll_clock),%eax
169
			incl 	%eax
170
			movl	%eax,SYMBOL_NAME(ll_clock)
171
 
172
			/* The following could be optimized a little... */
173
			xorl %ebx, %ebx
174
			movw %ss, %bx
175
			/* We must switch to a ``safe stack'' */
176
	/*
177
	 * OK, this is the idea: in %esp we have the address of the
178
	 * stack pointer in the APPLICATION address space...
179
	 * We assume that address spaces are implemented through segments...
180
	 * What we have to do is to add the segment base to %esp:
181
	 *	- Load the GDT base in a register
182
	 *	- Add DS * 8 to that value
183
	 *	- Read the corresponding GDT entry (the segment descriptor)
184
	 *	- Compute the base...
185
	 *	It is (*p & 0xFC) | (*(p +1)  & 0x0F) << 16) | *(p + 2)
186
	 */
187
			movl SYMBOL_NAME(GDT_base), %edi
188
			addl %ebx, %edi
189
			xorl %ebx, %ebx
190
			movb 7(%edi), %bh
191
			movb 4(%edi), %bl
192
			shl $16, %ebx
193
			movw 2(%edi), %bx
194
			/* Is it correct? I think so... Test it!!! */
195
			addl %ebx, %esp
196
			/* Save EBX for returning to our stack... */
197
			movw %ds, %cx
198
			movw %ss, %dx
199
			movw %cx, %ss
200
			pushl %ebx
201
			pushl %edx
202
			cld
203
			movl	SYMBOL_NAME(timermode), %eax
204
			cmpl	$1, %eax
205
			je	oneshot
206
			call    SYMBOL_NAME(periodic_wake_up)
207
			jmp	goon
208
oneshot:		call    SYMBOL_NAME(oneshot_wake_up)
227 giacomo 209
                        jmp     Timer_OK
2 pj 210
goon:
211
			/* This is the overrun test		 */
212
			/* Do it after sending EOI to master PIC */
213
 
214
			movb    $0x0A,%al
215
			movl	$0x020,%edx
216
			outb    %al,%dx
217
			inb     %dx,%al
218
			testb   $1,%al
219
			jz      Timer_OK
220
			movl    $(CLOCK_OVERRUN),%eax
221
			pushl	%eax
222
			call    SYMBOL_NAME(ll_abort)
223
 
224
Timer_OK:
225
			/* Restore ESP */
226
			popl	%edx
227
			popl	%ebx	/* We must subtract it from ESP...*/
228
			subl	%ebx, %esp
229
			movw	%dx, %ss
40 pj 230
 
2 pj 231
#ifdef __VIRCSW__
232
 
233
			movw	SYMBOL_NAME(currCtx), %ax
234
			cmpw    %ax,JmpSel
235
			je      NoPreempt2
236
			movw    %ax,JmpSel
237
			ljmp    JmpZone  /* DISPATCH! */
238
#endif
239
NoPreempt2:
240
 
241
			cmpl	$0, SYMBOL_NAME(last_handler)
242
			je	nohandler
243
			movl	SYMBOL_NAME(last_handler), %ebx
244
			call	*%ebx
245
nohandler:
305 giacomo 246
 
2 pj 247
			popw	%gs
248
			popw	%fs
249
			popw	%es
250
			popw	%ds
251
			popal
252
			iret