Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Oct 1997 09:42:45 -0700 (PDT)
From:      "Jamil J. Weatherbee" <jamil@trojanhorse.ml.org>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   i386/4816: FreeBSD driver for Industrial Computer Source DIO48S/AT-P
Message-ID:  <199710201642.JAA03280@trojanhorse.ml.org>
Resent-Message-ID: <199710201650.JAA04445@hub.freebsd.org>

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

>Number:         4816
>Category:       i386
>Synopsis:       FreeBSD driver for Industrial Computer Source DIO48S/AT-P
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 20 09:50:00 PDT 1997
>Last-Modified:
>Originator:     Jamil J. Weatherbee
>Organization:
>Release:        FreeBSD 2.2-STABLE i386
>Environment:

FreeBSD i386 platform, DIO48S/AT-P is a 48 line digital input/output board
with change of state interrupts independently selectable on each of 6 8
bit ports.  I have named the driver "dio", given it major number 83
(chardev), and written a manpage. This board uses 16 bytes of iospace and
a jumper selectable interrupt, when being operated in interrupt enabled
mode (as opposed to polled mode).  This is my first time doing this under
freebsd, but I have attempted to be thorough, I would appreciate being
informed of what the usual process for maintaining a driver like this in
the source tree is.  

>Description:

Basically gives a clean interface to a set of 8255 PPIs on a board only
capable of operating in mode 0. Also makes change of state interrupts
available to user through select() hooks.  I currently use three of these
boards for industrial automation.  You should be able to compile this into
a working kernel (on some unused ioports and interrupt) and have it attach
even without the board because (as with most boards of this type), there
is no reliable way to probe for it without the risk of damaging any
special equipment that has been attached.
I am interested in possibly being able to maintain any changes myself to
this as people using it come up with new general features to add.  My
motivation for doing this was to be able to use change of state interrupts
and also to make it easier for anyone in the future looking for a board
like this under freebsd.  I have had a number of digital io boards from
various vendors and have found that this one is well featured and also a
good value.


>How-To-Repeat:

Jordan said to send the driver after running shar on the relevant files.

