Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jul 1998 16:22:51 -0700
From:      Mike Smith <mike@smith.net.au>
To:        chanders@timing.com (Craig Anderson)
Cc:        Mike Smith <mike@smith.net.au>, freebsd-hackers@FreeBSD.ORG
Subject:   Re: Using FreeBSD for data acquisition? (long) 
Message-ID:  <199807312322.QAA01183@dingo.cdrom.com>
In-Reply-To: Your message of "Fri, 31 Jul 1998 15:31:37 MDT." <199807312131.PAA04940@count.timing.com> 

next in thread | previous in thread | raw e-mail | index | archive | help

Looks like you might have some race conditions here; see commentary.
Also check the sleep priority; it looks like you might be seeing a 
number of situations where you're coming up only when the timeout 
expires.

> 
> #if !defined(gt401_h)
> #  define gt401_h
> 
> #include <sys/ioccom.h>
> 
> /* units of pt4 are 0.4 x 10^-6 sec */
> 
> #define D_TYPE_NONE 99
> #define D_TYPE_ERROR 1
> #define D_TYPE_TIMETAG 2
> 
> #define MIN_PERIOD_X_10000 1
> #define MAX_PERIOD_X_10000 50000
> 
> typedef struct gt401_read_s
> {
>   short overflow;
>   short d_type;
>   union
>   {
>     struct
>     {
>       unsigned int board_index;
>       long long board_time_tag_usec;
>       unsigned int driver_index;
>       long long driver_board_usec;
>     } tt;
>     struct
>     {
>       short err_code;
>       char err_str[58];
>     } ee;
>   } dd;
> }
> gt401_read;
> 
> #define GT401_START_EVENTS \
> 		_IOW('G', 1, int)
> #define GT401_STOP_EVENTS \
> 		_IO('G', 2)
> #define GT401_GET_HIGH_WATER \
> 		_IOR('G', 3, int)
> #define GT401_CLEAR_HIGH_WATER \
> 		_IO('G', 4)
> 
> #endif /* #if !defined(gt401_h) */
> 
> --==_Exmh_18363059200
> Content-Type: text/plain ; name="Makefile"; charset=us-ascii
> Content-Description: Makefile
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: attachment; filename="Makefile"
> 
> # $Id: Makefile,v 1.12 1998/07/30 17:19:23 chanders Exp $
> 
> =2EPATH:	.
> KMOD	=3D gt401_mod
> SRCS	=3D gt401.c gt401.h ngt401.h
> #MAN4	=3D gt401.4
> #MAN8	=3D gt401in.8
> LN	=3D ln -f -s
> 
> CFLAGS	+=3D \
> 		-I. \
> 		-I/usr/src/sys \
> 		-DGT401_MODULE
> 
> CLEANFILES	+=3D ngt401.h
> 
> ngt401.h:
> 	echo "#define NGT401 1" > ngt401.h
> 
> r0:	gt401_mod.o
> 	cp gt401_mod.o \
> 		/usr/local/tsc/rel/bin
> 
> 
> test03: test03.c
> 	cc -o test03 test03.c
> 
> test04: test04.c
> 	cc -o test04 test04.c
> 
> test05: test05.c
> 	cc -o test05 test05.c
> 
> test06: test06.c
> 	cc -g -o test06 test06.c
> 
> test07: test07.c
> 	cc -g -o test07 test07.c
> 
> test08: test08.c
> 	cc -g -o test08 test08.c
> 
> log_read_counts_980726:	log_read_counts_980726.c
> 	cc -g -o log_read_counts_980726 log_read_counts_980726.c
> 
> counts_to_histogram: counts_to_histogram.c
> 	cc -g -o counts_to_histogram counts_to_histogram.c
> 
> kmem_gt401: kmem_gt401.c
> 	cc -g -o kmem_gt401 kmem_gt401.c
> 
> =2Einclude <bsd.kmod.mk>
> 
> 
> --==_Exmh_18363059200
> Content-Type: text/plain ; name="gt401.c"; charset=us-ascii
> Content-Description: gt401.c
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: attachment; filename="gt401.c"
> 
> 
> #include <sys/errno.h>
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/conf.h>
> #include <sys/signalvar.h>
> #include <sys/proc.h>
> #include <sys/kernel.h>
> 
> #include <machine/clock.h>
> #include <machine/endian.h>
> 
> #include <i386/isa/isa.h>
> #include <i386/isa/isa_device.h>
> #include <i386/isa/timerreg.h>
> #include <i386/isa/icu.h>
> 
> #include "ngt401.h"
> #include "gt401.h"
> 
> #define UNIT(d)		(minor(d) >> 16)
> 
> #define CDEV_MAJOR 90
> #define MAX_GT401_RBUF (4*1024)
> 
> enum
> {
>   io_addr_status_reg =3D 0,
>   io_addr_ram_addr_reg =3D 0,
>   io_addr_cont_reg_1 =3D 1,
>   io_addr_cont_reg_2 =3D 2,
>   io_addr_mux_addr_reg =3D 3,
>   io_addr_mux_data_reg =3D 4,
>   io_addr_8254_data_reg =3D 5,
>   io_addr_us_count0 =3D 6,
>   io_addr_us_count1 =3D 7,
>   io_addr_cmd_ready =3D 7,
>   io_addr_dp_ram =3D 8,
>   io_addr_err_reg =3D 13,
> 
>   dp_ram_lus_page =3D 0,
>   dp_ram_command_first_page =3D 144,
>   dp_ram_status_page =3D 146,
> 
>   mux_54_ctr_0 =3D 0,
>   mux_54_ctr_1 =3D 8,
>   mux_54_ctr_2 =3D 16,
>   mux_54_cont =3D 24,
> 
>   cmd_poll_inner_loop =3D 512,
>   cmd_poll_sleep_loop =3D 20,
>   cmd_poll_usleep =3D 10000,
>   cmd_buf_sz =3D 20,
> 
>   cmd_init =3D 1,
>   cmd_self_test =3D 2,
>   cmd_nop =3D 3,
>   cmd_ext_osc =3D 7,
>   cmd_pulse =3D 8,
>   cmd_tt =3D 9,
>   cmd_chan_off =3D 12,
>   cmd_tt_size =3D 13,
>   cmd_clr_tt =3D 15,
>   cmd_clr_err =3D 20,
> 
>   cont_reg1_src_mask =3D 7,
>   cont_reg1_pulse_en =3D 0x08,
>   cont_reg1_sw_pulse =3D 0x10,
> 
>   status_reg_ready_for_cmd =3D 1,
> 
>   cont_reg2_irq_src_mask =3D 7,
>   cont_reg2_irq_src_chan0 =3D 0,
>   cont_reg2_irq_src_chan1 =3D 1,
>   cont_reg2_irq_src_chan2 =3D 2,
>   cont_reg2_irq_src_chan3 =3D 3,
>   cont_reg2_irq_src_board_proc =3D 4,
>   cont_reg2_irq_src_out0 =3D 5,
>   cont_reg2_irq_src_out1 =3D 6,
>   cont_reg2_irq_src_out2 =3D 7,
>   cont_reg2_intr_en_bit =3D 0x08,
>   cont_reg2_intr_edge_bit =3D 0x10,
> 
>   conn_CLK0 =3D 0,   /* All CLKn values must be consecutive */
>   conn_CLK1 =3D 1,
>   conn_CLK2 =3D 2,
>   conn_EXT_CLK0 =3D 3,   /* All EXT_CLKn values must be consecutive */
>   conn_EXT_CLK1 =3D 4,
>   conn_EXT_CLK2 =3D 5,
>   conn_GATE0 =3D 6,   /* All GATEn values must be consecutive */
>   conn_GATE1 =3D 7,
>   conn_GATE2 =3D 8,
>   conn_EXT_GATE0 =3D 9,   /* All EXT_GATEn values must be consecutive */
>   conn_EXT_GATE1 =3D 10,
>   conn_EXT_GATE2 =3D 11,
>   conn_OUT0 =3D 12,  /* All OUTn values must be consecutive */
>   conn_OUT1 =3D 13,
>   conn_OUT2 =3D 14,
>   conn_IO_CHAN0 =3D 15,  /* All IO_CHANn values must be consecutive */
>   conn_IO_CHAN1 =3D 16,
>   conn_IO_CHAN2 =3D 17,
>   conn_IO_CHAN3 =3D 18,
>   conn_EXT_CHAN0 =3D 19,  /* all EXT_CHANNn values must be consecutive */=
> 
>   conn_EXT_CHAN1 =3D 20,
>   conn_EXT_CHAN2 =3D 21,
>   conn_EXT_CHAN3 =3D 22,
>   conn_TEN_MHZ =3D 23,
>   conn_GATED_TEN_MHZ =3D 24,
>   conn_SW_LOW =3D 25,  /* To force an input low */
>   conn_SW_HIGH =3D 26,  /* To force an input high */
>   conn_SW_INTR =3D 27,  /* For selecting interrupts from */
> 
>   tt_ptr_reg =3D 12,   /* in dpram status page */
>   err_reg =3D 13, /* in dpram status page */
> 
>   tt_edge_neg =3D 0x08,
>   tt_edge_pos =3D 0x10,
> 
>   ten_int =3D 2,
>   ten_int_out =3D 3,
>   ten_ext =3D 4,
> 
>   err_success =3D 0,
>   err_no_io_fd =3D 1,
>   err_timeout =3D 2,
>   err_cmd_sz =3D 3,
>   err_invalid_8254_ctr =3D 4,
>   err_connect_dst =3D 5,
>   err_connect_src =3D 6,
>   err_io_open =3D 7,
>   err_ten_mhz =3D 8,
>   err_irq_src =3D 9
> };
> 
> /* One dev per board */
> static struct isa_device devices[NGT401];
> 
> /*
>  * Setup the per-device structure defining routines used at 'boot' time.
>  */
> static int gt401attach(struct isa_device* devices);
> static int gt401probe(struct isa_device* devices);
> 
> void		gt401intr(int unit);
> 
> static int get_lus (int base_io_port, long long *lus);
> static int mux_matrix_connect (int unit,
> 			       u_short src,
> 			       u_short dst);
> static int pulse_out (int unit,
> 		      int enable,
> 		      int src);
> static int removeIntr(int irq);
> static int send_cmd (int unit, u_char *cmd_buf, u_int size);
> static int set_8254 (int unit,
> 		     u_short counter,
> 		     u_short mode,
> 		     u_short initial_count);
> static int set_irq (int unit,
> 		    int enable,
> 		    int src,
> 		    int edge);
> static int setupIntr(struct isa_device* device,
> 		     int irq,
> 		     inthand2_t* hand,
> 		     int unit,
> 		     u_int* maskp);
> 
> static int start_tt (int unit);
> static int stop_tt (int unit);
> static int get_tt_count (int unit);
> static int get_tt (int unit, long long *tt);
> static int get_status(int unit);
> 
> struct isa_driver gt401driver =3D
> {
>     gt401probe,
>     gt401attach,
>     "gt401"
> };
> 
> static	d_open_t	gt401open;
> static	d_close_t	gt401close;
> static	d_read_t	gt401read;
> static	d_ioctl_t	gt401ioctl;
> static	d_select_t	gt401select;
> 
> static struct cdevsw gt401_cdevsw =3D
> {
>   gt401open,
>   gt401close,
>   gt401read,
>   nowrite,
>   gt401ioctl,
>   nostop,
>   nullreset,
>   nodevtotty,
>   gt401select,
>   nommap,
>   NULL,
>   "gt401",
>   NULL,
>   -1
> };
> 
> struct gt401Unit
> {
>   short inuse;
>   short tagging_active;
> 
>   char * sleep_address;
> 
>   u_char cont_reg1;
>   u_char cont_reg2;
>   u_char mux_control[8];
>   int counts_8254[2];
> 
>   u_int driver_index;
>   u_int max_rbuf_count;
> 
>   /* rbuf_XXX is a ring buffer for reads */
>   short rbuf_count;
>   short rbuf_first;
>   short rbuf_last;
>   gt401_read rbuf [MAX_GT401_RBUF];
> };
> 
> #if 1 /* debug */
> static char * save_sleep_address =3D 0;
> #endif
> static struct gt401Unit gt401Unit[NGT401];
> 
> static int
> get_lus (int base_io_port, long long *lus)
> {
>   char us_count[8] =3D {0};
>   char bb[8] =3D {0};
>   long long *ll_us =3D (long long *)&(us_count[0]);
>   long long *ll_bb =3D (long long *)&(bb[0]);
> 
>   us_count [0] =3D inb (base_io_port + io_addr_us_count0);
> 
>   outb((base_io_port + io_addr_ram_addr_reg), dp_ram_lus_page);
> 
>   inb(base_io_port); /* need a 1us delay */
>   inb(base_io_port);
> 
>   us_count [1] =3D inb (base_io_port + io_addr_us_count1);
> 
>   bb[0] =3D inb (base_io_port + io_addr_dp_ram + 0);
>   bb[1] =3D inb (base_io_port + io_addr_dp_ram + 1);
>   bb[2] =3D inb (base_io_port + io_addr_dp_ram + 2);
>   bb[3] =3D inb (base_io_port + io_addr_dp_ram + 3);
>   bb[4] =3D inb (base_io_port + io_addr_dp_ram + 4);
>   bb[5] =3D inb (base_io_port + io_addr_dp_ram + 5);
>   bb[6] =3D inb (base_io_port + io_addr_dp_ram + 6);
>   bb[7] =3D inb (base_io_port + io_addr_dp_ram + 7);
> 
>   *lus =3D *ll_bb + *ll_us;
> 
>   return 0;
> }
> 
> static int
> gt401attach(struct isa_device* devices)
> {
>   int ii,jj;
> 
>   uprintf ("gt401attach\n");
> 
>   for (ii=3D0; ii<NGT401; ++ii)
>     {
>       gt401Unit[ii].inuse =3D 0;
>       gt401Unit[ii].tagging_active =3D 0;
>       gt401Unit[ii].sleep_address =3D (char *)&(gt401Unit[ii].inuse);
>       gt401Unit[ii].cont_reg1 =3D 0;
>       gt401Unit[ii].cont_reg2 =3D 0;
>       for (jj=3D0; jj<8; ++jj)
> 	gt401Unit[ii].mux_control[jj] =3D 0;
>       gt401Unit[ii].counts_8254[0] =3D 0;
>       gt401Unit[ii].counts_8254[1] =3D 0;
>       gt401Unit[ii].driver_index =3D 0;
>       gt401Unit[ii].max_rbuf_count =3D 0;
>       gt401Unit[ii].rbuf_count =3D 0;
>       gt401Unit[ii].rbuf_first =3D 0;
>       gt401Unit[ii].rbuf_last =3D MAX_GT401_RBUF - 1;
>       for (jj=3D0; jj<MAX_GT401_RBUF; ++jj)
> 	{
> 	  gt401Unit[ii].rbuf[jj].d_type =3D D_TYPE_NONE;
> 	  gt401Unit[ii].rbuf[jj].overflow =3D 0;
> 	}
>     }
> #if 1 /* debug */
>   save_sleep_address =3D gt401Unit[0].sleep_address;
> #endif
>   return 1;
> }
> 
> static int
> gt401close (dev_t dev,
> 	    int flags,
> 	    int fmt,
> 	    struct proc* p)
> {
>   int  unit =3D UNIT(dev);
> 
> #if 1 /* debug */
>   uprintf ("gt401close unit=3D%d\n",unit);
> #endif
> 
>   gt401Unit[unit].tagging_active =3D 0;
>   gt401Unit[unit].inuse =3D 0;
>   set_irq (unit,
> 	   0,
> 	   -1,
> 	   1);
> 
>   return 0;
> }
> static int
> gt401ioctl (dev_t dev,
> 	    int cmd,
> 	    caddr_t data,
> 	    int flag,
> 	    struct proc* p)
> {
>   int  unit =3D UNIT(dev);
> 
>   if ((unit < 0) || (unit >=3D NGT401))
>     return (ENODEV);
> 
>   if (!(devices[unit].id_alive))
>     return (ENODEV);
> 
>   if (!gt401Unit[unit].inuse)
>     return (ENODEV);
> 
>   switch (cmd)
>     {
>     case GT401_START_EVENTS:
>       {
> 	int *       count_x_10000_i;
> 	int         max_counter =3D 0xffff;
> 	double      period;
> 	double      period_x_10000;
> 	double      target_counts_d;
> 	int         target_counts_i;
> 
> #if 0
> 	stop_tt(unit);
> #endif
> 
> 	count_x_10000_i =3D ((int *)data);
> 
> #if 1 /* debug */
> 	uprintf("gt401ioctl: GT401_START_EVENTS arg=3D%d\n",*count_x_10000_i);
> #endif
> 
> 	if (*count_x_10000_i < MIN_PERIOD_X_10000)
> 	  {
> 	    return (EINVAL);
> 	  }
> 	if (*count_x_10000_i > MAX_PERIOD_X_10000)
> 	  {
> 	    return (EINVAL);
> 	  }
> 	period_x_10000 =3D (double)(*count_x_10000_i);
> 	period =3D period_x_10000 / 10000.;
> 	target_counts_d =3D period * 10e6;
> 	target_counts_i =3D (int)target_counts_d;
> 
> 	if (target_counts_i < max_counter)
> 	  {
> 	    gt401Unit[unit].counts_8254[0] =3D target_counts_i;
> 	    gt401Unit[unit].counts_8254[1] =3D 0;
> 	  }
> 	else
> 	  {
> 	    gt401Unit[unit].counts_8254[0] =3D target_counts_i / max_counter;
> 	    ++gt401Unit[unit].counts_8254[0];
> 	    gt401Unit[unit].counts_8254[1] =3D (target_counts_i
> 					      / gt401Unit[unit].counts_8254[0]);
> 	  }
> #if 1 /* debug */
> 	uprintf("gt401ioctl: 8254[0]=3D%d 8254[1]=3D%d\n",
> 		gt401Unit[unit].counts_8254[0],
> 		gt401Unit[unit].counts_8254[1]);
> #endif
> 	if (gt401Unit[unit].counts_8254[1] <=3D 0)
> 	  { /* using one 8254 */
> 	    mux_matrix_connect (unit,
> 				conn_TEN_MHZ,
> 				conn_CLK1);
> 	    mux_matrix_connect (unit,
> 				conn_SW_HIGH,
> 				conn_GATE1);
> 	    set_8254 (unit,
> 		      1,
> 		      3,
> 		      gt401Unit[unit].counts_8254[0]);
> 	    set_irq (unit,
> 		     1,
> 		     conn_OUT1,
> 		     1);
> 	  } /* using one 8254 */
> 	else
> 	  { /* using two 8254's */
> 	    mux_matrix_connect (unit,
> 				conn_TEN_MHZ,
> 				conn_CLK0);
> 	    mux_matrix_connect (unit,
> 				conn_SW_HIGH,
> 				conn_GATE0);
> 	    set_8254 (unit,
> 		      0,
> 		      3,
> 		      gt401Unit[unit].counts_8254[0]);
> 	    mux_matrix_connect (unit,
> 				conn_OUT0,
> 				conn_CLK1);
> 	    mux_matrix_connect (unit,
> 				conn_SW_HIGH,
> 				conn_GATE1);
> 	    set_8254 (unit,
> 		      1,
> 		      3,
> 		      gt401Unit[unit].counts_8254[1]);
> 	    set_irq (unit,
> 		     1,
> 		     conn_OUT1,
> 		     1);
> 	  } /* using two 8254's */
> 
> #if 0 /* debug */
> 	uprintf("gt401ioctl: disable 8254 clock for debug.\n");
> 	mux_matrix_connect (unit,
> 			    conn_SW_LOW,
> 			    conn_GATE0);
> 	mux_matrix_connect (unit,
> 			    conn_SW_LOW,
> 			    conn_GATE1);
> #endif
> 	gt401Unit[unit].tagging_active =3D 1;
> 
> #if 0 /* not yet */
> 	start_tt(unit);
> #endif
> 
>       }
>       break;
>     case GT401_STOP_EVENTS:
>       gt401Unit[unit].tagging_active =3D 0;
> #if 1 /* debug */
>       uprintf("gt401ioctl: GT401_STOP_EVENTS\n");
> #endif
> #if 0 /* not yet */
>       stop_tt(unit);
> #endif
>       set_irq (unit,
> 	       0,
> 	       -1,
> 	       1);
>       break;
>     case GT401_GET_HIGH_WATER:
>       {
> 	int * iarg =3D ((int *)data);
> 	*iarg =3D gt401Unit[unit].max_rbuf_count;
>       }
>       break;
>     case GT401_CLEAR_HIGH_WATER:
>       gt401Unit[unit].max_rbuf_count =3D 0;
>       break;
>     default:
>       return (ENODEV);
>       break;
>     }
>   return 0;
> }
> 
> void
> gt401intr(int unit)
> {
>   int        base_io_port;
>   int        io_cont_reg2;
>   long long  btime_intr;
>   int        rbuf_index;
> 
>   unit =3D 0; /* debug */
>   base_io_port =3D devices[0].id_iobase;
>   get_lus(base_io_port,&btime_intr);
> 
>   if (gt401Unit[0].tagging_active =3D=3D 0)
>     return;
> 
>   ++gt401Unit[0].driver_index;
> 
>   rbuf_index =3D gt401Unit[0].rbuf_last + 1;
>   if (rbuf_index >=3D MAX_GT401_RBUF)
>     rbuf_index =3D 0;

	rbuf_index = (gt401Unit[0].rbuf_last + 1) % MAX_GT401_RBUF;

>   if (gt401Unit[0].rbuf_count >=3D MAX_GT401_RBUF)
>     {
>       gt401Unit[0].rbuf_count =3D MAX_GT401_RBUF - 1;
>       ++gt401Unit[0].rbuf_first;
>       if(gt401Unit[0].rbuf_first >=3D MAX_GT401_RBUF)
> 	gt401Unit[0].rbuf_first =3D 0;
>       gt401Unit[0].rbuf [gt401Unit[0].rbuf_first].overflow =3D 1;
>     }
>   gt401Unit[0].rbuf[rbuf_index].d_type =3D D_TYPE_TIMETAG;
>   gt401Unit[0].rbuf[rbuf_index].dd.tt.driver_index =3D gt401Unit[0].drive=
> r_index;
>   gt401Unit[0].rbuf[rbuf_index].dd.tt.driver_board_usec =3D btime_intr;
>   ++gt401Unit[0].rbuf_count;
>   gt401Unit[0].rbuf_last =3D rbuf_index;
>   if (gt401Unit[0].max_rbuf_count < gt401Unit[0].rbuf_count)
>     gt401Unit[0].max_rbuf_count =3D gt401Unit[0].rbuf_count;
> 
>   io_cont_reg2 =3D base_io_port + io_addr_cont_reg_2;
> 
>   gt401Unit[0].cont_reg2 &=3D ~(cont_reg2_intr_en_bit);
>   outb (io_cont_reg2,
> 	gt401Unit[0].cont_reg2);
> 
>   send_cmd (unit, NULL, 0);
> 
>   if (gt401Unit[0].tagging_active !=3D 0)
>     {
>       gt401Unit[0].cont_reg2 |=3D cont_reg2_intr_en_bit;
>       outb (io_cont_reg2,
> 	    gt401Unit[0].cont_reg2);
>     }
> #if 1 /* debug */
>   if (gt401Unit[0].sleep_address !=3D save_sleep_address)
>     {
>       panic("gt401intr: sleep_address %x !=3D %x",
> 	    gt401Unit[0].sleep_address,
> 	    save_sleep_address);
>     }
> #endif
>   wakeup (gt401Unit[0].sleep_address);
> }
> 
> static int
> gt401open (dev_t dev,
> 	   int flags,
> 	   int fmt,
> 	   struct proc* p)
> {
>   int  unit =3D UNIT(dev);
>   int jj;
> 
> #if 1 /* debug */
>   uprintf("gt401open unit=3D%d\n",unit);
> #endif
> 
>   if ((unit < 0) || (unit >=3D NGT401))
>     return (ENXIO);
> 
>   if (!(devices[unit].id_alive))
>     return (ENXIO);
> 
>   if (gt401Unit[unit].inuse)
>     return (EBUSY);
> 
>   gt401Unit[unit].inuse =3D 1;
>   gt401Unit[unit].tagging_active =3D 0;
>   gt401Unit[unit].rbuf_count =3D 0;
>   gt401Unit[unit].rbuf_first =3D 0;
>   gt401Unit[unit].rbuf_last =3D MAX_GT401_RBUF - 1;
>   for (jj=3D0; jj<MAX_GT401_RBUF; ++jj)
>     {
>       gt401Unit[unit].rbuf[jj].d_type =3D D_TYPE_NONE;
>       gt401Unit[unit].rbuf[jj].overflow =3D 0;
>     }
> 
> #if 1 /* debug */
>   {
>     int addr =3D devices[unit].id_iobase;
>     uprintf("gt401open unit=3D%d io_addr=3D0x%x\n",unit,addr);
>   }
> #endif
> 
>   return 0;
> }
> 
> static int
> gt401probe(struct isa_device* devices)
> {
>   int addr =3D 0x100;
>   int ii;
>   long long time_check[9];
>   long long time_diffs[8];
>   int units =3D 0;
>   long long duration_max;
>   long long duration_min;
>   long long min_max_range;
>   long long min_max_range_check;
> 
>   for (ii=3D0; ii<NGT401; ++ii)
>     {
>       devices[ii].id_alive =3D 0;
>       devices[ii].id_enabled =3D 0;
>     }
> 
>   /* check for gt401 at addr by reading it's time */
>   for (ii=3D0; ii<9; ++ii)
>     {
>       get_lus (addr,&(time_check[ii]));
>       tsleep (&ii, PZERO, "gt401", 10);
>     }
> 
>   for (ii=3D1; ii<9; ++ii)
>     {
>       time_diffs[ii-1] =3D time_check[ii] - time_check[ii-1];
>     }
>   duration_max =3D duration_min =3D time_diffs[0];
>   for (ii=3D0; ii<8; ++ii)
>     {
>       if (duration_max < time_diffs[ii])
> 	duration_max =3D time_diffs[ii];
>       if (duration_min > time_diffs[ii])
> 	duration_min =3D time_diffs[ii];
>     }
>   min_max_range_check =3D duration_min / 2;
>   min_max_range =3D duration_max - duration_min;
> 
> #if 1 /* debug */
>   uprintf("gt401probe addr 0x%x min %d max %d check %d range %d\n",
> 	  addr,
> 	  (int)duration_min,
> 	  (int)duration_max,
> 	  (int)min_max_range_check,
> 	  (int)min_max_range);
> #endif
> 
>   if (duration_min < 5000)
>     {
>       uprintf("gt401probe time diff too small\n");
>       return 0;
>     }
>   if (min_max_range > min_max_range_check)
>     {
>       uprintf("gt401probe time diff too variable\n");
>       return 0;
>     }
> 
>   devices[0].id_unit =3D 0;
>   devices[0].id_iobase =3D addr;
>   devices[0].id_driver =3D &gt401driver;
>   devices[0].id_irq =3D 0;
>   devices[0].id_intr =3D gt401intr;
>   devices[0].id_drq =3D -1;
> #if 0 /* debug */
>   devices[0].id_ri_flags =3D RI_FAST;

You do not want to do this with your current architecture; you can 
never call wakeup() from inside a fast interrupt handler.

> #endif
> 
>   devices[0].id_alive =3D 1;
>   devices[0].id_enabled =3D 1;
> 
>   ++units;
> 
>   return units;
> }
> 
> static int
> gt401read (dev_t dev,
> 	   struct uio* uio,
> 	   int flag)
> {
>   int     left_to_move =3D 0;
>   int     status;
>   int     unit =3D UNIT(dev);
>   int     i_timeout =3D hz / 4;
> 
>   if ((unit < 0) || (unit >=3D NGT401))
>     return (ENODEV);
>   if (!(devices[0].id_alive))
>     return (ENODEV);
>   if (!gt401Unit[0].inuse)
>     return (ENODEV);
> 
>   disable_intr();

This is very bad; don't do this.  Add the driver to one of the 
'standard' interrupt masks and then use splfoo(), or create your own
interrupt mask.

>   for (;;)
>     {
>       if (gt401Unit[0].rbuf_count > 0)
> 	break;
>       enable_intr();

... because there is a race window here.

>       status =3D tsleep (gt401Unit[0].sleep_address,
> 		       (PSWP | PCATCH),
> 		       "gt401",
> 		       i_timeout);
>       if (!((status =3D=3D 0)
> 	    || (status =3D=3D EWOULDBLOCK)))
> 	{
> 	  return (status);
> 	}
>       disable_intr();
>     }
> 
>   left_to_move =3D uio->uio_resid / sizeof(struct gt401_read_s);
> 
>   while (left_to_move > 0)
>     {
>       if (gt401Unit[0].rbuf_count <=3D 0)
> 	break;
> 
>       status =3D uiomove((caddr_t)&(gt401Unit[0].rbuf[gt401Unit[0].rbuf_f=
> irst]),
> 		       sizeof(struct gt401_read_s),
> 		       uio);
>       if (status)
> 	{
> 	  enable_intr();
> 	  return (EFAULT);
> 	}
> 
>       --left_to_move;
> 
>       --gt401Unit[0].rbuf_count;
>       ++gt401Unit[0].rbuf_first;
>       if(gt401Unit[0].rbuf_first >=3D MAX_GT401_RBUF)
> 	gt401Unit[0].rbuf_first =3D 0;

  gt401Unit[0].rbuf_first = (gt401Unit[0].rbuf_first + 1) % MAX_GT401_RBUF;

>       if (gt401Unit[0].rbuf_count <=3D 0)
> 	break;
>     }
> 
>   enable_intr();
>   return 0;
> }

