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