Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 May 2007 14:57:30 GMT
From:      Alexey Tarasov <taleks@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 119672 for review
Message-ID:  <200705111457.l4BEvUfs055031@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=119672

Change 119672 by taleks@taleks_th on 2007/05/11 14:56:54

	Updated ISR handler for real/vm86 mode, udated pxe_core code with PXE API calls.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/btx_mod/btx/btx.S#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.h#3 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_isr.S#2 edit

Differences ...

==== //depot/projects/soc2007/taleks-pxe_http/btx_mod/btx/btx.S#4 (text+ko) ====

@@ -402,7 +402,6 @@
 		popl %es			#  data
 		movl %esp,%ebx			# Stack frame
 		movl $dmpfmt,%esi		# Dump format string
-		movl $MEM_BUF,%edi		# Buffer
 		pushl %edi			# Dump to
 		call dump			#  buffer
 		popl %esi			#  and
@@ -707,10 +706,14 @@
 		jmp int_hw			# V86 int 0x70
 		push $0x71			# Int 0x29: IRQ9
 		jmp int_hw			# V86 int 0x71
-		push $0x72			# Int 0x2a: IRQ10
-		jmp int_hw			# V86 int 0x72
+#		push $0x72			# Int 0x2a: IRQ10
+#		jmp int_hw			# V86 int 0x72
+# just to test, my NIC's IRQ
+		nop
+		jmp user_isr_call
 		push $0x73			# Int 0x2b: IRQ11
 		jmp int_hw			# V86 int 0x73
+		jmp user_isr_call
 		push $0x74			# Int 0x2c: IRQ12
 		jmp int_hw			# V86 int 0x74
 		push $0x75			# Int 0x2d: IRQ13
@@ -874,58 +877,101 @@
  *  will be run user_isr_call, which role is to run provided function
  *  in user space.
  */
-intx30.2:	xorl %eax,%eax			# clear eax
+
+
+intx30.2:
+		cli
+		pushl %edi
+		pushl %ebx
+		pushw %ds
+		pushw %dx
+
+		pushl %ss			# Set up
+		popl %ds			#  registers
+		
+
+ 		movl $MEM_USR,%ebx		# User base address
+		addl 0x18(%esp,1),%ebx		# getting user stack head
+		addl $0x04, %ebx		#  first parameter
+
+		movl (%ebx), %eax
+		movw 0x2(%ebx), %dx
+		xchgw %dx, %bx
 
 /*
  * updating call gate
  */
- 		mov gdtdesc,%edi		# calculating descriptors entry
- 		add $SEL_CALLGATE,%edi		# pointing callgate selector
-
-		popl %eax			# got 32bit offset to handler
-
-		movw %ax,(%edi)			# +0: store offset 00..15
-		shr $0x10,%eax			# getting high word
-		add $0x06,%edi			# +6:
-		mov %ax,(%edi)			#   handler offset 16..31
+		movl $callgate, %edi
+		movw %ax, (%edi)		# +0: store offset 00..15
+		shr $0x10 ,%eax			# getting high word
+		movw %ax, 0x06(%edi)		# +6: handler offset 16..31
 /*
  * installing handler
- */
- 		xor %ax,%ax			# clear ax
- 		pop %ax				# getting interrupt number
- 		mov $0x08, %bl			#
- 		mulb %bl			#
-
-		mov $MEM_IDT,%di		# point to IDT.
-		add %ax,%di			# calculate entry
-
-		mov $SEL_SCODE,%dh		# supervisor code selector
-		mov user_isr_call,%ax		# tramp address
-
-		mov $0x8e,%dl			# i386+ interrupt gate, DPL=0
-
-		mov %ax,(%edi)			# 0: handler offset 0..15
-		mov %dh,0x2(%edi)		# +2: dest selector
-						# +4: 000:word_count=0
-		mov %dl,0x5(%edi)		# +5: P:DPL:type
-						# +6: handler offset 16..31
+ */		
+#		xorl %eax, %eax			# clear 
+#		movw %bx, %ax			# getting interrupt number
+# 		mov $0x08, %bl			# calculating offset
+# 		mulb %bl			#  to IDT entry
+# #
+#		movl $MEM_IDT,%edi		# base address of IDT.
+#		addl %eax, %edi			# calculate address of entry
+#
+# 		movb $SEL_SCODE, %dh		# supervisor code selector
+#		mov  user_isr_call, %ax		# tramp address
+#  		movb $0x8e, %dl			# i386+ interrupt gate, DPL=0
+# 
+# 		movw %ax,(%edi)			# 0: handler offset 0..15
+# 		movb  %dh, 0x2(%edi)		# +2: dest selector
+# 						# +4: 000:word_count=0
+# 		movb %dl, 0x5(%edi)		# +5: P:DPL:type
+ 						# +6: handler offset 16..31
 /*
  *  NOTE: it seems nothing else must be done
  */
