Subversion Repositories shark

Rev

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