Listing 1—The interrupt handler for DeviceNet messages copies the message from the 82527 into a buffer, saves the length, and frees the 82527 for the next message. The run time is 100 µs.

#define CAN_BASE 0xA000
UCHAR global_CAN_buf[10];
UINT global_event;

// Handles receipt of incoming DeviceNet messages
// The three dots are required in C++ mode
void interrupt far can_isr(...)
{
	UCHAR i, int_source, addr, mailbox, length;

	int_source = peekb(CAN_BASE, 0x5F);  // read interrupt source
	if ((int_source < 3) || (int_source > 7)) return;

	mailbox = int_source - 2;
	for (i=0; i < 10; i++) global_CAN_buf[i] = 0;

	// compute address of config register in mailbox of interest
	addr = 6 + (mailbox << 4);		// multiply by 16
	length = peekb(CAN_BASE, addr);     	// read message length
	length = length >> 4;
	global_CAN_buf[9] = length;   		// save message length
	for (i=0; i < length; i++){     		// move message from 82527
	  addr++;
	  global_CAN_buf[i] = peekb(CAN_BASE, addr);
	}
	addr = 1 + (mailbox << 4); 	  	// point to control 1 reg.
	pokeb(CAN_BASE, addr, 0x55);		// clear INT_PENDING bit
	addr--;		// point to control 0 reg.
	pokeb(CAN_BASE, addr, 0xFD);		// clear NEWDAT
	global_event |= 0x0001 << mailbox; // set bit in global_event
	outp(0x20,0x20);                     		// nonspecific EOI
}