+
+		popw %dx
+		popw %ds
+		popl %ebx		
+		popl %edi
+		sti	
 		iret				# return from syscall
 
 user_isr_call:
 /*
  * NOTE: isr must use lret to return and restore SS, ESP, CS, EIP.
 */
-		push %ds			# saving ds
-		mov $SEL_UDATA,%ax		#
-		mov %ax,%ds			# setting it to userspace data
-						# cs is updated from selector
+		pushl %ds			# saving ds
+		pushl %edi
+		movl $SEL_SDATA, %eax		#
+		movl %eax, %ds			
+						
+		movl $callgate, %edi
+		movw (%edi), %ax
+		popl %edi		
+
+		cmpw $0x0000, %ax
+		je isr_ret
+		
+#		movl $SEL_UDATA, %eax
+#		movl %eax, %ds 
+#		pushl	%ds
+#		popl	%fs
+#		pushl	%fs
+#		popl	%gs
+#		pushl	%gs
+#		popl	%es
+		
+		
 		lcall $SEL_CALLGATE,$0x00000000	# far call via callgate selector
 						# offset is ignored
-		pop %ds				# restore data segment
+
+isr_ret:
+		
+
+		popl %ds
+
 		iret				# return from interrupt handler
+		
 
 /*
  * Dump structure [EBX] to [EDI], using format string [ESI].
@@ -1159,8 +1205,10 @@
 		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
 		.word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
 		.word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
+#		.word 0xffff,MEM_USR,0xba00,0xcf# SEL_UCODE
+#		.word 0xffff,MEM_USR,0xb200,0xcf# SEL_UDATA		
 		.word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS
-		.word 0x5,   0x0,    0xec00,0x0 # SEL_CALLGATE
+callgate:	.word 0x0, SEL_UCODE,0xec00,0x0 # SEL_CALLGATE				
 gdt.1:
 /*
  * Pseudo-descriptors.
@@ -1228,6 +1276,7 @@
 		.ascii "ss:esp" 		# "ss:esp="
 		.byte 0x80|DMP_MEM|DMP_EOL,0x0	# "00 00 ... 00 00\n"
 		.asciz "BTX halted\n"		# End
+#save_esp:	.word	0x0000,0x0000
 
 /*
  * End of BTX memory.

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#5 (text+ko) ====

@@ -174,7 +174,43 @@
 void
 pxe_core_install_isr()
 {
+	t_PXENV_UNDI_GET_INFORMATION *undi_info =
+		(t_PXENV_UNDI_GET_INFORMATION *)scratch_buffer;
+
+#ifdef PXE_DEBUG
+	printf("pxe_isr_install() called\n");
+#endif
+	bzero(undi_info, sizeof(*undi_info));
+
+	pxe_core_call(PXENV_UNDI_GET_INFORMATION);
+
+	if (undi_info->Status != 0) {
+		printf("pxe_isr_install: failed %x\n", undi_info->Status);
+		return;
+	}
+
+	irq=(uint8_t)(undi_info->IntNumber);
+
+#ifdef PXE_DEBUG
+	printf("pxe_isr_install() info:\n");
+	printf("IRQ: %d\n", undi_info->IntNumber);
+	printf("Base io: %d\n", undi_info->BaseIo);
+	printf("MTU: %d\n", undi_info->MaxTranUnit);
+	printf("RX buffer queue: %d\n", undi_info->RxBufCt);
+	printf("TX buffer queue: %d\n", undi_info->TxBufCt);
+	printf("installing ISR\n");
+#endif
+	uint16_t int_num=(irq < 8) ? irq + 0x08 : irq + 0x68;
+
+	caddr_t isr_addr=pxe_isr-__base;
+	printf("setting interrupt: %d for 0x%x (0x%x, base = 0x%x)\n",
+		int_num, pxe_isr, isr_addr, __base);
 
+	__isr_install(isr_addr, int_num);
+
+#ifdef PXE_DEBUG
+	printf("pxe_isr_install(): success\n");
+#endif
 }
 
 void
@@ -239,10 +275,39 @@
 int
 pxe_core_transmit(pxe_packet *pack)
 {
+	t_PXENV_UNDI_TRANSMIT *undi_send =
+		(t_PXENV_UNDI_TRANSMIT *)scratch_buffer;
+
+	bzero(undi_send, sizeof(*undi_info));
+
+	/* media address */
+	uint_8_t	media_addr[6] = {0,0,0,0,0,0};
+
+	t_PXENV_UNDI_TBD	tbd;
+	tbd.ImmedLength = pack->data_size;	/* packet length */
+	tbd.Xmit.segment = VTOPSEG(pack->data);	/* immediate transmit buffer */
+	tbd.Xmit.offset = VTOPOFF(pack->data);
+	tbd.DataBlkCount = 1 ;			/* one block */
+	tbd.DataBlk[0].TDPtrType = 1;		/* segment:offset type */
+	tbd.DataBlk[0].TDRsvdByte = 0;		/* reserved */
+
+	/* NOTE: if it will work? Check params*/
+	tbd.DataBlk[0].TDDataLen=tbd.ImmedLength; /* size of packet*/
+	tbd.DataBlk[0].TDDataPtr.segment = VTOPSEG(pack->data);;
+	tbd.DataBlk[0].TDDataPtr.offset = VTOPOFF(pack->data);;
 