>Fix:

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	/usr/src/sys/i386/isa/dio.c
#	/usr/src/sys/sys/dioctl.h
#	/usr/src/share/man/man4/man4.i386/dio.4
#
echo x - /usr/src/sys/i386/isa/dio.c
sed 's/^X//' >/usr/src/sys/i386/isa/dio.c << 'END-of-/usr/src/sys/i386/isa/dio.c'
X/*
X * Copyright (c) 1997 Jamil J. Weatherbee
X * All rights reserved.
X *
X * 
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer
X *    in this position and unchanged.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission
X * 
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X *
X * Industrial Computer Source model DIO48S/AT-P
X * 48 channel digital input/output board with change of state interrupt
X * dio.c, character device driver, last revised Oct 19 1997
X * See http://www.indcompsrc.com/products/data/html/dio48s_at-p.html
X *
X * Written by: Jamil J. Weatherbee <jamil@trojanhorse.ml.org>
X *
X */
X
X
X/* Include Files */
X
X#include "dio.h"
X#if NDIO > 0
X
X#include <sys/param.h> 
X#include <sys/systm.h>
X#include <sys/proc.h>
X#include <sys/kernel.h>
X#include <sys/conf.h>
X#include <sys/fcntl.h>
X#include <sys/malloc.h>
X#include <sys/buf.h> 
X#include <machine/clock.h>
X#include <i386/isa/isa.h>
X#include <i386/isa/isa_device.h>
X#include <sys/dioctl.h> 
X
X#ifdef DEVFS
X#include <sys/devfsext.h>
X#endif 
X
X/* Local Defines */
X
X#define CDEV_MAJOR 83
X#define NUMPORTS 16
X
X#define PORTA 0x0
X#define PORTB 0x1
X#define PORTC 0x2
X#define CNTRL0 0x3
X#define PORTD 0x4
X#define PORTE 0x5
X#define PORTF 0x6
X#define CNTRL1 0x7
X#define ENBCHS 0xB
X#define CLRCHS 0xF
X
X/* mode bits for the control registers */
X
X#define MODE0 0x80 
X#define AINMASK 0x10
X#define BINMASK 0x02
X#define CINMASK 0x09
X#define CHSMASK 0xff
X
X/* Minor allocations:
X * UUUUUCCC
X * UUUUU: board unit (X=0-31) 
X * CCC: digital i/o channel (0-2,4-6) 
X *      channel  name       devnode  connector  signal pins (lsb/msb)
X *      0        PA port 0  dioXa    J2         47, 45, 43, 41, 39, 37, 35, 33
X *      1        PB port 0  dioXb    J2         31, 29, 27, 25, 23, 21, 19, 17
X *      2        PC port 0  dioXc    J2         15, 13, 11,  9,  7,  5,  3,  1
X *      4        PA port 1  dioXd    J3         47, 45, 43, 41, 39, 37, 35, 33
X *      5        PB port 1  dioXe    J3         31, 29, 27, 25, 23, 21, 19, 17
X *      6        PC port 1  dioXf    J3         15, 13, 11,  9,  7,  5,  3,  1
X */
X
X#define MAXUNITS 32
X#define NUMCHANNELS 8 
X#define CFGSIZE 6
X#define UNIT(dev) ((minor(dev) & 0xf8) >> 3)
X#define CHANNEL(dev) (minor(dev) & 0x07)
X#define LMINOR(unit, channel) ((unit << 3) + channel)
X
X/* Port status setting */
X
X#define STATUS_UNUSED 0
X#define STATUS_POLLED_INPUT 1
X#define STATUS_CHS_INPUT 2
X#define STATUS_OUTPUT 3
X#define STATUS_CONTROLLER 4 
X
X/* Type definitions */
Xtypedef struct 
X{ 
X  struct isa_device *isaunit; /* ptr to isa device information */     
X  u_char laststate[NUMCHANNELS]; /* The last state of the device */
X  u_char chs; /* last setting posted to chs */
X  short status[NUMCHANNELS]; /* The status for the port, see above */ 
X  struct selinfo readselect[NUMCHANNELS]; /* chs select info for each chan */
X  short ready[NUMCHANNELS]; /* set to true if chs input is ready */ 
X  void *devfs_token[NUMCHANNELS]; /* devfs token for each channels node */
X   
X} tdio_unit;
X
X
X/* general info on how to configure a unit based on its channel statuses */
Xtypedef struct {
X                 int channel; /* the channel in question 0-2,4-6 */
X                 int controller; /* the controller to mask CNTRL0 or CNTRL1 */
X                 int input_mask; /* the mask on channel as input */
X                 int chs_mask; /* how to mask off chs */ 
X                 char *nodename; /* the name of the device node (DEVFS) */
X               } tdio_cfg;
X
X
X/* Function Prototypes */
X
Xstatic int dio_probe (struct isa_device *idp);  /* Check for dio board */
Xstatic int dio_attach (struct isa_device *idp);  /* Take dio board */
Xstatic int dio_ioctl (dev_t dev, int cmd, caddr_t data, 
X			 int fflag, struct proc *p); /* Special ops */
Xstatic int dio_open (dev_t dev, int oflags, int devtype, struct proc *p);
Xstatic void dio_sync (int unit); /* updates the control registers */
Xstatic int dio_close (dev_t dev, int fflag, int devtype, struct proc *p);
Xstatic void dio_strategy (struct buf *bp); /* called by rawread and rawwrite */
Xstatic int dio_select (dev_t dev, int which, struct proc *p); 
X
X/* Global Data */
X
Xstatic int dio_devsw_installed = 0;  /* Protect against reinit multiunit */
Xstatic tdio_unit *dio_unit[NDIO]; /* data structs for each unit */ 
Xstatic tdio_cfg dio_cfg[CFGSIZE] = { { PORTA, CNTRL0, AINMASK, 0x01,"dio%da"},
X                                     { PORTB, CNTRL0, BINMASK, 0x02,"dio%db"},
X                                     { PORTC, CNTRL0, CINMASK, 0x04,"dio%dc"},
X                                     { PORTD, CNTRL1, AINMASK, 0x08,"dio%dd"},
X                                     { PORTE, CNTRL1, BINMASK, 0x10,"dio%de"},
X                                     { PORTF, CNTRL1, CINMASK, 0x20,"dio%df"}};
X
X/* Character device switching structure */
Xstatic struct cdevsw dio_cdevsw = { dio_open, dio_close, rawread, rawwrite,
X                                    dio_ioctl, nostop, noreset, nodevtotty,
X                                    dio_select, nommap, dio_strategy, "dio",
X                                    NULL, -1 };
X
X/* Structure expected to tell how to probe and attach the driver
X * Must be published externally (cannot be static) */
Xstruct isa_driver diodriver = { dio_probe, dio_attach, "dio", 0 };
X
X
X/* Unit input chs interrupt handling routine
X * BTW: the standard DIO48s board has a 2.5 microsecond response time
X *      to a change of state (theoretically) */
Xvoid diointr (int unit)
X{
X  tdio_unit *info = dio_unit[unit];
X  int iobase = info->isaunit->id_iobase;
X  int channel; 
X  u_char curstate; 
X   
X  for (channel=0; channel<NUMCHANNELS; channel++)
X   if ((info->status[channel] == STATUS_CHS_INPUT) &&
X       ((curstate = inb (iobase+channel)) != info->laststate[channel]))
X    {	
X      info->laststate[channel] = curstate; /* save cur state as last state */
X      info->ready[channel] = 1; /* now ready for chs based read */
X      selwakeup (&info->readselect[channel]); /* wakeup any selectors */
X    }
X  outb (iobase+CLRCHS, 0); /* Clear CHS interrupt latch */
X}
X
X
X/* Since this device can always be read/write the select() allows the user
X * to actually make some use of the change of state interrupts by calling
X * select() on a read descriptor that has had chs interrupts enabled via
X * ioctl (fd, DIOENBCHS, NULL) */
Xstatic int dio_select (dev_t dev, int which, struct proc *p)
X{
X  int unit = UNIT(dev); /* Get unit number */
X  int channel = CHANNEL(dev); /* and channel in that unit */
X  tdio_unit *info = dio_unit[unit]; /* info on this unit */
X  int s; /* interrupt priority */
X   
X  s = spltty(); /* prevent diointr() from occuring here */
X  
X  switch (which) /* are we sleeping on a read or write descriptor */ 
X   {
X     case FWRITE: splx(s); return 1; /* always ready for writing */
X     case FREAD: if (info->status[channel] == STATUS_CHS_INPUT)
X	          {
X		    if (info->ready[channel]) /* if ready */
X		     {
X		       splx(s);
X		       return 1;		  
X		     }
X		     
X		    /* record the select request */ 
X		    selrecord (p, &info->readselect[channel]);
X		    splx(s); 
X		    return 0; /* not ready but will get waken up when ready */
X		  }
X                 splx(s); return 1; /* any input except chs set is ready */
X   }
X  
X  splx(s); 
X  return 0; /* this should not ever happen */ 
X   
X}
X
X
X/* The probing routine - returns number of bytes needed */
Xstatic int dio_probe (struct isa_device *idp)
X{
X  int unit = idp->id_unit;  /* this device unit number */
X  int iobase = idp->id_iobase; /* the base address of the unit */
X  int port; 
X    
X  if ((unit < 0) || (unit >= NDIO) || (unit >= MAXUNITS))
X   { 
X     printf ("dio: invalid unit number (%d)\n", unit);
X     return 0;
X   }
X   
X  /* the unit number is ok, lets check if used */
X  if (dio_unit[unit]) 
X   {
X     printf ("dio: unit (%d) already attached\n", unit);
X     return 0;
X   }
X
X  /* note: there is no reliable way to probe this board */ 
X
X  return NUMPORTS; /* this device needs this many ports */ 
X}
X
X
X/* The attachment routine - returns true on success */
Xstatic int dio_attach (struct isa_device *idp)
X{
X  int unit = idp->id_unit;  /* this device unit number */   
X  int iobase = idp->id_iobase; /* the base address of the unit */ 
X  tdio_unit *info; /* pointer to driver specific info for unit */
X  int ncfg; /* configuration record number */
X   
X  if (!(info = malloc(sizeof(*info), M_DEVBUF, M_NOWAIT)))
X   {
X     printf ("dio%d: cannot allocate driver storage\n", unit);
X     return 0;
X   }
X  dio_unit[unit] = info; /* make sure to save the pointer! (prev bug) */
X  bzero (info, sizeof(*info)); /* clear info structure to all false */
X  info->isaunit = idp;  /* store ptr to isa device information */
X
X  outb (iobase+CLRCHS, 0); /* Clear CHS interrupt latch */
X   
X  /* only need to set this once */
X  info->status[CNTRL0] = info->status[CNTRL1] = STATUS_CONTROLLER;
X      
X  dio_sync (unit); /* This will have the effect of setting all to
X		    * polled inputs */
X  
X  /* insert devfs nodes */
X  
X#ifdef DEVFS   
X  for (ncfg=0; ncfg<CFGSIZE; ncfg++)
X   info->devfs_token[dio_cfg[ncfg].channel] = 
X     devfs_add_devswf(&dio_cdevsw, LMINOR(unit, dio_cfg[ncfg].channel), DV_CHR,
X		      UID_ROOT, GID_WHEEL, 0600 ,dio_cfg[ncfg].nodename, unit);
X#endif   
X   
X  printf ("dio%d: Interrupt-driven unit\n", unit);
X  return 1; /* obviously successful */
X}
X
X
X/* I/O control routine */
Xstatic int dio_ioctl (dev_t dev, int cmd, caddr_t data, 
X			 int fflag, struct proc *p)
X{
X  int unit = UNIT(dev); /* Get unit number */
X  int channel = CHANNEL(dev); /* and channel in that unit */
X  tdio_unit *info = dio_unit[unit]; /* info on this unit */
X  int iobase = info->isaunit->id_iobase; /* the iobase of unit in question */
X  short status = info->status[channel]; /* the status of unit in question */
X  int s; /* interrupt priority level */ 
X   
X  switch (cmd)
X   {  
X    case DIOENBCHS: if ((status == STATUS_POLLED_INPUT) ||
X			 (status == STATUS_CHS_INPUT))
X	             {
X		       s = spltty();
X                       info->status[channel] = STATUS_CHS_INPUT;
X		       info->ready[channel] = 0;
X		       dio_sync (unit);
X                       /* this should prevent any chs simply by ioctling */
X		       info->laststate[channel] = inb (iobase+channel);
X                       splx (s);
X		       return 0;
X	             }
X                    return EPERM;
X      
X    case DIODISCHS: if ((status == STATUS_POLLED_INPUT) ||
X			 (status == STATUS_CHS_INPUT))
X	             {
X		       s = spltty();	
X                       info->status[channel] = STATUS_POLLED_INPUT;
X                       dio_sync (unit);
X                       splx(s);
X		       return 0;
X		     }
X                    return EPERM; 
X   }
X  return ENOTTY; /* inappropriate (unhandled) ioctl for device */  
X}
X
X
X/* How to open a channel (a channel can only be opened by one process) */
Xstatic int dio_open (dev_t dev, int oflags, int devtype, struct proc *p)
X{
X  int unit = UNIT(dev); /* Get unit number */
X  int channel = CHANNEL(dev); /* and channel in that unit */
X  tdio_unit *info;  /* info on this unit */
X  int iobase; /* the iobase of unit in question */
X  short status; /* the status of unit in question */
X  int s; /* priority value */
X   
X  /* We know the major is safe, now check the minor */
X 
X  if ((unit >= NDIO) || (unit >= MAXUNITS)) return ENXIO; /* unit ok? */
X  if (channel >= NUMCHANNELS) return ENXIO; /* is the channel no valid? */ 
X  if (!dio_unit[unit]) return ENXIO; /* is the unit attached? */
X   
X  /* standard assigns now safe */
X  info = dio_unit[unit]; 
X  iobase = info->isaunit->id_iobase; 
X   
X  if (info->status[channel]) return EBUSY; /* channel is already opened 
X					    * or maybye is a controller */
X   
X  /* If it can be written to, it must be an output port */ 
X  if (oflags & FWRITE)   
X   {
X     s = spltty(); 
X     info->status[channel] = STATUS_OUTPUT;
X     dio_sync (unit);
X     splx(s); 
X     return 0;
X   } 
X  if (oflags & FREAD)
X   {
X     s = spltty(); 
X     info->status[channel] = STATUS_POLLED_INPUT;
X     dio_sync (unit); 
X     info->laststate[channel] = inb (iobase+channel); /* get cur state */    
X     splx(s);
X     return 0;
X   }
X  return EPERM; /* Needs to be either read or write or both */  	
X}
X
X
X/* Closing a channel is really easy just change its status to
X * inputs (actually STATUS_UNUSED) and resync */
Xstatic int dio_close (dev_t dev, int fflag, int devtype, struct proc *p)
X{
X  int unit = UNIT(dev); /* Get unit number */
X  int channel = CHANNEL(dev); /* and channel in that unit */
X  tdio_unit *info = dio_unit[unit]; /* info on this unit */
X  int s; /* priority value */
X   
X  s = spltty();
X  info->status[channel] = STATUS_UNUSED; /* this channel now closed */
X  dio_sync (unit); /* channel switched to input (looks high to me) */
X  splx(s); 
X   
X  return 0; /* close is always successful */ 
X}
X
X
X/* called by kernel routines rawread and rawrite to actually perform the
X * i/o via inb() and outb() */
Xstatic void dio_strategy (struct buf *bp)
X{
X  /* this is the machine i/o port that we are going to r/w */
X  int unit = UNIT(bp->b_dev);
X  int channel = CHANNEL(bp->b_dev);
X  tdio_unit *info = dio_unit[unit];
X  int port = info->isaunit->id_iobase+channel;
X  u_char *c = (u_char *) bp->b_un.b_addr; /* current byte were ioing */
X  int bufsz = bp->b_bcount; /* size of the buffer to r/w */
X  int index; /* current index in the buffer (byte number were on) */
X  int s; 
X   
X  if (bp->b_flags & B_READ) /* read into the buffer */
X   { 
X     s = spltty(); 
X     info->ready[channel] = 0; /* now we are not ready */ 
X     splx(s);
X     for (index=0; index<bufsz; index++) *c++ = inb (port);
X   }
X  else /* write out from the buffer */
X   for (index=0; index<bufsz; index++, c++) outb (port, *c);
X 
X  bp->b_resid = 0; /* no i/o remaining to be done (we hope) */ 
X  biodone (bp); /* done with the buffer */ 
X   
X}
X
X
X/* Syncronize the control registers of the unit with the values in the 
X * status info table for the unit */
Xstatic void dio_sync (int unit)
X{
X  tdio_unit* info = dio_unit[unit]; 
X  int iobase = info->isaunit->id_iobase; 
X  int ncfg; /* current configuration counter */
X   
X  info->laststate[CNTRL0] = info->laststate[CNTRL1] = MODE0; /* init. masks */ 
X  info->chs = CHSMASK; /* all chs interrupts masked case */ 
X   
X  for (ncfg=0; ncfg<CFGSIZE; ncfg++)
X   {   
X     switch (info->status[dio_cfg[ncfg].channel])
X      {
X       case STATUS_OUTPUT: info->laststate[dio_cfg[ncfg].controller] &= 
X	                     ~dio_cfg[ncfg].input_mask; break; /* is output */
X       case STATUS_CHS_INPUT: info->chs &= ~dio_cfg[ncfg].chs_mask; /* chs */
X       default: info->laststate[dio_cfg[ncfg].controller] |=
X	          dio_cfg[ncfg].input_mask; /* is input */   
X      }
X   }
X  
X  /* now we need to actually write these things to the registers */
X   
X  outb (iobase+ENBCHS, info->chs); /* write the chs intrerrupt mask */
X  outb (iobase+CNTRL0, info->laststate[CNTRL0]); /* write the cntrl0 value */
X  outb (iobase+CNTRL1, info->laststate[CNTRL1]); /* write the cntrl0 value */
X
X}
X
X
X
X/* Driver initialization */
Xstatic void dio_drvinit (void *unused)
X{
X  dev_t dev;  /* Type for holding device major/minor numbers (int) */
X
X  if (!dio_devsw_installed)
X   {
X     dev = makedev (CDEV_MAJOR, 0);  /* description of device major */
X     cdevsw_add (&dev, &dio_cdevsw, NULL);  /* put driver in cdev table */
X     dio_devsw_installed=1;
X   }
X}
X
X
X/* System initialization call instance */
X
XSYSINIT (diodev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR,
X         dio_drvinit,NULL);
X
X#endif
X
END-of-/usr/src/sys/i386/isa/dio.c
echo x - /usr/src/sys/sys/dioctl.h
sed 's/^X//' >/usr/src/sys/sys/dioctl.h << 'END-of-/usr/src/sys/sys/dioctl.h'
X/*
X * Copyright (c) 1997 Jamil J. Weatherbee
X * All rights reserved.
X *
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer
X *    in this position and unchanged.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission
X * 
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X *
X * Industrial Computer Source model DIO48S/AT-P
X * 48 channel digital input/output board with change of state interrupt
X * dioctl.h, definitions for dio ioctl(), last revised Oct 19 1997
X *
X * Written by: Jamil J. Weatherbee <jamil@trojanhorse.ml.org>
X *
X */
X
X#ifndef _SYS_DIOCTL_H_
X#define _SYS_DIOCTL_H_
X
X#ifndef KERNEL
X#include <sys/types.h>
X#endif
X#include <sys/ioccom.h>
X
X/* Change of state related ioctls. CHS is disabled by default, this makes it
X * a polling channel. With CHS enabled the channel is state driven. */
X
X#define DIOENBCHS 0  /* enable change of state interrupt on a read only port */
X#define DIODISCHS 1 /* disable change of state interrupt on a read only port */
X
X#endif
X
END-of-/usr/src/sys/sys/dioctl.h
echo x - /usr/src/share/man/man4/man4.i386/dio.4
sed 's/^X//' >/usr/src/share/man/man4/man4.i386/dio.4 << 'END-of-/usr/src/share/man/man4/man4.i386/dio.4'
X.\"
X.\" Copyright (c) 1997 Jamil J. Weatherbee
X.\" All rights reserved.
X.\"
X.\"
X.\" 
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer
X.\"    in this position and unchanged.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\" 3. The name of the author may not be used to endorse or promote products
X.\"    derived from this software without specific prior written permission
X.\" 
X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X.\"
X.\" Industrial Computer Source model DIO48S/AT-P
X.\" 48 channel digital input/output board with change of state interrupt
X.\" dio.c, character device driver, last revised Oct 19 1997
X.\" See http://www.indcompsrc.com/products/data/html/dio48s_at-p.html
X.\"
X.\"
X.Dd October 19, 1997
X.Dt DIO 4 i386
X.Os FreeBSD
X.Sh NAME
X.Nm dio
X.Nd
XIndustrial Computer Source DIO48S/AT-P driver
X.Sh SYNOPSIS
X.Cd "device dio0 at isa? port 0x250 tty irq 12 vector diointr"
X.Sh DESCRIPTION
XThis driver supports the Industrial Computer Source \fIDIO48S/AT-P 48 Line
XDigital I/O board with Change of State Interrupt\fP.
X.Pp
XThis board provides 6 8 bit digital I/O ports.  It makes use of two type
X8255-5 Programmable Peripheral Interface chips.  Each port can be
Xindependently configured as input or output.  Ports configured as input can
Xindividually have their change of state interrupts enabled.
X.Pp
XThe selection of input or output mode for each port is via flags passed
Xthrough the
X.Xr open 2
Xcall:
X.Pp
X.Bd -literal -offset indent
XO_RDONLY	open for input
XO_WRONLY	open for output
XO_RDWR		open for output
X.Ed
X.Pp
XSelection of the I/O port is through the minor number:
X.Pp
X.Bd -literal -offset indent
XThe 8 bit minor number format is UUUUUCCC, where
XUUUUU: board unit (X=0-31)
X  CCC: digital i/o channel (0-2,4-6)
X.Pp
Xch  name       devnode  conn  signal pins (lsb/msb)
X0   PA port 0  dioXa    J2    47, 45, 43, 41, 39, 37, 35, 33
X1   PB port 0  dioXb    J2    31, 29, 27, 25, 23, 21, 19, 17
X2   PC port 0  dioXc    J2    15, 13, 11,  9,  7,  5,  3,  1
X4   PA port 1  dioXd    J3    47, 45, 43, 41, 39, 37, 35, 33
X5   PB port 1  dioXe    J3    31, 29, 27, 25, 23, 21, 19, 17
X6   PC port 1  dioXf    J3    15, 13, 11,  9,  7,  5,  3,  1
X.Ed
X.Pp
X.Sh IOCTL
XThe following
X.Xr ioctl 2
Xcalls apply to
X.Nm
Xdevices.  Their declaration can be found in the header file
X.Pa <sys/dioctl.h>.
X.Bl -tag -width DIOENBCHS
X.It Dv DIOENBCHS
XSet an input to Change of State enabled mode.  Calls to
X.Xr read 2
Xwill never block; however,
X.Xr select 2
Xcan be used to wait for inputs to change that have had their interrupts
Xenabled in this fashion.
X.It Dv DIODISCHS
XUndo the effect of a previous DIOENBCHS reqest.
X.Sh BUGS
XThere is no way to reliably detect a \fIDIO48S/AT-P\fP without the risk of
Xdamaging connected hardware.
X.Pp
XThe TST/BEN jumper must be set to BEN for this driver to operate correctly.
XAlso, only MODE 0 is supported by the \fIDIO48S/AT-P\fP.
X.Sh AUTHOR
XJamil J. Weatherbee <jamil@trojanhorse.ml.org>.
END-of-/usr/src/share/man/man4/man4.i386/dio.4
exit

>Audit-Trail:
>Unformatted:



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