1/*- 2 * Copyright (C) 1989,90 W. Jolitz 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)icu.s 7.7 (Berkeley) 10/11/92 12 */ 13 14 15 .data 16 .globl _imen 17 .globl _cpl 18_cpl: .long 0xffff # current priority level (all off) 19_imen: .long 0xffff # interrupt mask enable (all off) 20 .globl _highmask 21_highmask: .long 0xffff 22 .globl _ttymask 23_ttymask: .long 0 24 .globl _biomask 25_biomask: .long 0 26 .globl _netmask 27_netmask: .long 0 28 .globl _isa_intr 29_isa_intr: .space 16*4 30 31 .text 32#include <net/netisr.h> 33 34#define DONET(s, c) ; \ 35 .globl c ; \ 36 btrl $ s ,_netisr ; \ 37 jnb 1f ; \ 38 call c ; \ 391: 40 41/* 42 * Handle return from interrupt after device handler finishes 43 * 44 * register usage: 45 * 46 * %ebx is cpl we are going back to 47 * %esi is 0 if returning to kernel mode 48 * 49 * Note that these registers will be preserved though C calls, 50 * such as the network interrupt routines. 51 */ 52doreti: 53 cli 54 popl %ebx # flush unit number 55 popl %ebx # get previous priority 56 # now interrupt frame is a trap frame! 57 58 /* compensate for drivers that return with non-zero cpl */ 59 movl 0x34(%esp), %esi /* cs */ 60 andl $3, %esi 61 jz 1f 62 63return_to_user_mode: /* entry point from trap and syscall return */ 64 65 /* return cs is for user mode: force 0 cpl */ 66 xorl %ebx,%ebx 671: 68 69 /* like splx(%ebx), except without special 0 handling */ 70 cli 71 movl %ebx, %eax 72 movw %ax,_cpl 73 orw _imen,%ax 74 outb %al, $ IO_ICU1+1 75 movb %ah, %al 76 outb %al, $ IO_ICU2+1 77 78 /* return immediately if previous cpl was non-zero */ 79 cmpw $0, %bx 80 jnz just_return 81 82 /* do network stuff, if requested, even if returning to kernel mode */ 83 cmpl $0,_netisr 84 jne donet 85 86 /* if (returning to user mode && astpending), go back to trap 87 * (check astpending first since it is more likely to be false) 88 */ 89 cmpl $0,_astpending 90 je just_return 91 92 testl %esi, %esi 93 jz just_return 94 95 /* we need to go back to trap */ 96 popl %es 97 popl %ds 98 popal 99 addl $8,%esp 100 101 pushl $0 102 TRAP (T_ASTFLT) 103 /* this doesn't return here ... instead it goes though 104 * calltrap in locore.s 105 */ 106 107donet: 108 /* like splnet(), except we know the current pri is 0 */ 109 cli 110 movw _netmask, %ax 111 movw %ax,_cpl 112 orw _imen,%ax 113 outb %al, $ IO_ICU1+1 114 movb %ah, %al 115 outb %al, $ IO_ICU2+1 116 sti 117 118 DONET(NETISR_RAW,_rawintr) 119#ifdef INET 120 DONET(NETISR_IP,_ipintr) 121 DONET(NETISR_ARP,_arpintr) 122#endif 123#ifdef IMP 124 DONET(NETISR_IMP,_impintr) 125#endif 126#ifdef NS 127 DONET(NETISR_NS,_nsintr) 128#endif 129#ifdef ISO 130 DONET(NETISR_ISO,_clnlintr) 131#endif 132#ifdef CCITT 133 DONET(NETISR_CCITT,_hdintr) 134#endif 135 136 btrl $ NETISR_SCLK,_netisr 137 jnb return_to_user_mode 138 139 /* like splsoftclock */ 140 cli 141 movw $0x8000, %ax 142 movw %ax,_cpl 143 orw _imen,%ax 144 outb %al, $ IO_ICU1+1 145 movb %ah, %al 146 outb %al, $ IO_ICU2+1 147 sti 148 149 # back to an interrupt frame for a moment 150 pushl %eax 151 pushl $0xff # dummy intr 152 call _softclock 153 leal 8(%esp), %esp 154 jmp return_to_user_mode 155 156just_return: 157 pop %es 158 pop %ds 159 popa 160 leal 8(%esp),%esp 161 iret 162 163/* 164 * Interrupt priority mechanism 165 * 166 * Two flavors -- imlXX masks relative to ISA noemenclature (for PC compat sw) 167 * -- splXX masks with group mechanism for BSD purposes 168 */ 169 170 .globl _splhigh 171 .globl _splclock 172_splhigh: 173_splclock: 174 cli # disable interrupts 175 movw $0xffff,%ax # set new priority level 176 movw %ax,%dx 177 # orw _imen,%ax # mask off those not enabled yet 178 movw %ax,%cx 179 outb %al,$ IO_ICU1+1 /* update icu's */ 180 movb %ah,%al 181 outb %al,$ IO_ICU2+1 182 movzwl _cpl,%eax # return old priority 183 movw %dx,_cpl # set new priority level 184 sti # enable interrupts 185 ret 186 187 .globl _spltty # block clists 188_spltty: 189 cli # disable interrupts 190 movw _cpl,%ax 191 orw _ttymask,%ax 192 movw %ax,%dx 193 orw _imen,%ax # mask off those not enabled yet 194 movw %ax,%cx 195 outb %al,$ IO_ICU1+1 /* update icu's */ 196 movb %ah,%al 197 outb %al,$ IO_ICU2+1 198 movzwl _cpl,%eax # return old priority 199 movw %dx,_cpl # set new priority level 200 sti # enable interrupts 201 ret 202 203 .globl _splimp 204 .globl _splnet 205_splimp: 206_splnet: 207 cli # disable interrupts 208 movw _cpl,%ax 209 orw _netmask,%ax 210 movw %ax,%dx 211 orw _imen,%ax # mask off those not enabled yet 212 movw %ax,%cx 213 outb %al,$ IO_ICU1+1 /* update icu's */ 214 movb %ah,%al 215 outb %al,$ IO_ICU2+1 216 movzwl _cpl,%eax # return old priority 217 movw %dx,_cpl # set new priority level 218 sti # enable interrupts 219 ret 220 221 .globl _splbio 222_splbio: 223 cli # disable interrupts 224 movw _cpl,%ax 225 orw _biomask,%ax 226 movw %ax,%dx 227 orw _imen,%ax # mask off those not enabled yet 228 movw %ax,%cx 229 outb %al,$ IO_ICU1+1 /* update icu's */ 230 movb %ah,%al 231 outb %al,$ IO_ICU2+1 232 movzwl _cpl,%eax # return old priority 233 movw %dx,_cpl # set new priority level 234 sti # enable interrupts 235 ret 236 237 .globl _splsoftclock 238_splsoftclock: 239 cli # disable interrupts 240 movw _cpl,%ax 241 orw $0x8000,%ax # set new priority level 242 movw %ax,%dx 243 orw _imen,%ax # mask off those not enabled yet 244 movw %ax,%cx 245 outb %al,$ IO_ICU1+1 /* update icu's */ 246 movb %ah,%al 247 outb %al,$ IO_ICU2+1 248 movzwl _cpl,%eax # return old priority 249 movw %dx,_cpl # set new priority level 250 sti # enable interrupts 251 ret 252 253 .globl _splnone 254 .globl _spl0 255_splnone: 256_spl0: 257 cli # disable interrupts 258 pushl _cpl # save old priority 259 movw _cpl,%ax 260 orw _netmask,%ax # mask off those network devices 261 movw %ax,_cpl # set new priority level 262 orw _imen,%ax # mask off those not enabled yet 263 outb %al,$ IO_ICU1+1 /* update icu's */ 264 movb %ah,%al 265 outb %al,$ IO_ICU2+1 266 sti # enable interrupts 267 268 DONET(NETISR_RAW,_rawintr) 269#ifdef INET 270 DONET(NETISR_IP,_ipintr) 271 DONET(NETISR_ARP,_arpintr) 272#endif 273#ifdef IMP 274 DONET(NETISR_IMP,_impintr) 275#endif 276#ifdef NS 277 DONET(NETISR_NS,_nsintr) 278#endif 279#ifdef ISO 280 DONET(NETISR_ISO,_clnlintr) 281#endif 282#ifdef CCITT 283 DONET(NETISR_CCITT,_hdintr) 284#endif 285 286 cli # disable interrupts 287 popl _cpl # save old priority 288 nop 289 290 movw $0,%ax # set new priority level 291 movw %ax,%dx 292 orw _imen,%ax # mask off those not enabled yet 293 movw %ax,%cx 294 outb %al,$ IO_ICU1+1 /* update icu's */ 295 movb %ah,%al 296 outb %al,$ IO_ICU2+1 297 movzwl _cpl,%eax # return old priority 298 movw %dx,_cpl # set new priority level 299 sti # enable interrupts 300 ret 301 302 .globl _splx 303_splx: 304 cli # disable interrupts 305 movw 4(%esp),%ax # new priority level 306 movw %ax,%dx 307 cmpw $0,%dx 308 je _spl0 # going to "zero level" is special 309 310 orw _imen,%ax # mask off those not enabled yet 311 movw %ax,%cx 312 outb %al,$ IO_ICU1+1 /* update icu's */ 313 movb %ah,%al 314 outb %al,$ IO_ICU2+1 315 movzwl _cpl,%eax # return old priority 316 movw %dx,_cpl # set new priority level 317 sti # enable interrupts 318 ret 319 320 /* hardware interrupt catcher (IDT 32 - 47) */ 321 .globl _isa_strayintr 322 323IDTVEC(intr0) 324 INTR1(0, _highmask, 0) ; call _isa_strayintr ; INTREXIT1 325 326IDTVEC(intr1) 327 INTR1(1, _highmask, 1) ; call _isa_strayintr ; INTREXIT1 328 329IDTVEC(intr2) 330 INTR1(2, _highmask, 2) ; call _isa_strayintr ; INTREXIT1 331 332IDTVEC(intr3) 333 INTR1(3, _highmask, 3) ; call _isa_strayintr ; INTREXIT1 334 335IDTVEC(intr4) 336 INTR1(4, _highmask, 4) ; call _isa_strayintr ; INTREXIT1 337 338IDTVEC(intr5) 339 INTR1(5, _highmask, 5) ; call _isa_strayintr ; INTREXIT1 340 341IDTVEC(intr6) 342 INTR1(6, _highmask, 6) ; call _isa_strayintr ; INTREXIT1 343 344IDTVEC(intr7) 345 INTR1(7, _highmask, 7) ; call _isa_strayintr ; INTREXIT1 346 347 348IDTVEC(intr8) 349 INTR2(8, _highmask, 8) ; call _isa_strayintr ; INTREXIT2 350 351IDTVEC(intr9) 352 INTR2(9, _highmask, 9) ; call _isa_strayintr ; INTREXIT2 353 354IDTVEC(intr10) 355 INTR2(10, _highmask, 10) ; call _isa_strayintr ; INTREXIT2 356 357IDTVEC(intr11) 358 INTR2(11, _highmask, 11) ; call _isa_strayintr ; INTREXIT2 359 360IDTVEC(intr12) 361 INTR2(12, _highmask, 12) ; call _isa_strayintr ; INTREXIT2 362 363IDTVEC(intr13) 364 INTR2(13, _highmask, 13) ; call _isa_strayintr ; INTREXIT2 365 366IDTVEC(intr14) 367 INTR2(14, _highmask, 14) ; call _isa_strayintr ; INTREXIT2 368 369IDTVEC(intr15) 370 INTR2(15, _highmask, 15) ; call _isa_strayintr ; INTREXIT2 371 372