Actually, you can simplify this drastically; there's no need to lock the
ringbuffer unless you are particularly concerned about the overflow
case.  Disabling interrupts for a long time like you do here may cause
loss of timer interrupts, as well as the race above.

static int
gt401read (dev_t dev,
	   struct uio* uio,
	   int flag)
{
	int     left_to_move = 0;
	int     status;
	int     unit = UNIT(dev);
	int     i_timeout = hz / 4;
	int     s, ofs;

	if ((unit < 0) || (unit >= NGT401))
 		return (ENODEV);
	if (!(devices[0].id_alive))
		return (ENODEV);
	if (!gt401Unit[0].inuse)
		return (ENODEV);

	s = splfoo();

	while (gt401Unit[0].rbuf_count == 0) {
		status = tsleep(gt401Unit[0].sleep_address,
				PRIBIO | PCATCH,
				"gt401",
				i_timeout);
		if (!((status == 0) || (status == EWOULDBLOCK))) {
			splx(s);
			return(status);
		}
	}
	splx(s);

	left_to_move = min(gt401Unit[0].rbuf_count, 
			   (uio->uio_resid / sizeof(struct gt401_read_s));
		
	ofs = gt401Unit[0].rbuf_first;
	for (; left_to_move > 0; left_to_move --) {
		if (uiomove((caddr_t)&gt401Unit[0].rbuf[ofs],
			    sizeof(struct gt401_read_s, uio)
			return(EFAULT);
		ofs = (ofs + 1) % GT401_MAX_RBUF;
		gt401Unit[0].rbuf_count--;
	}
	gt401Unit[0].rbuf_first = ofs;
	return(0);
}


> static int
> gt401select (dev_t dev,
> 	     int rw,
> 	     struct proc* p)
> {
>   return 0;
> }
> 
> /*
>  * =
> 
>  */
> #ifdef GT401_MODULE
> 
> #include <sys/exec.h>
> #include <sys/sysent.h>
> #include <sys/sysproto.h>
> #include <sys/lkm.h>
> 
> MOD_DEV(gt401, LM_DT_CHAR, CDEV_MAJOR, &gt401_cdevsw);
> 
> int =
> 
> gt401_load(struct lkm_table* lkmtp, int cmd)
> {
>   int units;
>   int irq =3D 11;
>   int istat;
> 
>   uprintf("Gt401 driver loading, capable of %d board(s)\n", NGT401);
> 
>   units =3D gt401probe (&devices[0]);
>   if (units <=3D 0)
>     {
>       uprintf("gt401 driver: probe failed\n");
>       return (1);
>     }
> 
>   gt401attach (&devices[0]);
> 
>   istat =3D setupIntr (&devices[0],
> 		     irq,
> 		     gt401intr,
> 		     0,
> 		     NULL);
>   if (istat !=3D irq)
>     {
>       uprintf ("gt401 driver: INT %d register failed\n",irq);
>       return (1);
>     }
> 
>   return (0);
> }
> 
> int
> gt401_unload(struct lkm_table* lkmtp, int cmd)
> {
>   int unit;
> 
>   uprintf("Gt401 driver unloading...\n");
> 
>   for (unit=3D0; unit<NGT401; ++unit)
>     {
>       if (devices[unit].id_alive =3D=3D 1)
> 	{
> 	  /** disable interrupts on board */
> 
> 	  if (devices[unit].id_irq !=3D 0)
> 	    {
> 	      uprintf ("removeINTR 0x%x\n",(ffs(devices[unit].id_irq) - 1));
> 	      removeIntr(ffs(devices[unit].id_irq) - 1);
> 	    }
> 	}
>     }
> 
>   return (0);
> }
> 
> /** XXX: /usr/include/lkm.h fails to define this: */
> int gt401_stat(struct lkm_table* lkmtp, int cmd);
> int
> gt401_stat(struct lkm_table* lkmtp, int cmd)
> {
>     return (0);
> }
> 
> int
> gt401_mod(struct lkm_table* lkmtp, int cmd, int ver)
> {
>   DISPATCH(lkmtp, cmd, ver, gt401_load, gt401_unload, gt401_stat);
> }
> 
> #endif /* GT401_MODULE */
> 
> static int
> mux_matrix_connect (int unit,
> 		    u_short src,
> 		    u_short dst)
> {
>   int        base_io_port;
>   int        err;
>   u_short    mux_addr_reg;
>   u_char     mux_addr_reg_val;
>   u_short    mux_data_reg;
>   u_char     src_val;
> 
>   base_io_port =3D devices[unit].id_iobase;
> 
>   err =3D 0;
> 
>   mux_addr_reg =3D base_io_port + io_addr_mux_addr_reg;
>   mux_data_reg =3D base_io_port + io_addr_mux_data_reg;
> 
>   // verify that dst is valid
>   switch (dst)
>     {
>     case conn_IO_CHAN0:
>     case conn_IO_CHAN1:
>     case conn_IO_CHAN2:
>     case conn_IO_CHAN3:
>     case conn_EXT_CHAN0:
>     case conn_EXT_CHAN1:
>     case conn_EXT_CHAN2:
>     case conn_EXT_CHAN3:
>     case conn_CLK0:
>     case conn_CLK1:
>     case conn_CLK2:
>     case conn_GATE0:
>     case conn_GATE1:
>     case conn_GATE2:
>       break;
>     default:
>       err =3D err_connect_dst;
>       return err;
>     }
> 
>   // verify that src is valid
>   switch (dst)
>     {
>     case conn_IO_CHAN0:
>     case conn_IO_CHAN1:
>     case conn_IO_CHAN2:
>     case conn_IO_CHAN3:
>       switch (src)
> 	{
> 	case conn_EXT_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_EXT_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_EXT_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_EXT_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT0:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_OUT1:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_OUT2:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_SW_LOW:
> 	  src_val =3D 7;
> 	  break;
> 	case conn_SW_HIGH:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_src;
> 	  return err;
> 	}
>       break;
>     case conn_EXT_CHAN0:
>       if (src !=3D conn_IO_CHAN0)
> 	{
> 	  err =3D err_connect_src;
> 	  return err;
> 	}
>       break;
>     case conn_EXT_CHAN1:
>       if (src !=3D conn_IO_CHAN1)
> 	{
> 	  err =3D err_connect_src;
> 	  return err;
> 	}
>       break;
>     case conn_EXT_CHAN2:
>       if (src !=3D conn_IO_CHAN2)
> 	{
> 	  err =3D err_connect_src;
> 	  return err;
> 	}
>       break;
>     case conn_EXT_CHAN3:
>       if (src !=3D conn_IO_CHAN3)
> 	{
> 	  err =3D err_connect_src;
> 	  return err;
> 	}
>       break;
>     case conn_CLK0:
>       switch (src)
> 	{
> 	case conn_IO_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_IO_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_IO_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_IO_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT2:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_TEN_MHZ:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_GATED_TEN_MHZ:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_EXT_CLK2:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_dst;
> 	  return err;
> 	}
>       break;
>     case conn_CLK1:
>       switch (src)
> 	{
> 	case conn_IO_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_IO_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_IO_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_IO_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT0:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_TEN_MHZ:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_GATED_TEN_MHZ:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_EXT_CLK2:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_dst;
> 	  return err;
> 	}
>       break;
>     case conn_CLK2:
>       switch (src)
> 	{
> 	case conn_IO_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_IO_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_IO_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_IO_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT1:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_TEN_MHZ:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_GATED_TEN_MHZ:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_EXT_CLK2:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_dst;
> 	  return err;
> 	}
>       break;
>     case conn_GATE0:
>       switch (src)
> 	{
> 	case conn_IO_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_IO_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_IO_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_IO_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT1:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_OUT2:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_SW_LOW:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_SW_HIGH:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_EXT_GATE0:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_dst;
> 	  return err;
> 	}
>       break;
>     case conn_GATE1:
>       switch (src)
> 	{
> 	case conn_IO_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_IO_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_IO_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_IO_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT0:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_OUT2:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_SW_LOW:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_SW_HIGH:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_EXT_GATE1:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_dst;
> 	  return err;
> 	}
>       break;
>     case conn_GATE2:
>       switch (src)
> 	{
> 	case conn_IO_CHAN0:
> 	  src_val =3D 0;
> 	  break;
> 	case conn_IO_CHAN1:
> 	  src_val =3D 1;
> 	  break;
> 	case conn_IO_CHAN2:
> 	  src_val =3D 2;
> 	  break;
> 	case conn_IO_CHAN3:
> 	  src_val =3D 3;
> 	  break;
> 	case conn_OUT0:
> 	  src_val =3D 4;
> 	  break;
> 	case conn_OUT1:
> 	  src_val =3D 5;
> 	  break;
> 	case conn_SW_LOW:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_SW_HIGH:
> 	  src_val =3D 6;
> 	  break;
> 	case conn_EXT_GATE2:
> 	  src_val =3D 7;
> 	  break;
> 	default:
> 	  err =3D err_connect_dst;
> 	  return err;
> 	}
>       break;
>     }
> 
>   // handle sw set gate and chan
>   switch (src)
>     {
>     case conn_SW_LOW:
>       switch (dst)
> 	{
> 	case conn_IO_CHAN0:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~1);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_IO_CHAN1:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~2);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_IO_CHAN2:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~4);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_IO_CHAN3:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~8);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_GATE0:
> 	  mux_addr_reg_val =3D 3;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~1);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_GATE1:
> 	  mux_addr_reg_val =3D 3;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~2);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_GATE2:
> 	  mux_addr_reg_val =3D 3;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~4);
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	}
>       break;
>     case conn_SW_HIGH:
>       switch (dst)
> 	{
> 	case conn_IO_CHAN0:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 1;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_IO_CHAN1:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 2;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_IO_CHAN2:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 4;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_IO_CHAN3:
> 	  mux_addr_reg_val =3D 6;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 8;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_GATE0:
> 	  mux_addr_reg_val =3D 3;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 1;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_GATE1:
> 	  mux_addr_reg_val =3D 3;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 2;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	case conn_GATE2:
> 	  mux_addr_reg_val =3D 3;
> 	  outb (mux_addr_reg, mux_addr_reg_val);
> 	  gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 4;
> 	  outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 	  break;
> 	}
>       break;
>     }
> 
>   // make the connection
> 
>   switch (dst)
>     {
>     case conn_IO_CHAN0:
>       mux_addr_reg_val =3D 4;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~7;
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D src_val;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~1;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_IO_CHAN1:
>       mux_addr_reg_val =3D 4;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~0x38;
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D (src_val << 3);
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~2;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_IO_CHAN2:
>       mux_addr_reg_val =3D 5;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~7;
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D src_val;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~4;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_IO_CHAN3:
>       mux_addr_reg_val =3D 5;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~0x38;
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D (src_val << 3);
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
> 
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D ~8;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
> 
>     case conn_EXT_CHAN0:
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 1;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_EXT_CHAN1:
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 2;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_EXT_CHAN2:
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 4;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_EXT_CHAN3:
>       mux_addr_reg_val =3D 7;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D 8;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
> 
>     case conn_CLK0:
>       mux_addr_reg_val =3D 0;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~7);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D src_val;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_CLK1:
>       mux_addr_reg_val =3D 1;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~7);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D src_val;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_CLK2:
>       mux_addr_reg_val =3D 2;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~7);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D src_val;
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_GATE0:
>       mux_addr_reg_val =3D 0;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~0x38);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D (src_val << 3);
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_GATE1:
>       mux_addr_reg_val =3D 1;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~0x38);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D (src_val << 3);
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     case conn_GATE2:
>       mux_addr_reg_val =3D 2;
>       outb (mux_addr_reg, mux_addr_reg_val);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] &=3D (~0x38);
>       gt401Unit[unit].mux_control[mux_addr_reg_val] |=3D (src_val << 3);
>       outb(mux_data_reg, gt401Unit[unit].mux_control[mux_addr_reg_val]);
>       break;
>     }
> 
>   return err;
> }
> 
> static int
> pulse_out (int unit,
> 	   int enable,
> 	   int src)
> {
>   int       base_io_port;
>   u_short   cont_reg1;
>   int       err;
>   u_char    src_code;
> 
>   base_io_port =3D devices[unit].id_iobase;
>   err =3D err_success;
> 
>   cont_reg1 =3D base_io_port + io_addr_cont_reg_1;
>   if (enable =3D=3D 0)
>     { /* disable pulse output */
>       gt401Unit[unit].cont_reg1 &=3D (~cont_reg1_pulse_en);
>       outb (cont_reg1, gt401Unit[unit].cont_reg1);
>       return err;
>     }
> 
>   // enable pulse output
>   switch (src)
>     {
>     case conn_IO_CHAN0:
>       src_code =3D 0;
>       break;
>     case conn_IO_CHAN1:
>       src_code =3D 1;
>       break;
>     case conn_IO_CHAN2:
>       src_code =3D 2;
>       break;
>     case conn_IO_CHAN3:
>       src_code =3D 3;
>       break;
>     case conn_SW_LOW:
>     case conn_SW_HIGH:
>       src_code =3D 4;
>       break;
>     case conn_OUT0:
>       src_code =3D 5;
>       break;
>     case conn_OUT1:
>       src_code =3D 6;
>       break;
>     case conn_OUT2:
>       src_code =3D 7;
>       break;
>     default:
>       err =3D err_connect_src;
>       return err;
>     }
> 
>   gt401Unit[unit].cont_reg1 &=3D cont_reg1_src_mask;
>   gt401Unit[unit].cont_reg1 |=3D src_code;
> 
>   switch (src)
>     {
>     case conn_SW_LOW:
>       gt401Unit[unit].cont_reg1 &=3D (~cont_reg1_sw_pulse);
>       break;
>     case conn_SW_HIGH:
>       gt401Unit[unit].cont_reg1 |=3D cont_reg1_sw_pulse;
>       break;
>     }
> 
>   outb (cont_reg1,
> 	gt401Unit[unit].cont_reg1);
> 
>   tsleep (&err, PZERO, "gt401", 100);
> 
>   gt401Unit[unit].cont_reg1 |=3D cont_reg1_pulse_en; // then enable pulse=
>  out
> 
>   outb (cont_reg1,
> 	gt401Unit[unit].cont_reg1);
> 
>   return err;
> }
> 
> static int
> set_irq (int unit,
> 	 int enable,
> 	 int src,
> 	 int edge)
> {
>   int       base_io_port;
>   int       err;
>   int       io_cont_reg2;
>   int       src_code;
> 
>   base_io_port =3D devices[unit].id_iobase;
>   err =3D err_success;
> 
>   io_cont_reg2 =3D base_io_port + io_addr_cont_reg_2;
> 
>   if (enable =3D=3D 0)
>     { /* turn off interrupts */
>       gt401Unit[unit].cont_reg2 &=3D ~(cont_reg2_intr_en_bit);
> #if 0 /* debug */
>       printf ("outb (%x,%x)\n",
> 	      io_cont_reg2,
> 	      gt401Unit[unit].cont_reg2);
> #endif
>       outb (io_cont_reg2,
> 	    gt401Unit[unit].cont_reg2);
>       return err;
>     } /* turn off interrupts */
> 
>   /* turn on interrupts */
>   switch (src)
>     {
>     case conn_IO_CHAN0:
>       src_code =3D cont_reg2_irq_src_chan0;
>       break;
>     case conn_IO_CHAN1:
>       src_code =3D cont_reg2_irq_src_chan1;
>       break;
>     case conn_IO_CHAN2:
>       src_code =3D cont_reg2_irq_src_chan2;
>       break;
>     case conn_IO_CHAN3:
>       src_code =3D cont_reg2_irq_src_chan3;
>       break;
>     case conn_OUT0:
>       src_code =3D cont_reg2_irq_src_out0;
>       break;
>     case conn_OUT1:
>       src_code =3D cont_reg2_irq_src_out1;
>       break;
>     case conn_OUT2:
>       src_code =3D cont_reg2_irq_src_out2;
>       break;
>     default:
>       err =3D err_irq_src;
>       return err;
>     }
>   gt401Unit[unit].cont_reg2 &=3D ~(cont_reg2_irq_src_mask);
>   gt401Unit[unit].cont_reg2 |=3D src_code;
> 
>   if (edge =3D=3D 0)
>     gt401Unit[unit].cont_reg2 &=3D ~(cont_reg2_intr_edge_bit);
>   else
>     gt401Unit[unit].cont_reg2 |=3D cont_reg2_intr_edge_bit;
> 
>   gt401Unit[unit].cont_reg2 &=3D ~(cont_reg2_intr_en_bit);
> #if 0 /* debug */
>       printf ("outb (%x,%x)\n",
> 	      io_cont_reg2,
> 	      gt401Unit[unit].cont_reg2);
> #endif
>   outb (io_cont_reg2,
> 	gt401Unit[unit].cont_reg2);
> 
>   gt401Unit[unit].cont_reg2 |=3D cont_reg2_intr_en_bit;
> #if 0 /* debug */
>       printf ("outb (%x,%x)\n",
> 	      io_cont_reg2,
> 	      gt401Unit[unit].cont_reg2);
> #endif
>   outb (io_cont_reg2,
> 	gt401Unit[unit].cont_reg2);
> 
>   return err;
> }
> 
> /*
>  * Register the appropriate INTerrupt.
>  */
> static int
> setupIntr(struct isa_device* device,
>           int irq, inthand2_t* hand, int unit, u_int* maskp)
> {
>     u_int mask;
>     u_int flags;
> 
>     mask =3D 1ul << irq;
>     flags =3D device->id_ri_flags;
> 
>     if (maskp)
>         INTRMASK(*maskp, mask);
> 
>     if (register_intr(irq, 0, flags, hand, maskp, unit) =3D=3D 0) {
>         device->id_irq =3D mask;
>         INTREN(mask);
>         return (irq);
>     }
> 
>     if (maskp)
>         INTRUNMASK(*maskp, mask);
> 
>     return (-1);
> }
> 
> 
> /*
>  * Unregister the appropriate INTerrupt.
>  */
> static int
> removeIntr(int irq)
> {
>     if (unregister_intr(irq, intr_handler[irq])) {
>         uprintf("\tINT #%d failed to unregister\n", irq);
>         return (EPERM);
>     }
>     else {
>         INTRDIS(1 << irq);
>         uprintf("\tINT #%d unregistered\n", irq);
>         return (0);
>     }
> }
> 
> static int
> send_cmd (int unit, u_char *cmd_buf, u_int size)
> {
>   int         base_io_port;
>   u_short     cmd_ready_reg;
>   u_short     dual_port_bank_index;
>   u_short     dual_port_bank_reg;
>   u_short     dual_port_data_reg;
>   int         err;
>   int         ii;
>   int         jj;
>   u_short     status_reg;
>   u_char      status_val;
>   int         ready;
>   int         ready_loop_max =3D 5000;
> 
>   err =3D err_success;
> 
>   base_io_port =3D devices[unit].id_iobase;
> 
>   // Wait for command ready bit
>   status_reg =3D base_io_port + io_addr_status_reg;
>   ready =3D 0;
>   for (ii=3D0; ii<cmd_poll_sleep_loop; ++ii)
>     {
>       for (jj=3D0; jj<cmd_poll_inner_loop; ++jj)
> 	{
> 	  if (jj > ready_loop_max)
> 	    break;
> 	  status_val =3D inb(status_reg);
> 	  if ((status_val & status_reg_ready_for_cmd) !=3D 0)
> 	    {
> 	      ready =3D 1;
> 	      break;
> 	    }
> 	}
>       if (ready)
> 	break;
>     }
>   if (!ready)
>     {
>       err =3D err_timeout;
>       return err;
>     }
>   if (size =3D=3D 0)
>     {
>       return err;
>     }
>   if (size > cmd_buf_sz)
>     {
>       err =3D err_cmd_sz;
>       return err;
>     }
> 
>   // place command bytes into dual port ram
>   dual_port_bank_reg =3D base_io_port + io_addr_ram_addr_reg;
>   dual_port_bank_index =3D dp_ram_command_first_page;
>   for (ii=3D0; ii<size; )
>     {
>       dual_port_data_reg =3D base_io_port + io_addr_dp_ram;
>       outb(dual_port_bank_reg, dual_port_bank_index);
> 
>       for (jj=3D0; jj<8; ++jj)
> 	{ // 8 bytes in each bank
> 	  outb(dual_port_data_reg, cmd_buf[ii]);
> 	  ++ii;
> 	  if (ii >=3D size)
> 	    break;
> 	  ++dual_port_data_reg;
> 	}
>       if (ii >=3D size)
> 	break;
>       ++dual_port_bank_index;
>     }
> 
>   // signal command
>   cmd_ready_reg =3D base_io_port + io_addr_cmd_ready;
>   outb(cmd_ready_reg, 0);
> 
>   return err;
> }
> 
> static int
> set_8254 (int unit,
> 	  u_short counter,
> 	  u_short mode,
> 	  u_short initial_count)
> {
>   u_short   addr54;
>   int       base_io_port;
>   u_char    control_byte;
>   int       err;
>   u_char    ic_hi;
>   u_char    ic_lo;
>   u_short   i8254_data_reg;
>   u_short   mux_addr_reg;
> 
>   err =3D err_success;
> 
>   base_io_port =3D devices[unit].id_iobase;
> 
>   switch (counter)
>     {
>     case 0:
>       addr54 =3D mux_54_ctr_0;
>       break;
>     case 1:
>       addr54 =3D mux_54_ctr_1;
>       break;
>     case 2:
>       addr54 =3D mux_54_ctr_2;
>       break;
>     default:
>       err =3D err_invalid_8254_ctr;
>       return err;
>     }
> 
>   mux_addr_reg =3D base_io_port + io_addr_mux_addr_reg;
>   i8254_data_reg =3D base_io_port + io_addr_8254_data_reg;
> 
>   control_byte =3D 0;
>   control_byte |=3D ((counter & 3) << 6);
>   control_byte |=3D (3 << 4);
>   control_byte |=3D ((mode & 7) << 1);
>   // BCD bit is 0, meaning counter it 16 bit unsigned binary
> 
>   outb(mux_addr_reg, mux_54_cont); // map in 8254 control register
>   outb(i8254_data_reg, control_byte);
>   outb(mux_addr_reg, addr54);      // map in 8254 counter register.
> 
>   ic_lo =3D initial_count & 0xff;
>   ic_hi =3D (initial_count >> 8) & 0xff;
> 
>   outb(i8254_data_reg, ic_lo);
>   outb(i8254_data_reg, ic_hi);
> 
>   return err;
> }
> 
> static int start_tt (int unit)
> {
>   u_char cmd_buf[8] =3D {0};
>   int    istat;
> 
>   cmd_buf[0] =3D cmd_clr_err;
>   send_cmd(unit,cmd_buf,1);
>   istat =3D get_status(unit);
>   printf ("start_tt after clr_err stat=3D%d\n",istat);
> 
>   cmd_buf[0] =3D cmd_tt_size;
>   cmd_buf[1] =3D 12;
>   cmd_buf[2] =3D 0;   /* no wrap */
>   send_cmd(unit, cmd_buf, 3);
>   istat =3D get_status(unit);
>   printf ("start_tt tt_size stat=3D%d\n",istat);
> 
>   cmd_buf[0] =3D cmd_tt;
>   cmd_buf[1] =3D tt_edge_pos; /* chan=3D0 << 6 | edge */
>   send_cmd(unit, cmd_buf, 2);
>   istat =3D get_status(unit);
>   printf ("start_tt tt stat=3D%d\n",istat);
> 
>   return 0;
> }
> 
> static int stop_tt (int unit)
> {
>   u_char cmd_buf[8] =3D {0};
>   int istat;
> 
>   cmd_buf[0] =3D cmd_clr_err;
>   send_cmd(unit,cmd_buf,1);
>   istat =3D get_status(unit);
>   printf ("stop_tt stat after cmd_clr_err=3D%d\n",istat);
> 
>   cmd_buf[0] =3D cmd_chan_off;
>   cmd_buf[1] =3D 0xc0;
>   send_cmd(unit, cmd_buf, 2);
>   istat =3D get_status(unit);
>   printf ("stop_tt stat after cmd_chan_off=3D%d\n",istat);
> 
> #if 0
>   cmd_buf[0] =3D cmd_clr_tt;
>   cmd_buf[1] =3D 0;     /* clear time tag buffer and time tag counter */
>   send_cmd(unit, cmd_buf, 2);
>   istat =3D get_status(unit);
>   printf ("stop_tt stat after cmd_clr_tt=3D%d\n",istat);
> #endif
> 
>   return 0;
> }
> 
> static int get_tt_count (int unit)
> {
>   return 0;
> }
> 
> static int get_tt (int unit, long long *tt)
> {
>   int        base_io_port;
>   int        ram_addr_reg;
>   int        next_tt;
> 
>   send_cmd(unit,NULL,0);
>   base_io_port =3D devices[unit].id_iobase;
> 
>   ram_addr_reg =3D base_io_port + io_addr_ram_addr_reg;
>   outb (ram_addr_reg, dp_ram_status_page);
> 
>   {
>     int ii;
>     printf ("status page : ");
>     for (ii=3D0; ii<8; ++ii)
>       {
> 	next_tt =3D inb(base_io_port + 8 + ii);
> 	printf (" 0x%x");
>       }
>     printf ("\n");
>   }
> 
>   {
>     int ii;
>     printf ("tag buf :");
>     outb (ram_addr_reg, 156);
>     for (ii=3D0; ii<8; ++ii)
>       {
> 	next_tt =3D inb(base_io_port + 8 + ii);
> 	printf (" 0x%x");
>       }
>     outb (ram_addr_reg, 157);
>     for (ii=3D0; ii<4; ++ii)
>       {
> 	next_tt =3D inb(base_io_port + 8 + ii);
> 	printf (" 0x%x");
>       }
>     printf ("\n");
>   }
> 
>   return 0;
> }
> 
> static int get_status(int unit)
> {
>   int        base_io_port;
>   int        ram_addr_reg;
>   int        status_reg;
>   int        istat;
> 
>   base_io_port =3D devices[unit].id_iobase;
>   ram_addr_reg =3D base_io_port + io_addr_ram_addr_reg;
> 
>   send_cmd(unit,NULL,0);
> 
>   outb (ram_addr_reg, dp_ram_status_page);
> 
>   status_reg =3D base_io_port + err_reg;
>   istat =3D inb(status_reg) & 0xff;
> 
>   return istat;
> }
> 
> 
> --==_Exmh_18363059200
> Content-Type: text/plain ; name="log_read_counts_980726.c"; charset=us-ascii
> Content-Description: log_read_counts_980726.c
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: attachment; filename="log_read_counts_980726.c"
> 
> #if 0
> cc -o test04 test04.c
> 
> Experiment with /dev/gt401 not doing time tags
> Run continuously
> #endif
> 
> #include <sys/types.h>
> #include <sys/rtprio.h>
> #include <stdio.h>
> 
> #include <fcntl.h>
> #include "gt401.h"
> 
> #define DEV_PATH "/dev/gt401"
> int fd =3D -1;
> 
> int arg_ioctl =3D 0;
> 
> int read_count =3D 0;
> 
> #define MAX_TTAG_BUF (4*1024)
> 
> main (int argc, char **argv)
> {
>   int istat;
>   int ii;
>   gt401_read * ttag;
>   gt401_read ttag_buf[MAX_TTAG_BUF], last_ttag;
>   int log_mod;
>   double period_d;
>   double freq_d;
>   int first_flag =3D 1;
>   int read_req =3D (sizeof(gt401_read) * MAX_TTAG_BUF);
>   int read_data_count;
>   int max_read_data_count =3D 0;
> 
>   long long sample_period =3D -1;
>   long long sample_period_hi;
>   long long sample_period_low;
>   int read_dropped =3D 0;
>   int driver_dropped =3D 0;
> 
>   long long index_diff_driver;
>   long long index_diff_read_error;
>   long long calc_usec_diff_driver;
>   long long calc_index_diff_driver;
>   long long index_diff_driver_error;
> 
>   struct rtprio rtp;
>   int rtp_flag =3D 0;
> 
> #if 1
>   rtp_flag =3D 1;
>   rtp.type =3D RTP_PRIO_REALTIME;
>   rtp.prio =3D 0;
>   istat =3D rtprio (RTP_SET,
> 		  0,
> 		  &rtp);
>   if (istat !=3D 0)
>     {
>       perror("rtprio");
>       exit (1);
>     }
>   fprintf (stderr,"rtprio\n");
> #else
>   fprintf (stderr, "No rtprio\n");
> #endif
> 
>   fd =3D open (DEV_PATH, O_RDONLY, 0);
>   if (fd < 0)
>     {
>       fprintf(stderr,"open of %s failed\n",DEV_PATH);
>       exit (__LINE__);
>     }
> 
>   arg_ioctl =3D 20;
> 
>   period_d =3D ((double)arg_ioctl) / 10000.0;
>   freq_d =3D 1.0 / period_d;
>   log_mod =3D (int)(freq_d * 30.0);
> 
>   sample_period =3D (long long)(period_d * 1e6);
>   sample_period_low =3D sample_period - (sample_period / 8);
>   sample_period_hi =3D sample_period + (sample_period / 8);
> 
>   fprintf (stderr,"periodX10000=3D%d period=3D%f freq=3D%f\n",arg_ioctl,p=
> eriod_d,freq_d);
>   fprintf (stderr,"sizeof(gt401_read) =3D %d\n",sizeof(gt401_read));
> 
>   for (ii=3D1; ii<argc; ++ii)
>     {
>       printf ("# %s\n",argv[ii]); /* gnuplot comment line */
>     }
>   printf ("# period=3D%f freq=3D%f",
> 	  period_d, freq_d);
>   if (rtp_flag)
>     printf(" RTPRIO");
>   else
>     printf(" NO RTPRIO");
>   printf ("\n");
> 
>   istat =3D ioctl(fd,GT401_START_EVENTS,&arg_ioctl);
> 
>   for (;;)
>     {
>       istat =3D read (fd,(void *)&(ttag_buf[0]),read_req);
>       if (istat <=3D 0)
> 	{
> 	  fprintf (stderr,"read fail istat=3D%d\n",istat);
> 	  perror("read fail");
> 	  exit (__LINE__);
> 	}
>       read_data_count =3D istat / sizeof(gt401_read);
>       printf ("%d\n",read_data_count);
>       fflush(stdout);
>     } /* for (;;) */
> 
>   istat =3D ioctl(fd,GT401_STOP_EVENTS,&arg_ioctl);
> 
>   return (0);
> }
> 
> --==_Exmh_18363059200
> Content-Type: text/plain; name="log_read_counts_980726.c"; charset=us-ascii
> Content-Description: log_read_counts_980726.c
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: attachment; filename="log_read_counts_980726.c"
> 
> #if 0
> cc -o test04 test04.c
> 
> Experiment with /dev/gt401 not doing time tags
> Run continuously
> #endif
> 
> #include <sys/types.h>
> #include <sys/rtprio.h>
> #include <stdio.h>
> 
> #include <fcntl.h>
> #include "gt401.h"
> 
> #define DEV_PATH "/dev/gt401"
> int fd =3D -1;
> 
> int arg_ioctl =3D 0;
> 
> int read_count =3D 0;
> 
> #define MAX_TTAG_BUF (4*1024)
> 
> main (int argc, char **argv)
> {
>   int istat;
>   int ii;
>   gt401_read * ttag;
>   gt401_read ttag_buf[MAX_TTAG_BUF], last_ttag;
>   int log_mod;
>   double period_d;
>   double freq_d;
>   int first_flag =3D 1;
>   int read_req =3D (sizeof(gt401_read) * MAX_TTAG_BUF);
>   int read_data_count;
>   int max_read_data_count =3D 0;
> 
>   long long sample_period =3D -1;
>   long long sample_period_hi;
>   long long sample_period_low;
>   int read_dropped =3D 0;
>   int driver_dropped =3D 0;
> 
>   long long index_diff_driver;
>   long long index_diff_read_error;
>   long long calc_usec_diff_driver;
>   long long calc_index_diff_driver;
>   long long index_diff_driver_error;
> 
>   struct rtprio rtp;
>   int rtp_flag =3D 0;
> 
> #if 1
>   rtp_flag =3D 1;
>   rtp.type =3D RTP_PRIO_REALTIME;
>   rtp.prio =3D 0;
>   istat =3D rtprio (RTP_SET,
> 		  0,
> 		  &rtp);
>   if (istat !=3D 0)
>     {
>       perror("rtprio");
>       exit (1);
>     }
>   fprintf (stderr,"rtprio\n");
> #else
>   fprintf (stderr, "No rtprio\n");
> #endif
> 
>   fd =3D open (DEV_PATH, O_RDONLY, 0);
>   if (fd < 0)
>     {
>       fprintf(stderr,"open of %s failed\n",DEV_PATH);
>       exit (__LINE__);
>     }
> 
>   arg_ioctl =3D 20;
> 
>   period_d =3D ((double)arg_ioctl) / 10000.0;
>   freq_d =3D 1.0 / period_d;
>   log_mod =3D (int)(freq_d * 30.0);
> 
>   sample_period =3D (long long)(period_d * 1e6);
>   sample_period_low =3D sample_period - (sample_period / 8);
>   sample_period_hi =3D sample_period + (sample_period / 8);
> 
>   fprintf (stderr,"periodX10000=3D%d period=3D%f freq=3D%f\n",arg_ioctl,p=
> eriod_d,freq_d);
>   fprintf (stderr,"sizeof(gt401_read) =3D %d\n",sizeof(gt401_read));
> 
>   for (ii=3D1; ii<argc; ++ii)
>     {
>       printf ("# %s\n",argv[ii]); /* gnuplot comment line */
>     }
>   printf ("# period=3D%f freq=3D%f",
> 	  period_d, freq_d);
>   if (rtp_flag)
>     printf(" RTPRIO");
>   else
>     printf(" NO RTPRIO");
>   printf ("\n");
> 
>   istat =3D ioctl(fd,GT401_START_EVENTS,&arg_ioctl);
> 
>   for (;;)
>     {
>       istat =3D read (fd,(void *)&(ttag_buf[0]),read_req);
>       if (istat <=3D 0)
> 	{
> 	  fprintf (stderr,"read fail istat=3D%d\n",istat);
> 	  perror("read fail");
> 	  exit (__LINE__);
> 	}
>       read_data_count =3D istat / sizeof(gt401_read);
>       printf ("%d\n",read_data_count);
>       fflush(stdout);
>     } /* for (;;) */
> 
>   istat =3D ioctl(fd,GT401_STOP_EVENTS,&arg_ioctl);
> 
>   return (0);
> }
> 
> --==_Exmh_18363059200--
> 
> 
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-hackers" in the body of the message
> 

-- 
\\  Sometimes you're ahead,       \\  Mike Smith
\\  sometimes you're behind.      \\  mike@smith.net.au
\\  The race is long, and in the  \\  msmith@freebsd.org
\\  end it's only with yourself.  \\  msmith@cdrom.com



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



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