-	/* UNDI transmit ip packet call*/
+	undi_send->Protocol = P_IP;
+	undi_send->DestAddr.segment = VTOPSEG(media_addr);
+	undi_send->DestAddr.offset  = VTOPOFF(media_addr);
+
+	pxe_core_call(PXENV_UNDI_GET_INFORMATION);
+
+	if (undi_send->Status != 0) {
+		printf("pxe_core_transmit(): failed %x\n", undi_info->Status);
+		return (0);
+	}
 
-	return (0);
+	return (1);
 }
 
 /* flushes pending, aborted, wrong and etc packets */
@@ -267,9 +332,98 @@
 	return (1);
 }
 
+/*
+ *  checks if interrupt handler was executed for our NIC
+ *    (in case of shared IRQs)
+ *  in:
+ *	none
+ *  out:
+ *	0 - not our interrupt, return
+ *	1 - our, must handle receiving
+ */
+int
+pxe_core_is_our()
+{
+	/*
+	 * NOTE: best idea to do it in real mode interrupt handler,
+	 *       The PXE specs suggest fast interrupt handling,
+	 *	 starting handler thread and returning
+	 */
+	t_PXENV_UNDI_ISR *undi_isr =
+		(t_PXENV_UNDI_ISR *)scratch_buffer;
+
+	bzero(undi_isr, sizeof(*undi_isr));
+
+	undi_isr->FuncFlag=PXENV_UNDI_ISR_IN_START;
+	pxe_core_call(PXENV_UNDI_ISR);
+
+	if (undi_isr->Status != 0) {	/* pxe_core_call() failed */
+		/* pretend, failed cause not ours interrupt */
+		return (0);
+	}
+
+	if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_OURS)
+		return (1);
+
+	return (0);
+}
+
+/*
+	0 - failed
+	1 - success
+*/
+int
+pxe_core_get_packet(int func, t_PXENV_UNDI_ISR *undi_isr )
+{
+
+	undi_isr->FuncFlag = func;
+
+	while(1) {	/* cycle to handle busy flag */
+
+		undi_isr->Status = 0;
+
+		pxe_core_call(PXENV_UNDI_ISR);
+
+		if (undi_isr->Status != 0) {
+			/* something gone wrong */
+			return (0);
+		}
+
+		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) {
+			/* nothing to de */
+			break;
+		}
+
+		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
+			/* NIC is busy, wait */
+			sleep(1);
+			continue;
+		}
+
+		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_RECIEVE) {
+			/* that's what we are waiting for */
+			break;
+		}
+
+		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
+			/* transmitted packet */
+			return (0);
+		}
+	}
+
+	return (1);
+}
+
 void
 pxe_core_isr()
 {
+	/*
+	 * NOTE: code here it must be redone to separate receiving thread
+	 *       and interrupt handler.
+	 *       in fact real mode ISR implements pxe_core_is_ours()
+	 *       and modifies __pxe_isr_occured, which must be checked
+	 *	 in receiving queue.
+	 */
 	int	buffer_size = 0;  /* total size of packet*/
 	int	protocol = 0;     /* protocol */
 	int	recieved = 0;     /* bytes received to buffer */
@@ -282,9 +436,27 @@
 				 * real packet struct
 				 */
 
-	/*
-	 * TODO: UNDI get buffer size & etc
-	 */
+	if (!pxe_core_is_ours()) {
+		return;		/* not ours interrupt, handling is over */
+	}
+
+
+	t_PXENV_UNDI_ISR *undi_isr =
+		(t_PXENV_UNDI_ISR *)scratch_buffer;
+
+	bzero(undi_isr, sizeof(*undi_isr));
+
+	/* starting packet receive cycle */
+	if (0 -- pxe_core_get_packet(PXENV_UNDI_ISR_IN_PROCESS, undi_isr)) {
+		return;
+	}
+
+	buffer_size = undi_isr->BufferLength;
+	protocol = undi_isr->ProtType;
+	frame_size = undi_isr->FrameLength;
+
+/* how to get in this address from userspace, which starts at 0xa800?*/
+/*	frame_data = undi_isr->Frame.segment << 4 + undi_isr->Frame.offset; */
 
 
 	/* we are yet not interested in non-ip packets */
@@ -298,25 +470,26 @@
 	 * and memblock copy
 	 */
 
-/*    if (buffer_size==frame_size) {
+/*	if (buffer_size == frame_size) {*/
 
-        pxe_ip *iphdr = (pxe_ip *)frame_data;
+	pxe_ip *iphdr = (pxe_ip *)frame_data;
 
-        dummy_pack.protocol = protocol;
-        dummy_pack.state = PXE_PACKET_STATE_USING;
-        dummy_pack.data = frame_data;
-        dummy_pack.data_size = frame_size;
-        dummy_pack.user_data = NULL;
+	dummy_pack.protocol = protocol;
+	dummy_pack.state = PXE_PACKET_STATE_USING;
+	dummy_pack.data = frame_data;
+	dummy_pack.data_size = frame_size;
+	dummy_pack.user_data = NULL;
 
-        /* TODO: calc ip checksum /
+        /* TODO: calc ip checksum */
 
-        if (core_protocol[iphdr->protocol]) {
-		if (core_protocol[iphdr->protocol](&dummy_pack, PXE_CORE_FRAG,
-                NULL)) {
+	if (core_protocol[iphdr->protocol]) {
+		if (core_protocol[iphdr->protocol](&dummy_pack,
+			PXE_CORE_FRAG, NULL)) {
 			return;
 		}
 	}
-*/
+/*	}*/
+
 	pack = pxe_core_alloc_packet(buffer_size);
 
 	if (pack == NULL) {
@@ -339,17 +512,25 @@
 	pack->user_data = pack->data;
 
 	while (recieved < buffer_size) {
-		/*
-		 *	UNDI get frame
-		 */
+
+		if (!pxe_core_get_packet(PXENV_UNDI_ISR_GET_NEXT, undi_isr))
+			break;
+
+		frame_size = undi_isr->FrameLength;
+/* how to get in this address from userspace, which starts at 0xa800?*/
+/*	frame_data = undi_isr->Frame.segment << 4 + undi_isr->Frame.offset; */
 
-		frame_size=0;
 
 		pxe_core_recieve(pack, frame_data, frame_size);
 
 		recieved += frame_size;
 	}
 
+	if (recieved < buffer_size) { /* pxe_core_get_packet() in cycle failed */
+		pxe_core_drop(pack);
+		return;
+	}
+
 	pack->user_data = NULL;
 	++packets_received;
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#5 (text+ko) ====


==== //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#4 (text+ko) ====


==== //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.h#3 (text+ko) ====


==== //depot/projects/soc2007/taleks-pxe_http/pxe_isr.S#2 (text+ko) ====

@@ -39,6 +39,7 @@
 chained_irq_seg:	.word	0x0000			# stores original handler for interrupt
 
 original_mask:		.byte	0x00			# stores interrupt mask
+save_int_mask:		.byte	0x00			# stores interrupt mask
 base_ds:		.word	0x0000			# data segment
 s_pxenv_undi_isr:	.word	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0	
 
@@ -57,6 +58,11 @@
 		.word   0x0000				# PXE API entry point segment
 		add $6, %sp				# restore stack
 		ret
+/*
+ * NOTES to think:
+ * 1. it seems BTX programms PIC with ICW4 = 2 (Auto EOI), so half of this code may be omited
+ * 2. do we really need to save chained handler
+ */
 
 /*
  * Adopted from Intel PXE SDK
@@ -98,19 +104,23 @@
  * ACK to each hardware PIC needing ACK.
  */
 
-		movw  __pxe_nic_irq, %ax		# getting irq number
-		movb  %al, %dl				# moving it to dl
-		movb  $I8259_EOI, %al			# set EOI control word 
-
-		cmpb  $0x8, %dl				# is IRQ8-IRQ15?
-		jb    pxe_isr.master			#  no, use pic1
-
-		movw  $I8259_AT_INTR_CTRL_REG,%dx	# send EOI to PIC2
-		outb   %al, %dx                         #
-
-pxe_isr.master: movw  $I8259_EOI_REG, %dx               # send EOI to master
-		outb   %al, %dx				#
-	
+/*
+ * hope AEOI'programmed pic will do it work itself
+ **
+ *		movw  __pxe_nic_irq, %ax		# getting irq number
+ *		movb  %al, %dl				# moving it to dl
+ *		movb  $I8259_EOI, %al			# set EOI control word 
+ *
+ *		cmpb  $0x8, %dl				# is IRQ8-IRQ15?
+ *		jb    pxe_isr.master			#  no, use pic1
+ *
+ *		movw  $I8259_AT_INTR_CTRL_REG,%dx	# send EOI to PIC2
+ *		outb   %al, %dx                         #
+ *
+ * pxe_isr.master: 
+ *		movw  $I8259_EOI_REG, %dx               # send EOI to master
+ *		outb   %al, %dx				#
+ */	
 pxe_isr.exit:	popw  %es				# restore affected registers
 		popw  %di				#
 		popw  %dx				#
@@ -126,42 +136,44 @@
 		sti					# enable interrupts
 		pushf					# push flags
 
-#		pushw %es		
-
-#		movw chained_irq_off+2, %ax
-#		movw %ax, %es
-#		movw chained_irq_off, %bx
-		movl chained_irq_off, %eax
-
-#		call %es:(%bx)                          # call chained handler
-		call *%eax
-
-#		popw %es
+/*
+ *  here is calling of chained interrupt handler. Don't think it' srelly needed now
+ **
+ *		pushw %es		
+ *		movw chained_irq_off+2, %ax
+ *		movw %ax, %es
+ *		movw chained_irq_off, %bx
+ *		call %es:(%bx)                          # call chained handler
+ *		popw %es
+ */
 
 
-
 /*
  * If say "not my interrupt" by passing control to next in handler list, may
  * end up invoking the BIOS, which will turn off the interrupt at the PIC.
  * In case this happens, on return from next-handler call, see if must restore.
  * This only executes when an interrupt is fielded which is not ours to handle.
  */
-		movw    $I8259_PC_INTR_MASK_REG, %dx	# use master
-		movw    __pxe_nic_irq, %bx
-		cmpb    $0x8, %bl                       # is IRQ8-IRQ15?
-		jb      pxe_isr.1                       #  no
-		movw    $I8259_AT_INTR_MASK_REG, %dx	# use PIC2
-	
-pxe_isr.1:	movb    original_mask, %bl		# restore original mask
-		inb     %dx, %al
-		notb    %bl
-		testb   %bl, %al
-		jz      pxe_isr.2
 
-		notb    %bl
-		andb 	%bl, %al
-		outb    %al, %dx
-
+/*
+ *  rely all PIC related actions on BTX
+ **
+ *		movw    $I8259_PC_INTR_MASK_REG, %dx	# use master
+ *		movw    __pxe_nic_irq, %bx
+ *		cmpb    $0x8, %bl                       # is IRQ8-IRQ15?
+ *		jb      pxe_isr.1                       #  no
+ *		movw    $I8259_AT_INTR_MASK_REG, %dx	# use PIC2
+ *	
+ * pxe_isr.1:	movb    save_int_mask, %bl		# get saved mask
+ *		inb     %dx, %al
+ *		notb    %bl
+ *		testb   %bl, %al
+ *		jz      pxe_isr.2
+ *
+ *		notb    %bl
+ *		andb 	%bl, %al
+ *		outb    %al, %dx
+ */
 pxe_isr.2:
 		jmp	pxe_isr.exit
 
@@ -202,8 +214,11 @@
 
 		popw	%es     			# restore affected register
 
-#		call	pxe_mask_int			# TODO: implement
-
+/*
+ *	Masking is not our task
+ **
+ *		call	mask_int			# masking
+ */
 		popf					# restore flags
 
 		popw	%cx				# restore affected registers
@@ -254,7 +269,11 @@
 isr_remove.3:	movl   chained_irq_off, %eax		# getting old chained handler
 		movl   %eax, %es:(%bx)			# restore it
 
-#		call    pxe_unmask_int			# TODO: implement
+/*
+ *  Forget about unmasking for now
+ **
+ *		call    unmask_int			# unmasking
+ */
 
 isr_remove.fin:
 		movl    $0x0, chained_irq_off
@@ -262,3 +281,90 @@
 		popf
 		clc
 		ret
+
+/*
+ * Adopted from Intel PXE SDK
+ *  masks hardware interrupt
+ */
+mask_int:	pushw	%ax     			# saving all affected
+		pushw	%cx				# registers
+		pushw	%dx				#
+
+		movw	__pxe_nic_irq, %bx		# getting irq number
+		cmpw	$0x7, %bx			# see if this master PIC
+		jbe	mask_int.master			#  yes, it's PIC1
+
+		subw	$0x08, %bx			# getting 3bits value
+		movw	$I8259_AT_INTR_MASK_REG, %dx	# setting PIC register to PIC2
+		jmp	mask_int.1
+
+mask_int.master:
+		movw	I8259_PC_INTR_MASK_REG, %dx	# setting master PIC register
+
+mask_int.1:	movw	%bx, %cx
+		andw	$0x07, %cx
+		movw	$0x1, %bl
+		shlb	%cl, %bl
+		andb	original_mask, %bl		# get the original bit for this irq
+
+		pushf					# saving FLAGS register
+		cli					# stop interrupts (IF=0)
+		inb	%dx, %al
+
+		orb	%bl, %al			# change the bit to the orig value
+		outb	%al, %dx
+		popw	%ax				# popping FLAGS
+
+		testw	$0x200, %ax			# checking interrupt flag
+		jz	mask_int.2			#  IF=1
+		sti                                     # starting interrupts
+mask_int.2:
+		popw	%dx
+		popw	%cx
+		popw	%ax
+		ret
+
+/*
+ * Adopted from Intel PXE SDK
+ *  unmasks hardware interrupt
+ */
+unmask_int:	pushw	%ax				# save all affected
+		pushw	%cx				#  registers
+		pushw	%dx				#
+
+		movw	__pxe_nic_irq, %bx		# getting irq number		
+		cmpw	$0x07, %bx			# is it PIC2?
+		jbe	unmask_int.master		#  no, it's master
+
+		subw	$0x08, %bx
+		mov	$I8259_AT_INTR_MASK_REG, %dx	# setting slave PIC register
+		jmp	unmask_int.2
+
+unmask_int.master:
+		mov	$I8259_PC_INTR_MASK_REG, %dx	# setting master PIC register
+
+unmask_int.2:	movw	%bx, %cx
+		andw	$0x07, %cx			# masking first 3 bits
+		movb	$0x01, %bl			# 
+		shlb	%cl, %bl			# shifting 1 bit to left
+		notb	%bl
+
+		movb	%bl, save_int_mask		# saving mask
+
+		pushf                                   # saving FLAGS register
+		cli
+
+		inb	%dx, %al			# sending control word
+		movb	%al, original_mask              # saving mask
+		andb	%bl, %al			# and it with saved
+		outb	%al, %dx			# out result
+
+		popw	%ax				# popping flags
+		testw   $0x200, %ax			# IF==1 ?
+		jz      unmask_int.3			#  yes
+		sti					# set IF=1
+
+unmask_int.3:	popw	%dx                             # restore all affected registers
+		popw	%cx				# 
+		popw	%ax                             #
+		ret



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200705111457.l4BEvUfs055031>