Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!hp-pcd!hpfcso!hplisa!hpislx!larryc From: larryc@hpislx.HP.COM (Larry Corsa) Newsgroups: comp.sys.hp Subject: Re: Needed: Interrupt handler. Message-ID: <8480004@hpislx.HP.COM> Date: 1 Nov 90 19:02:48 GMT References: <1628.2727168f@iccgcc.decnet.ab.com> Organization: HP Measurement Systems Op., Loveland, CO, USA Lines: 231 / hpislx:comp.sys.hp / kay@iccgcc.decnet.ab.com / 3:45 pm Oct 25, 1990 / >> We're running HPUX 7.0 on a V/360 VXI workstation. We've installed a V >> card in the VXI rack. Can anyone tell us, or better yet, give us some >> code, on how to establish an interrupt handler for the VME card? >> >> We have the VXI drivers software but the interrupt support doesn't seem >> apply to VME devices. Au contraire, mon frere. VXI is a (mostly) pure superset of the VME bus. The impurities stem mostly from VME's lack of definition of P2 functionality. Most of the V/360's VXI driver is centered around VXI devices (obviously) which support a set of standard registers (card ID, etc.) and *may* support high level protocols (word serial). Well-behaved VME devices are certainly welcome. I've attached some example code for an HP B-sized card. This card does implement the VXI device registers and so can identify itself to the VXI resource manager, but is otherwise a pretty straightforward register-based card, ala VME. The incremental effort required to get interrupts from a pure VME card is: 1) identify your board to the resource mgr by using the "vmedevices" config file. 2) instead of mapping a VXI device's A16 registers, you'll use vxi_map_a24 (or a32) to get a pointer to the start of your card's registers. 3) when the interrupt occurs, if the interrupt_struct-->cause is VXI_INT_VME, the mask will be the IACK value defined by your card. Regards, Larry Corsa Technical Support Engineer Hewlett-Packard Company Measurement Systems Operation 815 14th Street SW Mail Stop CU312 Loveland, CO 80537, USA larryc@hpisla.lvld.hp.com /*file: E1332Afreq.c */ /********************************************************************* * Program for frequency measurements using HP E1332A Counter * *********************************************************************/ #include #include #include "sys/vxi.h" /*source file for HP V/360 VXI drivers*/ #define logical_address 48 /*Logical Address of HP E1332A*/ /*Initialize interrupt flag*/ int i_flag =0; typedef unsigned short word; typedef struct device_registers { word id_register; word devtype_register; word statuscontrol_register; word reserved_register; word cmdresponse_register; word parameter_register; word reserved2_register; word ivector_register; }DEVICE_REGISTERS; /*Function to reset the HP E1332A counter*/ void reset_dac32A(d32A_ptr) DEVICE_REGISTERS *d32A_ptr; { int l; /*send reset command 15 to command register*/ d32A_ptr->cmdresponse_register=15; /*wait for READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&1)==0); /*send parameter to begin reset activity*/ d32A_ptr->parameter_register=0; /*Wait a few microseconds to allow reset activity to complete*/ for (l=0;l<100;l++) {} } /*Function to send commands and parameter to HP E1332A counter*/ void dac32A_send(d32A_ptr,command,parameter) DEVICE_REGISTERS *d32A_ptr; int command, parameter; { /*wait for READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&1)==0); /*send the command to the command register*/ d32A_ptr->cmdresponse_register=command; /*wait for the READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&1)==0); /*send the parameter to the parameter register*/ d32A_ptr->parameter_register=parameter; } /*Function to retrieve and convert the counter reading*/ float d32A_read(d32A_ptr,command,channel) DEVICE_REGISTERS *d32A_ptr; { float result, r_exp = 1; int k; unsigned short data_word; /*wait for DONE, QUERY RESPONSE and READY bits to become valid*/ while(((d32A_ptr->statuscontrol_register)&0x83)!=0x83); /*get the first byte of data*/ data_word = ((d32A_ptr->cmdresponse_register)&0xff); /*check for overflow*/ if ((data_word &1) == 1) { printf("\n\nOVERFLOW OCCURRED - DATA INVALID\n"); exit(0); } /*place first byte in the result variable*/ result = data_word << 32; /*wait for QUERY RESPONSE REGISTER READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&2)==0); /*get second byte of data*/ data_word = ((d32A_ptr->cmdresponse_register)&0xff); result = result + (data_word << 24); /*wait for QUERY RESPONSE REGISTER READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&2)==0); /*get third byte of data*/ data_word = ((d32A_ptr->cmdresponse_register)&0xff); result = result +(data_word << 16); /*wait for QUERY RESPONSE REGISTER READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&2)==0); /*get fourth byte of data*/ data_word = ((d32A_ptr->cmdresponse_register)&0xff); result = result + (data_word << 8); /*wait for QUERY RESPONSE REGISTER READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&2)==0); /*get fifth byte of data*/ data_word = ((d32A_ptr->cmdresponse_register)&0xff); result = result + data_word; /*wait for QUERY RESPONSE REGISTER READY bit to become valid*/ while(((d32A_ptr->statuscontrol_register)&2)==0); /*get sixth byte of data*/ data_word = ((d32A_ptr->cmdresponse_register)&0xff); /*convert sixth byte, the exponent*/ for (k=data_word-128; k<0; k++) { r_exp = r_exp/2; } result = result * r_exp; return result; } /*Interrupt handler routine*/ int handler(eid,causevec) int eid; struct interrupt_struct *causevec; { /*set the interrupt flag to alert main program that counter has reading*/ i_flag=1; /*ensure the correct interrupt has occurred*/ if ((causevec->mask&0xffff) != 0xef30) { printf("\n\nReceived incorrect interrupt vector\n"); printf("Expected interrupt from E1332A at logical address 48\n"); printf("\n Received interrupt vector: %x HEX\n",causevec->mask&0xffff); printf(" Expecting: ef30 HEX \n"); printf(" ef HEX --> channel one frequency complete\n"); printf(" 30 HEX --> logical address of 48\n"); exit(0); } } main() { int eid; DEVICE_REGISTERS *dev; int i; struct interrupt_struct causevec; float reading; /*Open the HP V/360 VXI interface*/ eid=open("/dev/vxi/primary",O_RDWR); if(eid<0){ perror("open"); exit(1); } /*Mask for VME interrupts*/ causevec.cause = 0x2; /*Set up interrupt handler for interrupting device*/ io_on_interrupt(eid,&causevec,handler); /*Enable interrupts on on the VXI interface*/ io_interrupt_ctl(eid,1); /*Retrieve the pointer for the A16 registers of the device*/ dev=(DEVICE_REGISTERS *)vxi_get_a16_addr(eid,logical_address); /*Call the function to reset the counter*/ reset_dac32A(dev); /*Set the function: Frequency with 1024 msec gate time*/ dac32A_send(dev,4,9); /*Let computer perform some other task while waiting for interrupt*/ for (i=0;i<3500;i++) { printf("\r%i",i); /*check interrupt flag and if set, end looping*/ if (i_flag ==1) { i=4000; } } /*Send the command to read the result*/ dac32A_send(dev,14,0); /*Call the function to retrieve and convert the reading*/ reading = d32A_read(dev,14,0); /*Print out the measured frequency*/ printf("\nFrequency is %.1f \n",reading); }