staging: dgap: adds dgap driver to staging

This patch adds the dgap driver to staging. This is
a TTY serial port driver for the EPCA PCI based
product line by Digi International <www.digi.com>.

Signed-off-by: Lidza Louina <lidza.louina@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Scott_Kilau@digi.com 2013-08-21 21:48:31 -04:00 committed by Greg Kroah-Hartman
parent 6b5ad9d269
commit c84b8b503e
25 changed files with 14712 additions and 0 deletions

View File

@ -0,0 +1,6 @@
config DGAP
tristate "Digi EPCA PCI products"
default n
depends on TTY
---help---
Driver for the Digi International EPCA PCI based product line

View File

@ -0,0 +1,9 @@
EXTRA_CFLAGS += -DDG_NAME=\"dgap-1.3-16\" -DDG_PART=\"40002347_C\"
obj-$(CONFIG_DGAP) += dgap.o
dgap-objs := dgap_driver.o dgap_fep5.o dgap_mgmt.o \
dgap_parse.o dgap_proc.o dgap_trace.o \
dgap_tty.o dgap_sysfs.o

View File

@ -0,0 +1,290 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************
*
* dgap_conf.h - Header file for installations and parse files.
*
* $Id: dgap_conf.h,v 1.1 2009/10/23 14:01:57 markh Exp $
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef _DGAP_CONF_H
#define _DGAP_CONF_H
#define NULLNODE 0 /* header node, not used */
#define BNODE 1 /* Board node */
#define LNODE 2 /* Line node */
#define CNODE 3 /* Concentrator node */
#define MNODE 4 /* EBI Module node */
#define TNODE 5 /* tty name prefix node */
#define CUNODE 6 /* cu name prefix (non-SCO) */
#define PNODE 7 /* trans. print prefix node */
#define JNODE 8 /* maJor number node */
#define ANODE 9 /* altpin */
#define TSNODE 10 /* tty structure size */
#define CSNODE 11 /* channel structure size */
#define BSNODE 12 /* board structure size */
#define USNODE 13 /* unit schedule structure size */
#define FSNODE 14 /* f2200 structure size */
#define VSNODE 15 /* size of VPIX structures */
#define INTRNODE 16 /* enable interrupt */
/* Enumeration of tokens */
#define BEGIN 1
#define END 2
#define BOARD 10
#define EPCFS 11 /* start of EPC family definitions */
#define ICX 11
#define MCX 13
#define PCX 14
#define IEPC 15
#define EEPC 16
#define MEPC 17
#define IPCM 18
#define EPCM 19
#define MPCM 20
#define PEPC 21
#define PPCM 22
#ifdef CP
#define ICP 23
#define ECP 24
#define MCP 25
#endif
#define EPCFE 25 /* end of EPC family definitions */
#define PC2E 26
#define PC4E 27
#define PC4E8K 28
#define PC8E 29
#define PC8E8K 30
#define PC16E 31
#define MC2E8K 34
#define MC4E8K 35
#define MC8E8K 36
#define AVANFS 42 /* start of Avanstar family definitions */
#define A8P 42
#define A16P 43
#define AVANFE 43 /* end of Avanstar family definitions */
#define DA2000FS 44 /* start of AccelePort 2000 family definitions */
#define DA22 44 /* AccelePort 2002 */
#define DA24 45 /* AccelePort 2004 */
#define DA28 46 /* AccelePort 2008 */
#define DA216 47 /* AccelePort 2016 */
#define DAR4 48 /* AccelePort RAS 4 port */
#define DAR8 49 /* AccelePort RAS 8 port */
#define DDR24 50 /* DataFire RAS 24 port */
#define DDR30 51 /* DataFire RAS 30 port */
#define DDR48 52 /* DataFire RAS 48 port */
#define DDR60 53 /* DataFire RAS 60 port */
#define DA2000FE 53 /* end of AccelePort 2000/RAS family definitions */
#define PCXRFS 106 /* start of PCXR family definitions */
#define APORT4 106
#define APORT8 107
#define PAPORT4 108
#define PAPORT8 109
#define APORT4_920I 110
#define APORT8_920I 111
#define APORT4_920P 112
#define APORT8_920P 113
#define APORT2_920P 114
#define PCXRFE 117 /* end of PCXR family definitions */
#define LINE 82
#ifdef T1
#define T1M 83
#define E1M 84
#endif
#define CONC 64
#define CX 65
#define EPC 66
#define MOD 67
#define PORTS 68
#define METHOD 69
#define CUSTOM 70
#define BASIC 71
#define STATUS 72
#define MODEM 73
/* The following tokens can appear in multiple places */
#define SPEED 74
#define NPORTS 75
#define ID 76
#define CABLE 77
#define CONNECT 78
#define IO 79
#define MEM 80
#define DPSZ 81
#define TTYN 90
#define CU 91
#define PRINT 92
#define XPRINT 93
#define CMAJOR 94
#define ALTPIN 95
#define STARTO 96
#define USEINTR 97
#define PCIINFO 98
#define TTSIZ 100
#define CHSIZ 101
#define BSSIZ 102
#define UNTSIZ 103
#define F2SIZ 104
#define VPSIZ 105
#define TOTAL_BOARD 2
#define CURRENT_BRD 4
#define BOARD_TYPE 6
#define IO_ADDRESS 8
#define MEM_ADDRESS 10
#define FIELDS_PER_PAGE 18
#define TB_FIELD 1
#define CB_FIELD 3
#define BT_FIELD 5
#define IO_FIELD 7
#define ID_FIELD 8
#define ME_FIELD 9
#define TTY_FIELD 11
#define CU_FIELD 13
#define PR_FIELD 15
#define MPR_FIELD 17
#define MAX_FIELD 512
#define INIT 0
#define NITEMS 128
#define MAX_ITEM 512
#define DSCRINST 1
#define DSCRNUM 3
#define ALTPINQ 5
#define SSAVE 7
#define DSCR "32"
#define ONETONINE "123456789"
#define ALL "1234567890"
struct cnode {
struct cnode *next;
int type;
int numbrd;
union {
struct {
char type; /* Board Type */
short port; /* I/O Address */
char *portstr; /* I/O Address in string */
long addr; /* Memory Address */
char *addrstr; /* Memory Address in string */
long pcibus; /* PCI BUS */
char *pcibusstr; /* PCI BUS in string */
long pcislot; /* PCI SLOT */
char *pcislotstr; /* PCI SLOT in string */
char nport; /* Number of Ports */
char *id; /* tty id */
int start; /* start of tty counting */
char *method; /* Install method */
char v_type;
char v_port;
char v_addr;
char v_pcibus;
char v_pcislot;
char v_nport;
char v_id;
char v_start;
char v_method;
char line1;
char line2;
char conc1; /* total concs in line1 */
char conc2; /* total concs in line2 */
char module1; /* total modules for line1 */
char module2; /* total modules for line2 */
char *status; /* config status */
char *dimstatus; /* Y/N */
int status_index; /* field pointer */
} board;
struct {
char *cable;
char v_cable;
char speed;
char v_speed;
} line;
struct {
char type;
char *connect;
char speed;
char nport;
char *id;
char *idstr;
int start;
char v_type;
char v_connect;
char v_speed;
char v_nport;
char v_id;
char v_start;
} conc;
struct {
char type;
char nport;
char *id;
char *idstr;
int start;
char v_type;
char v_nport;
char v_id;
char v_start;
} module;
char *ttyname;
char *cuname;
char *printname;
int majornumber;
int altpin;
int ttysize;
int chsize;
int bssize;
int unsize;
int f2size;
int vpixsize;
int useintr;
} u;
};
#endif

View File

@ -0,0 +1,69 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: dgap_downld.h,v 1.1 2009/10/23 14:01:57 markh Exp $
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*
*/
/*
** downld.h
** - describes the interface between the user level download process
** and the concentrator download driver.
*/
#ifndef _DGAP_DOWNLD_H_
#define _DGAP_DOWNLD_H_
struct fepimg {
int type; /* board type */
int len; /* length of image */
char fepimage[1]; /* begining of image */
};
struct downldio {
unsigned int req_type; /* FEP or concentrator */
unsigned int bdid; /* opaque board identifier */
union {
struct downld_t dl; /* download structure */
struct fepimg fi; /* fep/bios image structure */
} image;
};
#define DIGI_DLREQ_GET (('d'<<8) | 220)
#define DIGI_DLREQ_SET (('d'<<8) | 221)
#define DIGI_DL_NUKE (('d'<<8) | 222) /* Not really a dl request, but
dangerous enuff to not put in
digi.h */
/* Packed bits of intarg for DIGI_DL_NUKE */
#define DIGI_NUKE_RESET_ALL (1 << 31)
#define DIGI_NUKE_INHIBIT_POLLER (1 << 30)
#define DIGI_NUKE_BRD_NUMB 0x0f
#define DLREQ_BIOS 0
#define DLREQ_FEP 1
#define DLREQ_CONC 2
#define DLREQ_CONFIG 3
#define DLREQ_DEVCREATE 4
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,626 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*
*************************************************************************
*
* Driver includes
*
*************************************************************************/
#ifndef __DGAP_DRIVER_H
#define __DGAP_DRIVER_H
#include <linux/version.h> /* To get the current Linux version */
#include <linux/types.h> /* To pick up the varions Linux types */
#include <linux/tty.h> /* To pick up the various tty structs/defines */
#include <linux/interrupt.h> /* For irqreturn_t type */
#include "dgap_types.h" /* Additional types needed by the Digi header files */
#include "digi.h" /* Digi specific ioctl header */
#include "dgap_kcompat.h" /* Kernel 2.4/2.6 compat includes */
#include "dgap_sysfs.h" /* Support for SYSFS */
/*************************************************************************
*
* Driver defines
*
*************************************************************************/
/*
* Driver identification, error and debugging statments
*
* In theory, you can change all occurances of "digi" in the next
* three lines, and the driver printk's will all automagically change.
*
* APR((fmt, args, ...)); Always prints message
* DPR((fmt, args, ...)); Only prints if DGAP_TRACER is defined at
* compile time and dgap_debug!=0
*/
#define PROCSTR "dgap" /* /proc entries */
#define DEVSTR "/dev/dg/dgap" /* /dev entries */
#define DRVSTR "dgap" /* Driver name string
* displayed by APR */
#define APR(args) do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
} while (0)
#define RAPR(args) do { PRINTF_TO_KMEM(args); printk args; } while (0)
#define TRC_TO_CONSOLE 1
/*
* Debugging levels can be set using debug insmod variable
* They can also be compiled out completely.
*/
#define DBG_INIT (dgap_debug & 0x01)
#define DBG_BASIC (dgap_debug & 0x02)
#define DBG_CORE (dgap_debug & 0x04)
#define DBG_OPEN (dgap_debug & 0x08)
#define DBG_CLOSE (dgap_debug & 0x10)
#define DBG_READ (dgap_debug & 0x20)
#define DBG_WRITE (dgap_debug & 0x40)
#define DBG_IOCTL (dgap_debug & 0x80)
#define DBG_PROC (dgap_debug & 0x100)
#define DBG_PARAM (dgap_debug & 0x200)
#define DBG_PSCAN (dgap_debug & 0x400)
#define DBG_EVENT (dgap_debug & 0x800)
#define DBG_DRAIN (dgap_debug & 0x1000)
#define DBG_CARR (dgap_debug & 0x2000)
#define DBG_MGMT (dgap_debug & 0x4000)
#if defined(DGAP_TRACER)
# if defined(TRC_TO_KMEM)
/* Choose one: */
# define TRC_ON_OVERFLOW_WRAP_AROUND
# undef TRC_ON_OVERFLOW_SHIFT_BUFFER
# endif //TRC_TO_KMEM
# define TRC_MAXMSG 1024
# define TRC_OVERFLOW "(OVERFLOW)"
# define TRC_DTRC "/usr/bin/dtrc"
#if defined TRC_TO_CONSOLE
#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
#else //!defined TRACE_TO_CONSOLE
#define PRINTF_TO_CONSOLE(args)
#endif
#if defined TRC_TO_KMEM
#define PRINTF_TO_KMEM(args) dgap_tracef args
#else //!defined TRC_TO_KMEM
#define PRINTF_TO_KMEM(args)
#endif
#define TRC(args) { PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
# define DPR_INIT(ARGS) if (DBG_INIT) TRC(ARGS)
# define DPR_BASIC(ARGS) if (DBG_BASIC) TRC(ARGS)
# define DPR_CORE(ARGS) if (DBG_CORE) TRC(ARGS)
# define DPR_OPEN(ARGS) if (DBG_OPEN) TRC(ARGS)
# define DPR_CLOSE(ARGS) if (DBG_CLOSE) TRC(ARGS)
# define DPR_READ(ARGS) if (DBG_READ) TRC(ARGS)
# define DPR_WRITE(ARGS) if (DBG_WRITE) TRC(ARGS)
# define DPR_IOCTL(ARGS) if (DBG_IOCTL) TRC(ARGS)
# define DPR_PROC(ARGS) if (DBG_PROC) TRC(ARGS)
# define DPR_PARAM(ARGS) if (DBG_PARAM) TRC(ARGS)
# define DPR_PSCAN(ARGS) if (DBG_PSCAN) TRC(ARGS)
# define DPR_EVENT(ARGS) if (DBG_EVENT) TRC(ARGS)
# define DPR_DRAIN(ARGS) if (DBG_DRAIN) TRC(ARGS)
# define DPR_CARR(ARGS) if (DBG_CARR) TRC(ARGS)
# define DPR_MGMT(ARGS) if (DBG_MGMT) TRC(ARGS)
# define DPR(ARGS) if (dgap_debug) TRC(ARGS)
# define P(X) dgap_tracef(#X "=%p\n", X)
# define X(X) dgap_tracef(#X "=%x\n", X)
#else//!defined DGAP_TRACER
#define PRINTF_TO_KMEM(args)
# define TRC(ARGS)
# define DPR_INIT(ARGS)
# define DPR_BASIC(ARGS)
# define DPR_CORE(ARGS)
# define DPR_OPEN(ARGS)
# define DPR_CLOSE(ARGS)
# define DPR_READ(ARGS)
# define DPR_WRITE(ARGS)
# define DPR_IOCTL(ARGS)
# define DPR_PROC(ARGS)
# define DPR_PARAM(ARGS)
# define DPR_PSCAN(ARGS)
# define DPR_EVENT(ARGS)
# define DPR_DRAIN(ARGS)
# define DPR_CARR(ARGS)
# define DPR_MGMT(ARGS)
# define DPR(args)
#endif//DGAP_TRACER
/* Number of boards we support at once. */
#define MAXBOARDS 32
#define MAXPORTS 224
#define MAXTTYNAMELEN 200
/* Our 3 magic numbers for our board, channel and unit structs */
#define DGAP_BOARD_MAGIC 0x5c6df104
#define DGAP_CHANNEL_MAGIC 0x6c6df104
#define DGAP_UNIT_MAGIC 0x7c6df104
/* Serial port types */
#define DGAP_SERIAL 0
#define DGAP_PRINT 1
#define SERIAL_TYPE_NORMAL 1
/* 4 extra for alignment play space */
#define WRITEBUFLEN ((4096) + 4)
#define MYFLIPLEN N_TTY_BUF_SIZE
#define SBREAK_TIME 0x25
#define U2BSIZE 0x400
#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
/*
* Our major for the mgmt devices.
*
* We can use 22, because Digi was allocated 22 and 23 for the epca driver.
* 22 has now become obsolete now that the "cu" devices have
* been removed from 2.6.
* Also, this *IS* the epca driver, just PCI only now.
*/
#ifndef DIGI_DGAP_MAJOR
# define DIGI_DGAP_MAJOR 22
#endif
/*
* The parameters we use to define the periods of the moving averages.
*/
#define MA_PERIOD (HZ / 10)
#define SMA_DUR (1 * HZ)
#define EMA_DUR (1 * HZ)
#define SMA_NPERIODS (SMA_DUR / MA_PERIOD)
#define EMA_NPERIODS (EMA_DUR / MA_PERIOD)
/*
* Define a local default termios struct. All ports will be created
* with this termios initially. This is the same structure that is defined
* as the default in tty_io.c with the same settings overriden as in serial.c
*
* In short, this should match the internal serial ports' defaults.
*/
#define DEFAULT_IFLAGS (ICRNL | IXON)
#define DEFAULT_OFLAGS (OPOST | ONLCR)
#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL)
#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \
ECHOCTL | ECHOKE | IEXTEN)
#ifndef _POSIX_VDISABLE
#define _POSIX_VDISABLE '\0'
#endif
#define SNIFF_MAX 65536 /* Sniff buffer size (2^n) */
#define SNIFF_MASK (SNIFF_MAX - 1) /* Sniff wrap mask */
#define VPDSIZE (512)
/*
* Lock function/defines.
* Makes spotting lock/unlock locations easier.
*/
# define DGAP_SPINLOCK_INIT(x) spin_lock_init(&(x))
# define DGAP_LOCK(x,y) spin_lock_irqsave(&(x), y)
# define DGAP_UNLOCK(x,y) spin_unlock_irqrestore(&(x), y)
# define DGAP_TRYLOCK(x,y) spin_trylock(&(x))
/*
* All the possible states the driver can be while being loaded.
*/
enum {
DRIVER_INITIALIZED = 0,
DRIVER_NEED_CONFIG_LOAD,
DRIVER_REQUESTED_CONFIG,
DRIVER_READY
};
/*
* All the possible states the board can be while booting up.
*/
enum {
BOARD_FAILED = 0,
CONFIG_NOT_FOUND,
BOARD_FOUND,
NEED_RESET,
FINISHED_RESET,
NEED_CONFIG,
FINISHED_CONFIG,
NEED_DEVICE_CREATION,
REQUESTED_DEVICE_CREATION,
FINISHED_DEVICE_CREATION,
NEED_BIOS_LOAD,
REQUESTED_BIOS,
WAIT_BIOS_LOAD,
FINISHED_BIOS_LOAD,
NEED_FEP_LOAD,
REQUESTED_FEP,
WAIT_FEP_LOAD,
FINISHED_FEP_LOAD,
NEED_PROC_CREATION,
FINISHED_PROC_CREATION,
BOARD_READY
};
/*
* All the possible states that a requested concentrator image can be in.
*/
enum {
NO_PENDING_CONCENTRATOR_REQUESTS = 0,
NEED_CONCENTRATOR,
REQUESTED_CONCENTRATOR
};
extern char *dgap_state_text[];
extern char *dgap_driver_state_text[];
/*
* Modem line constants are defined as macros because DSR and
* DCD are swapable using the ditty altpin option.
*/
#define D_CD(ch) ch->ch_cd /* Carrier detect */
#define D_DSR(ch) ch->ch_dsr /* Data set ready */
#define D_RTS(ch) DM_RTS /* Request to send */
#define D_CTS(ch) DM_CTS /* Clear to send */
#define D_RI(ch) DM_RI /* Ring indicator */
#define D_DTR(ch) DM_DTR /* Data terminal ready */
/*************************************************************************
*
* Structures and closely related defines.
*
*************************************************************************/
/*
* A structure to hold a statistics counter. We also
* compute moving averages for this counter.
*/
struct macounter
{
u32 cnt; /* Total count */
ulong accum; /* Acuumulator per period */
ulong sma; /* Simple moving average */
ulong ema; /* Exponential moving average */
};
/************************************************************************
* Device flag definitions for bd_flags.
************************************************************************/
#define BD_FEP5PLUS 0x0001 /* Supports FEP5 Plus commands */
#define BD_HAS_VPD 0x0002 /* Board has VPD info available */
/*
* Per-board information
*/
struct board_t
{
int magic; /* Board Magic number. */
int boardnum; /* Board number: 0-3 */
int firstminor; /* First minor, e.g. 0, 30, 60 */
int type; /* Type of board */
char *name; /* Product Name */
struct pci_dev *pdev; /* Pointer to the pci_dev struct */
u16 vendor; /* PCI vendor ID */
u16 device; /* PCI device ID */
u16 subvendor; /* PCI subsystem vendor ID */
u16 subdevice; /* PCI subsystem device ID */
uchar rev; /* PCI revision ID */
uint pci_bus; /* PCI bus value */
uint pci_slot; /* PCI slot value */
u16 maxports; /* MAX ports this board can handle */
uchar vpd[VPDSIZE]; /* VPD of board, if found */
u32 bd_flags; /* Board flags */
spinlock_t bd_lock; /* Used to protect board */
u32 state; /* State of card. */
wait_queue_head_t state_wait; /* Place to sleep on for state change */
struct tasklet_struct helper_tasklet; /* Poll helper tasklet */
u32 wait_for_bios;
u32 wait_for_fep;
struct cnode * bd_config; /* Config of board */
u16 nasync; /* Number of ports on card */
u32 use_interrupts; /* Should we be interrupt driven? */
ulong irq; /* Interrupt request number */
ulong intr_count; /* Count of interrupts */
u32 intr_used; /* Non-zero if using interrupts */
u32 intr_running; /* Non-zero if FEP knows its doing interrupts */
ulong port; /* Start of base io port of the card */
ulong port_end; /* End of base io port of the card */
ulong membase; /* Start of base memory of the card */
ulong membase_end; /* End of base memory of the card */
uchar *re_map_port; /* Remapped io port of the card */
uchar *re_map_membase;/* Remapped memory of the card */
uchar runwait; /* # Processes waiting for FEP */
uchar inhibit_poller; /* Tells the poller to leave us alone */
struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
struct tty_driver *SerialDriver;
char SerialName[200];
struct tty_driver *PrintDriver;
char PrintName[200];
u32 dgap_Major_Serial_Registered;
u32 dgap_Major_TransparentPrint_Registered;
u32 dgap_Serial_Major;
u32 dgap_TransparentPrint_Major;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
u32 TtyRefCnt;
#endif
struct bs_t *bd_bs; /* Base structure pointer */
char *flipbuf; /* Our flip buffer, alloced if board is found */
char *flipflagbuf; /* Our flip flag buffer, alloced if board is found */
u16 dpatype; /* The board "type", as defined by DPA */
u16 dpastatus; /* The board "status", as defined by DPA */
wait_queue_head_t kme_wait; /* Needed for DPA support */
u32 conc_dl_status; /* Status of any pending conc download */
/*
* Mgmt data.
*/
char *msgbuf_head;
char *msgbuf;
/* /proc/<board> entries */
struct proc_dir_entry *proc_entry_pointer;
struct dgap_proc_entry *dgap_board_table;
};
/************************************************************************
* Unit flag definitions for un_flags.
************************************************************************/
#define UN_ISOPEN 0x0001 /* Device is open */
#define UN_CLOSING 0x0002 /* Line is being closed */
#define UN_IMM 0x0004 /* Service immediately */
#define UN_BUSY 0x0008 /* Some work this channel */
#define UN_BREAKI 0x0010 /* Input break received */
#define UN_PWAIT 0x0020 /* Printer waiting for terminal */
#define UN_TIME 0x0040 /* Waiting on time */
#define UN_EMPTY 0x0080 /* Waiting output queue empty */
#define UN_LOW 0x0100 /* Waiting output low water mark*/
#define UN_EXCL_OPEN 0x0200 /* Open for exclusive use */
#define UN_WOPEN 0x0400 /* Device waiting for open */
#define UN_WIOCTL 0x0800 /* Device waiting for open */
#define UN_HANGUP 0x8000 /* Carrier lost */
struct device;
/************************************************************************
* Structure for terminal or printer unit.
************************************************************************/
struct un_t {
int magic; /* Unit Magic Number. */
struct channel_t *un_ch;
u32 un_time;
u32 un_type;
u32 un_open_count; /* Counter of opens to port */
struct tty_struct *un_tty;/* Pointer to unit tty structure */
u32 un_flags; /* Unit flags */
wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
u32 un_dev; /* Minor device number */
tcflag_t un_oflag; /* oflags being done on board */
tcflag_t un_lflag; /* lflags being done on board */
struct device *un_sysfs;
};
/************************************************************************
* Device flag definitions for ch_flags.
************************************************************************/
#define CH_PRON 0x0001 /* Printer on string */
#define CH_OUT 0x0002 /* Dial-out device open */
#define CH_STOP 0x0004 /* Output is stopped */
#define CH_STOPI 0x0008 /* Input is stopped */
#define CH_CD 0x0010 /* Carrier is present */
#define CH_FCAR 0x0020 /* Carrier forced on */
#define CH_RXBLOCK 0x0080 /* Enable rx blocked flag */
#define CH_WLOW 0x0100 /* Term waiting low event */
#define CH_WEMPTY 0x0200 /* Term waiting empty event */
#define CH_RENABLE 0x0400 /* Buffer just emptied */
#define CH_RACTIVE 0x0800 /* Process active in xxread() */
#define CH_RWAIT 0x1000 /* Process waiting in xxread() */
#define CH_BAUD0 0x2000 /* Used for checking B0 transitions */
#define CH_HANGUP 0x8000 /* Hangup received */
/*
* Definitions for ch_sniff_flags
*/
#define SNIFF_OPEN 0x1
#define SNIFF_WAIT_DATA 0x2
#define SNIFF_WAIT_SPACE 0x4
/************************************************************************
* Channel information structure.
************************************************************************/
struct channel_t {
int magic; /* Channel Magic Number */
struct bs_t *ch_bs; /* Base structure pointer */
struct cm_t *ch_cm; /* Command queue pointer */
struct board_t *ch_bd; /* Board structure pointer */
unsigned char *ch_vaddr; /* FEP memory origin */
unsigned char *ch_taddr; /* Write buffer origin */
unsigned char *ch_raddr; /* Read buffer origin */
struct digi_t ch_digi; /* Transparent Print structure */
struct un_t ch_tun; /* Terminal unit info */
struct un_t ch_pun; /* Printer unit info */
spinlock_t ch_lock; /* provide for serialization */
wait_queue_head_t ch_flags_wait;
u32 pscan_state;
uchar pscan_savechar;
u32 ch_portnum; /* Port number, 0 offset. */
u32 ch_open_count; /* open count */
u32 ch_flags; /* Channel flags */
u32 ch_close_delay; /* How long we should drop RTS/DTR for */
u32 ch_cpstime; /* Time for CPS calculations */
tcflag_t ch_c_iflag; /* channel iflags */
tcflag_t ch_c_cflag; /* channel cflags */
tcflag_t ch_c_oflag; /* channel oflags */
tcflag_t ch_c_lflag; /* channel lflags */
u16 ch_fepiflag; /* FEP tty iflags */
u16 ch_fepcflag; /* FEP tty cflags */
u16 ch_fepoflag; /* FEP tty oflags */
u16 ch_wopen; /* Waiting for open process cnt */
u16 ch_tstart; /* Transmit buffer start */
u16 ch_tsize; /* Transmit buffer size */
u16 ch_rstart; /* Receive buffer start */
u16 ch_rsize; /* Receive buffer size */
u16 ch_rdelay; /* Receive delay time */
u16 ch_tlw; /* Our currently set low water mark */
u16 ch_cook; /* Output character mask */
uchar ch_card; /* Card channel is on */
uchar ch_stopc; /* Stop character */
uchar ch_startc; /* Start character */
uchar ch_mostat; /* FEP output modem status */
uchar ch_mistat; /* FEP input modem status */
uchar ch_mforce; /* Modem values to be forced */
uchar ch_mval; /* Force values */
uchar ch_fepstopc; /* FEP stop character */
uchar ch_fepstartc; /* FEP start character */
uchar ch_astopc; /* Auxiliary Stop character */
uchar ch_astartc; /* Auxiliary Start character */
uchar ch_fepastopc; /* Auxiliary FEP stop char */
uchar ch_fepastartc; /* Auxiliary FEP start char */
uchar ch_hflow; /* FEP hardware handshake */
uchar ch_dsr; /* stores real dsr value */
uchar ch_cd; /* stores real cd value */
uchar ch_tx_win; /* channel tx buffer window */
uchar ch_rx_win; /* channel rx buffer window */
uint ch_custom_speed; /* Custom baud, if set */
uint ch_baud_info; /* Current baud info for /proc output */
ulong ch_rxcount; /* total of data received so far */
ulong ch_txcount; /* total of data transmitted so far */
ulong ch_err_parity; /* Count of parity errors on channel */
ulong ch_err_frame; /* Count of framing errors on channel */
ulong ch_err_break; /* Count of breaks on channel */
ulong ch_err_overrun; /* Count of overruns on channel */
/* /proc/<board>/<channel> entries */
struct proc_dir_entry *proc_entry_pointer;
struct dgap_proc_entry *dgap_channel_table;
uint ch_sniff_in;
uint ch_sniff_out;
char *ch_sniff_buf; /* Sniff buffer for proc */
ulong ch_sniff_flags; /* Channel flags */
wait_queue_head_t ch_sniff_wait;
};
/*************************************************************************
*
* Prototypes for non-static functions used in more than one module
*
*************************************************************************/
extern int dgap_ms_sleep(ulong ms);
extern void *dgap_driver_kzmalloc(size_t size, int priority);
extern char *dgap_ioctl_name(int cmd);
extern void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len);
extern void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len);
extern void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len);
extern void dgap_do_config_load(uchar __user *uaddr, int len);
extern int dgap_after_config_loaded(void);
extern int dgap_finalize_board_init(struct board_t *brd);
/*
* Our Global Variables.
*/
extern int dgap_driver_state; /* The state of the driver */
extern int dgap_debug; /* Debug variable */
extern int dgap_rawreadok; /* Set if user wants rawreads */
extern int dgap_poll_tick; /* Poll interval - 20 ms */
extern spinlock_t dgap_global_lock; /* Driver global spinlock */
extern uint dgap_NumBoards; /* Total number of boards */
extern struct board_t *dgap_Board[MAXBOARDS]; /* Array of board structs */
extern ulong dgap_poll_counter; /* Times the poller has run */
extern char *dgap_config_buf; /* The config file buffer */
extern spinlock_t dgap_dl_lock; /* Downloader spinlock */
extern wait_queue_head_t dgap_dl_wait; /* Wait queue for downloader */
extern int dgap_dl_action; /* Action flag for downloader */
extern int dgap_registerttyswithsysfs; /* Should we register the */
/* ttys with sysfs or not */
/*
* Global functions declared in dgap_fep5.c, but must be hidden from
* user space programs.
*/
extern void dgap_poll_tasklet(unsigned long data);
extern void dgap_cmdb(struct channel_t *ch, uchar cmd, uchar byte1, uchar byte2, uint ncmds);
extern void dgap_cmdw(struct channel_t *ch, uchar cmd, u16 word, uint ncmds);
extern void dgap_wmove(struct channel_t *ch, char *buf, uint cnt);
extern int dgap_param(struct tty_struct *tty);
extern void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len);
extern uint dgap_get_custom_baud(struct channel_t *ch);
extern void dgap_firmware_reset_port(struct channel_t *ch);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,253 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*
************************************************************************
*** FEP Version 5 dependent definitions
************************************************************************/
#ifndef __DGAP_FEP5_H
#define __DGAP_FEP5_H
/************************************************************************
* FEP memory offsets
************************************************************************/
#define START 0x0004L /* Execution start address */
#define CMDBUF 0x0d10L /* Command (cm_t) structure offset */
#define CMDSTART 0x0400L /* Start of command buffer */
#define CMDMAX 0x0800L /* End of command buffer */
#define EVBUF 0x0d18L /* Event (ev_t) structure */
#define EVSTART 0x0800L /* Start of event buffer */
#define EVMAX 0x0c00L /* End of event buffer */
#define FEP5_PLUS 0x0E40 /* ASCII '5' and ASCII 'A' is here */
#define ECS_SEG 0x0E44 /* Segment of the extended channel structure */
#define LINE_SPEED 0x10 /* Offset into ECS_SEG for line speed */
/* if the fep has extended capabilities */
/* BIOS MAGIC SPOTS */
#define ERROR 0x0C14L /* BIOS error code */
#define SEQUENCE 0x0C12L /* BIOS sequence indicator */
#define POSTAREA 0x0C00L /* POST complete message area */
/* FEP MAGIC SPOTS */
#define FEPSTAT POSTAREA /* OS here when FEP comes up */
#define NCHAN 0x0C02L /* number of ports FEP sees */
#define PANIC 0x0C10L /* PANIC area for FEP */
#define KMEMEM 0x0C30L /* Memory for KME use */
#define CONFIG 0x0CD0L /* Concentrator configuration info */
#define CONFIGSIZE 0x0030 /* configuration info size */
#define DOWNREQ 0x0D00 /* Download request buffer pointer */
#define CHANBUF 0x1000L /* Async channel (bs_t) structs */
#define FEPOSSIZE 0x1FFF /* 8K FEPOS */
#define XEMPORTS 0xC02 /*
* Offset in board memory where FEP5 stores
* how many ports it has detected.
* NOTE: FEP5 reports 64 ports when the user
* has the cable in EBI OUT instead of EBI IN.
*/
#define FEPCLR 0x00
#define FEPMEM 0x02
#define FEPRST 0x04
#define FEPINT 0x08
#define FEPMASK 0x0e
#define FEPWIN 0x80
#define LOWMEM 0x0100
#define HIGHMEM 0x7f00
#define FEPTIMEOUT 200000
#define ENABLE_INTR 0x0e04 /* Enable interrupts flag */
#define FEPPOLL_MIN 1 /* minimum of 1 millisecond */
#define FEPPOLL_MAX 20 /* maximum of 20 milliseconds */
#define FEPPOLL 0x0c26 /* Fep event poll interval */
#define IALTPIN 0x0080 /* Input flag to swap DSR <-> DCD */
/************************************************************************
* Command structure definition.
************************************************************************/
struct cm_t {
volatile unsigned short cm_head; /* Command buffer head offset */
volatile unsigned short cm_tail; /* Command buffer tail offset */
volatile unsigned short cm_start; /* start offset of buffer */
volatile unsigned short cm_max; /* last offset of buffer */
};
/************************************************************************
* Event structure definition.
************************************************************************/
struct ev_t {
volatile unsigned short ev_head; /* Command buffer head offset */
volatile unsigned short ev_tail; /* Command buffer tail offset */
volatile unsigned short ev_start; /* start offset of buffer */
volatile unsigned short ev_max; /* last offset of buffer */
};
/************************************************************************
* Download buffer structure.
************************************************************************/
struct downld_t {
uchar dl_type; /* Header */
uchar dl_seq; /* Download sequence */
ushort dl_srev; /* Software revision number */
ushort dl_lrev; /* Low revision number */
ushort dl_hrev; /* High revision number */
ushort dl_seg; /* Start segment address */
ushort dl_size; /* Number of bytes to download */
uchar dl_data[1024]; /* Download data */
};
/************************************************************************
* Per channel buffer structure
************************************************************************
* Base Structure Entries Usage Meanings to Host *
* *
* W = read write R = read only *
* C = changed by commands only *
* U = unknown (may be changed w/o notice) *
************************************************************************/
struct bs_t {
volatile unsigned short tp_jmp; /* Transmit poll jump */
volatile unsigned short tc_jmp; /* Cooked procedure jump */
volatile unsigned short ri_jmp; /* Not currently used */
volatile unsigned short rp_jmp; /* Receive poll jump */
volatile unsigned short tx_seg; /* W Tx segment */
volatile unsigned short tx_head; /* W Tx buffer head offset */
volatile unsigned short tx_tail; /* R Tx buffer tail offset */
volatile unsigned short tx_max; /* W Tx buffer size - 1 */
volatile unsigned short rx_seg; /* W Rx segment */
volatile unsigned short rx_head; /* W Rx buffer head offset */
volatile unsigned short rx_tail; /* R Rx buffer tail offset */
volatile unsigned short rx_max; /* W Rx buffer size - 1 */
volatile unsigned short tx_lw; /* W Tx buffer low water mark */
volatile unsigned short rx_lw; /* W Rx buffer low water mark */
volatile unsigned short rx_hw; /* W Rx buffer high water mark */
volatile unsigned short incr; /* W Increment to next channel */
volatile unsigned short fepdev; /* U SCC device base address */
volatile unsigned short edelay; /* W Exception delay */
volatile unsigned short blen; /* W Break length */
volatile unsigned short btime; /* U Break complete time */
volatile unsigned short iflag; /* C UNIX input flags */
volatile unsigned short oflag; /* C UNIX output flags */
volatile unsigned short cflag; /* C UNIX control flags */
volatile unsigned short wfill[13]; /* U Reserved for expansion */
volatile unsigned char num; /* U Channel number */
volatile unsigned char ract; /* U Receiver active counter */
volatile unsigned char bstat; /* U Break status bits */
volatile unsigned char tbusy; /* W Transmit busy */
volatile unsigned char iempty; /* W Transmit empty event enable */
volatile unsigned char ilow; /* W Transmit low-water event enable */
volatile unsigned char idata; /* W Receive data interrupt enable */
volatile unsigned char eflag; /* U Host event flags */
volatile unsigned char tflag; /* U Transmit flags */
volatile unsigned char rflag; /* U Receive flags */
volatile unsigned char xmask; /* U Transmit ready flags */
volatile unsigned char xval; /* U Transmit ready value */
volatile unsigned char m_stat; /* RC Modem status bits */
volatile unsigned char m_change; /* U Modem bits which changed */
volatile unsigned char m_int; /* W Modem interrupt enable bits */
volatile unsigned char m_last; /* U Last modem status */
volatile unsigned char mtran; /* C Unreported modem trans */
volatile unsigned char orun; /* C Buffer overrun occurred */
volatile unsigned char astartc; /* W Auxiliary Xon char */
volatile unsigned char astopc; /* W Auxiliary Xoff char */
volatile unsigned char startc; /* W Xon character */
volatile unsigned char stopc; /* W Xoff character */
volatile unsigned char vnextc; /* W Vnext character */
volatile unsigned char hflow; /* C Software flow control */
volatile unsigned char fillc; /* U Delay Fill character */
volatile unsigned char ochar; /* U Saved output character */
volatile unsigned char omask; /* U Output character mask */
volatile unsigned char bfill[13]; /* U Reserved for expansion */
volatile unsigned char scc[16]; /* U SCC registers */
};
/************************************************************************
* FEP supported functions
************************************************************************/
#define SRLOW 0xe0 /* Set receive low water */
#define SRHIGH 0xe1 /* Set receive high water */
#define FLUSHTX 0xe2 /* Flush transmit buffer */
#define PAUSETX 0xe3 /* Pause data transmission */
#define RESUMETX 0xe4 /* Resume data transmission */
#define SMINT 0xe5 /* Set Modem Interrupt */
#define SAFLOWC 0xe6 /* Set Aux. flow control chars */
#define SBREAK 0xe8 /* Send break */
#define SMODEM 0xe9 /* Set 8530 modem control lines */
#define SIFLAG 0xea /* Set UNIX iflags */
#define SFLOWC 0xeb /* Set flow control characters */
#define STLOW 0xec /* Set transmit low water mark */
#define RPAUSE 0xee /* Pause recieve */
#define RRESUME 0xef /* Resume receive */
#define CHRESET 0xf0 /* Reset Channel */
#define BUFSETALL 0xf2 /* Set Tx & Rx buffer size avail*/
#define SOFLAG 0xf3 /* Set UNIX oflags */
#define SHFLOW 0xf4 /* Set hardware handshake */
#define SCFLAG 0xf5 /* Set UNIX cflags */
#define SVNEXT 0xf6 /* Set VNEXT character */
#define SPINTFC 0xfc /* Reserved */
#define SCOMMODE 0xfd /* Set RS232/422 mode */
/************************************************************************
* Modes for SCOMMODE
************************************************************************/
#define MODE_232 0x00
#define MODE_422 0x01
/************************************************************************
* Event flags.
************************************************************************/
#define IFBREAK 0x01 /* Break received */
#define IFTLW 0x02 /* Transmit low water */
#define IFTEM 0x04 /* Transmitter empty */
#define IFDATA 0x08 /* Receive data present */
#define IFMODEM 0x20 /* Modem status change */
/************************************************************************
* Modem flags
************************************************************************/
# define DM_RTS 0x02 /* Request to send */
# define DM_CD 0x80 /* Carrier detect */
# define DM_DSR 0x20 /* Data set ready */
# define DM_CTS 0x10 /* Clear to send */
# define DM_RI 0x40 /* Ring indicator */
# define DM_DTR 0x01 /* Data terminal ready */
#endif

View File

@ -0,0 +1,93 @@
/*
* Copyright 2004 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*
*************************************************************************
*
* This file is intended to contain all the kernel "differences" between the
* various kernels that we support.
*
*************************************************************************/
#ifndef __DGAP_KCOMPAT_H
#define __DGAP_KCOMPAT_H
# ifndef KERNEL_VERSION
# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
# endif
#if !defined(TTY_FLIPBUF_SIZE)
# define TTY_FLIPBUF_SIZE 512
#endif
/* Sparse stuff */
# ifndef __user
# define __user
# define __kernel
# define __safe
# define __force
# define __chk_user_ptr(x) (void)0
# endif
# define PARM_STR(VAR, INIT, PERM, DESC) \
static char *VAR = INIT; \
char *dgap_##VAR; \
module_param(VAR, charp, PERM); \
MODULE_PARM_DESC(VAR, DESC);
# define PARM_INT(VAR, INIT, PERM, DESC) \
static int VAR = INIT; \
int dgap_##VAR; \
module_param(VAR, int, PERM); \
MODULE_PARM_DESC(VAR, DESC);
# define PARM_ULONG(VAR, INIT, PERM, DESC) \
static ulong VAR = INIT; \
ulong dgap_##VAR; \
module_param(VAR, long, PERM); \
MODULE_PARM_DESC(VAR, DESC);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
/* NOTHING YET */
# else
# error "this driver does not support anything below the 2.6.27 kernel series."
# endif
#endif /* ! __DGAP_KCOMPAT_H */

View File

@ -0,0 +1,768 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
*
* This is shared code between Digi's CVS archive and the
* Linux Kernel sources.
* Changing the source just for reformatting needlessly breaks
* our CVS diff history.
*
* Send any bug fixes/changes to: Eng.Linux at digi dot com.
* Thank you.
*
*/
/************************************************************************
*
* This file implements the mgmt functionality for the
* FEP5 based product lines.
*
************************************************************************
* $Id: dgap_mgmt.c,v 1.2 2010/12/13 19:38:04 markh Exp $
*/
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/ctype.h>
#include <linux/sched.h> /* For jiffies, task states */
#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
#include <linux/pci.h>
#include <linux/serial_reg.h>
#include <linux/termios.h>
#include <asm/uaccess.h> /* For copy_from_user/copy_to_user */
#include <asm/io.h> /* For read[bwl]/write[bwl] */
#include "dgap_driver.h"
#include "dgap_kcompat.h" /* Kernel 2.4/2.6 compat includes */
#include "dgap_fep5.h"
#include "dgap_parse.h"
#include "dgap_mgmt.h"
#include "dgap_downld.h"
#include "dgap_tty.h"
#include "dgap_proc.h"
#include "dgap_sysfs.h"
/* This holds the status of the KME buffer */
static int dgap_kmebusy = 0;
/* Our "in use" variables, to enforce 1 open only */
static int dgap_mgmt_in_use = 0;
static int dgap_downld_in_use = 0;
/*
* dgap_mgmt_open()
*
* Open the mgmt/downld/dpa device
*/
int dgap_mgmt_open(struct inode *inode, struct file *file)
{
unsigned long lock_flags;
unsigned int minor = iminor(inode);
DPR_MGMT(("dgap_mgmt_open start.\n"));
DGAP_LOCK(dgap_global_lock, lock_flags);
/* mgmt device */
if (minor == MGMT_MGMT) {
/* Only allow 1 open at a time on mgmt device */
if (dgap_mgmt_in_use) {
DGAP_UNLOCK(dgap_global_lock, lock_flags);
return (-EBUSY);
}
dgap_mgmt_in_use++;
}
/* downld device */
else if (minor == MGMT_DOWNLD) {
/* Only allow 1 open at a time on downld device */
if (dgap_downld_in_use) {
DGAP_UNLOCK(dgap_global_lock, lock_flags);
return (-EBUSY);
}
dgap_downld_in_use++;
}
else {
DGAP_UNLOCK(dgap_global_lock, lock_flags);
return (-ENXIO);
}
DGAP_UNLOCK(dgap_global_lock, lock_flags);
DPR_MGMT(("dgap_mgmt_open finish.\n"));
return 0;
}
/*
* dgap_mgmt_close()
*
* Open the mgmt/dpa device
*/
int dgap_mgmt_close(struct inode *inode, struct file *file)
{
unsigned long lock_flags;
unsigned int minor = iminor(inode);
DPR_MGMT(("dgap_mgmt_close start.\n"));
DGAP_LOCK(dgap_global_lock, lock_flags);
/* mgmt device */
if (minor == MGMT_MGMT) {
if (dgap_mgmt_in_use) {
dgap_mgmt_in_use = 0;
}
}
/* downld device */
else if (minor == MGMT_DOWNLD) {
if (dgap_downld_in_use) {
dgap_downld_in_use = 0;
}
}
DGAP_UNLOCK(dgap_global_lock, lock_flags);
DPR_MGMT(("dgap_mgmt_close finish.\n"));
return 0;
}
/*
* dgap_mgmt_ioctl()
*
* ioctl the mgmt/dpa device
*/
#ifdef HAVE_UNLOCKED_IOCTL
long dgap_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file->f_dentry->d_inode;
#else
int dgap_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
#endif
unsigned long lock_flags;
int error = 0;
int i = 0;
int j = 0;
struct board_t *brd;
struct channel_t *ch;
static struct downldio dlio;
void __user *uarg = (void __user *) arg;
DPR_MGMT(("dgap_mgmt_ioctl start.\n"));
switch (cmd) {
/* HiJack the usage of SEDELAY to turn on/off debugging. */
case DIGI_SEDELAY:
{
unsigned int value = 0;
if (copy_from_user((unsigned int *) &value, uarg, sizeof(unsigned int))) {
return (-EFAULT);
}
printk("Setting debug of value: %x\n", value);
dgap_debug = value;
return 0;
}
case DIGI_DLREQ_GET:
{
get_service:
DGAP_LOCK(dgap_global_lock, lock_flags);
if (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD) {
dgap_driver_state = DRIVER_REQUESTED_CONFIG;
dlio.req_type = DLREQ_CONFIG;
dlio.bdid = 0;
dlio.image.fi.type = 0;
DGAP_UNLOCK(dgap_global_lock, lock_flags);
if (copy_to_user(uarg, &dlio, sizeof(struct downldio))) {
DGAP_LOCK(dgap_global_lock, lock_flags);
dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
DGAP_UNLOCK(dgap_global_lock, lock_flags);
return(-EFAULT);
}
return(0);
}
DGAP_UNLOCK(dgap_global_lock, lock_flags);
/*
* Loop thru each board.
* Check state, force state machine to start running.
*/
for (i = 0; i < dgap_NumBoards; i++ ) {
brd = dgap_Board[i];
DGAP_LOCK(brd->bd_lock, lock_flags);
switch (brd->state) {
case NEED_DEVICE_CREATION:
/*
* Let go of lock, tty_register() (and us also)
* does a non-atomic malloc, so it would be
* possible to deadlock the system if the
* malloc went to sleep.
*/
DGAP_UNLOCK(brd->bd_lock, lock_flags);
dgap_tty_register(brd);
dgap_finalize_board_init(brd);
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = REQUESTED_DEVICE_CREATION;
dlio.req_type = DLREQ_DEVCREATE;
dlio.bdid = i;
dlio.image.fi.type = brd->dpatype;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
if (copy_to_user(uarg, &dlio, sizeof(struct downldio))) {
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = NEED_DEVICE_CREATION;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
return(-EFAULT);
}
return(0);
case NEED_BIOS_LOAD:
brd->state = REQUESTED_BIOS;
dlio.req_type = DLREQ_BIOS;
dlio.bdid = i;
dlio.image.fi.type = brd->dpatype;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
if (copy_to_user(uarg, &dlio, sizeof(struct downldio))) {
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = NEED_BIOS_LOAD;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
return(-EFAULT);
}
return(0);
case NEED_FEP_LOAD:
brd->state = REQUESTED_FEP;
dlio.req_type = DLREQ_FEP;
dlio.bdid = i;
dlio.image.fi.type = brd->dpatype;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
if (copy_to_user(uarg, &dlio, sizeof(struct downldio))) {
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = NEED_FEP_LOAD;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
return(-EFAULT);
}
return(0);
case NEED_PROC_CREATION:
DGAP_UNLOCK(brd->bd_lock, lock_flags);
dgap_proc_register_channel_postscan(brd->boardnum);
ch = brd->channels[0];
for (j = 0; j < brd->nasync; j++, ch = brd->channels[j]) {
struct device *classp;
classp =
tty_register_device(brd->SerialDriver, j,
&(ch->ch_bd->pdev->dev));
ch->ch_tun.un_sysfs = classp;
dgap_create_tty_sysfs(&ch->ch_tun, classp);
classp =
tty_register_device(brd->PrintDriver, j,
&(ch->ch_bd->pdev->dev));
ch->ch_pun.un_sysfs = classp;
dgap_create_tty_sysfs(&ch->ch_pun, classp);
}
dgap_create_ports_sysfiles(brd);
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = FINISHED_PROC_CREATION;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
default:
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
DGAP_LOCK(brd->bd_lock, lock_flags);
switch (brd->conc_dl_status) {
case NEED_CONCENTRATOR:
{
u16 offset = 0;
char *vaddr;
struct downld_t *to_dp;
vaddr = brd->re_map_membase;
if (!vaddr) {
brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
dlio.req_type = DLREQ_CONC;
dlio.bdid = i;
offset = readw((u16 *) (vaddr + DOWNREQ));
to_dp = (struct downld_t *) (vaddr + (int) offset);
if (!to_dp) {
brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
memcpy(&dlio.image.dl, to_dp, sizeof(struct downld_t));
brd->conc_dl_status = REQUESTED_CONCENTRATOR;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
if (copy_to_user(uarg, &dlio, sizeof(struct downldio))) {
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->conc_dl_status = NEED_CONCENTRATOR;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
return(-EFAULT);
}
return(0);
}
default:
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
}
/*
* Go to sleep waiting for the driver to signal an event to us.
*/
error = wait_event_interruptible(dgap_dl_wait, (dgap_dl_action));
DGAP_LOCK(dgap_dl_lock, lock_flags);
dgap_dl_action = 0;
DGAP_UNLOCK(dgap_dl_lock, lock_flags);
/* Break out of ioctl if user cancelled us */
if (error)
break;
goto get_service;
}
case DIGI_DLREQ_SET:
{
uchar __user *uaddr = NULL;
uchar *uaddr2 = NULL;
if (copy_from_user((char *) &dlio, uarg, sizeof(struct downldio))) {
return (-EFAULT);
}
if (dlio.req_type == DLREQ_CONFIG) {
uaddr = uarg +
(int) ( ((struct downldio *)0)->image.fi.fepimage);
dgap_do_config_load(uaddr, dlio.image.fi.len);
dgap_after_config_loaded();
DGAP_LOCK(dgap_global_lock, lock_flags);
dgap_driver_state = DRIVER_READY;
DGAP_UNLOCK(dgap_global_lock, lock_flags);
break;
}
if (dlio.bdid < 0 || dlio.bdid > dgap_NumBoards) {
return(-ENXIO);
}
brd = dgap_Board[dlio.bdid];
switch(dlio.req_type) {
case DLREQ_BIOS:
if (brd->state == BOARD_FAILED || brd->state == BOARD_READY) {
break;
}
if (dlio.image.fi.type == -1) {
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = BOARD_FAILED;
brd->dpastatus = BD_NOBIOS;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
uaddr = uarg +
(int) ( ((struct downldio *)0)->image.fi.fepimage);
dgap_do_bios_load(brd, uaddr, dlio.image.fi.len);
break;
case DLREQ_FEP:
if (brd->state == BOARD_FAILED || brd->state == BOARD_READY) {
break;
}
if (dlio.image.fi.type == -1) {
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = BOARD_FAILED;
brd->dpastatus = BD_NOBIOS;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
uaddr = uarg +
(int) ( ((struct downldio *)0)->image.fi.fepimage);
dgap_do_fep_load(brd, uaddr, dlio.image.fi.len);
break;
case DLREQ_CONC:
if (brd->state == BOARD_FAILED) {
break;
}
if (dlio.image.fi.type == -1) {
break;
}
uaddr2 = (char *) &dlio.image.dl;
dgap_do_conc_load(brd, uaddr2, sizeof(struct downld_t));
break;
case DLREQ_DEVCREATE:
if (brd->state == BOARD_FAILED || brd->state == BOARD_READY) {
break;
}
DGAP_LOCK(brd->bd_lock, lock_flags);
brd->state = FINISHED_DEVICE_CREATION;
DGAP_UNLOCK(brd->bd_lock, lock_flags);
break;
}
break;
}
case DIGI_GETDD:
{
/*
* This returns the total number of boards
* in the system, as well as driver version
* and has space for a reserved entry
*/
struct digi_dinfo ddi;
DGAP_LOCK(dgap_global_lock, lock_flags);
ddi.dinfo_nboards = dgap_NumBoards;
sprintf(ddi.dinfo_version, "%s", DG_PART);
DGAP_UNLOCK(dgap_global_lock, lock_flags);
DPR_MGMT(("DIGI_GETDD returning numboards: %lu version: %s\n",
ddi.dinfo_nboards, ddi.dinfo_version));
if (copy_to_user(uarg, &ddi, sizeof(ddi)))
return(-EFAULT);
break;
}
case DIGI_GETBD:
{
int brd2;
struct digi_info di;
if (copy_from_user(&brd2, uarg, sizeof(int))) {
return(-EFAULT);
}
DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd2));
if ((brd2 < 0) || (brd2 > dgap_NumBoards) || (dgap_NumBoards == 0))
return (-ENODEV);
memset(&di, 0, sizeof(di));
di.info_bdnum = brd2;
DGAP_LOCK(dgap_Board[brd2]->bd_lock, lock_flags);
di.info_bdtype = dgap_Board[brd2]->dpatype;
di.info_bdstate = dgap_Board[brd2]->dpastatus;
di.info_ioport = (ulong) dgap_Board[brd2]->port;
di.info_physaddr = (ulong) dgap_Board[brd2]->membase;
di.info_physsize = (ulong) dgap_Board[brd2]->membase - dgap_Board[brd2]->membase_end;
if (dgap_Board[brd2]->state != BOARD_FAILED)
di.info_nports = dgap_Board[brd2]->nasync;
else
di.info_nports = 0;
DGAP_UNLOCK(dgap_Board[brd2]->bd_lock, lock_flags);
DPR_MGMT(("DIGI_GETBD returning type: %x state: %x ports: %x size: %lx\n",
di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize));
if (copy_to_user(uarg, &di, sizeof (di)))
return(-EFAULT);
break;
}
case DIGI_KME:
{
int itmp, jtmp;
unchar *memaddr = NULL;
struct rw_t kme;
struct rw_t *mp = NULL;
int brd2 = 0;
struct board_t *bd;
/* This ioctl takes an argument of type 'rw_t'
* and uses it to interact with the KME struct
* located on the digiboard itself.
*/
if (copy_from_user(&kme, uarg, sizeof(kme)))
return(-EFAULT);
if (kme.rw_size > 128)
kme.rw_size = 128;
brd2 = kme.rw_board;
DPR_MGMT(("dgap_mgmt: DIGI_KME: %s asked for board %d\n", current->comm, brd2));
/* Sanity Checking... */
if ((brd2 < 0) || (brd2 > dgap_NumBoards) || (dgap_NumBoards == 0))
return (-ENODEV);
bd = dgap_Board[brd2];
DGAP_LOCK(dgap_Board[brd2]->bd_lock, lock_flags);
if (bd->state != BOARD_READY) {
DGAP_UNLOCK(dgap_Board[brd2]->bd_lock, lock_flags);
return(-ENODEV);
}
memaddr = bd->re_map_membase;
DGAP_UNLOCK(dgap_Board[brd2]->bd_lock, lock_flags);
/* If the concentrator number is 0... */
if (kme.rw_conc == 0 && kme.rw_addr < 0x100000) {
int page = 0;
int addr = kme.rw_addr;
int size = kme.rw_size;
caddr_t data = (caddr_t) kme.rw_data;
while ((itmp = size)) {
switch (kme.rw_req) {
case RW_READ:
{
register caddr_t cp1 = (char *)memaddr + addr;
register caddr_t cp2 = kme.rw_data;
DPR_MGMT(("RW_READ CARDMEM - page=%d rw_addr=0x%lx rw_size=%x\n",
page, kme.rw_addr, kme.rw_size));
for (jtmp = 0; jtmp < itmp; jtmp++) {
*cp2++ = readb(cp1++);
}
}
break;
case RW_WRITE:
{
register caddr_t cp1 = memaddr + addr;
register caddr_t cp2 = data;
DPR_MGMT(("RW_WRITE CARDMEM - page=%d rw_addr=0x%lx rw_size=%d\n",
page, kme.rw_addr, kme.rw_size));
for (jtmp = 0; jtmp < itmp; jtmp++) {
writeb(*cp2++, cp1++);
}
}
break;
}
addr += itmp;
data += itmp;
size -= itmp;
}
}
else {
/*
* Read/Write memory in a REMOTE CONCENTRATOR..
* There is only 1 buffer, so do mutual
* exclusion to make sure only one KME
* request is pending...
*/
mp = (struct rw_t *) (memaddr + KMEMEM);
while (dgap_kmebusy != 0) {
dgap_kmebusy = 2;
error = wait_event_interruptible(bd->kme_wait, (!dgap_kmebusy));
if (error)
goto endkme;
}
dgap_kmebusy = 1;
/* Copy KME request to the board.. */
mp->rw_board = kme.rw_board;
mp->rw_conc = kme.rw_conc;
mp->rw_reserved = kme.rw_reserved;
memcpy(&mp->rw_addr, &kme.rw_addr, sizeof(int));
memcpy(&mp->rw_size, &kme.rw_size, sizeof(short));
if(kme.rw_req == RW_WRITE) {
register caddr_t cp1 = (caddr_t) mp->rw_data;
register caddr_t cp2 = (caddr_t) kme.rw_data;
DPR_MGMT(("RW_WRITE CONCMEM - rw_addr=0x%lx rw_size=%d\n",
kme.rw_addr, kme.rw_size));
for (jtmp = 0; jtmp < (int) kme.rw_size; jtmp++) {
writeb(*cp2++, cp1++);
}
}
/* EXECUTE REQUEST */
mp->rw_req = kme.rw_req;
/*
* Wait for the board to process the
* request, but limit the wait to 2 secs
*/
for (itmp = jiffies + (2 * HZ); mp->rw_req;) {
if(jiffies >= itmp) {
error = ENXIO;
/* Set request back to 0.. */
mp->rw_req = 0;
goto endkme;
}
schedule_timeout(HZ / 10);
}
/*
* Since this portion of code is looksee
* ported from the HPUX EMUX code, i'm
* leaving OUT a portion of that code where
* the HP/UX code actually puts the process
* to sleep for some reason
*/
if (mp->rw_size < kme.rw_size)
memcpy(&kme.rw_size, &mp->rw_size, sizeof(short));
/* Copy the READ data back to the source buffer... */
if (kme.rw_req == RW_READ) {
register caddr_t cp1 = (caddr_t) mp->rw_data;
register caddr_t cp2 = (caddr_t) kme.rw_data;
DPR_MGMT(("RW_READ CONCMEM - rw_addr=0x%lx rw_size=%d\n",
kme.rw_addr, kme.rw_size));
for (jtmp = 0; jtmp < (int) kme.rw_size; jtmp++) {
*cp2++ = readb(cp1++);
}
}
/*
* Common exit point for code sharing the
* kme buffer. Before exiting, always wake
* another process waiting for the buffer
*/
endkme:
if (dgap_kmebusy != 1)
wake_up_interruptible(&bd->kme_wait);
dgap_kmebusy = 0;
if (error == ENXIO)
return(-EINVAL);
}
/* Copy the whole (Possibly Modified) mess */
/* back out to user space... */
if (!error) {
if (copy_to_user(uarg, &kme, sizeof(kme)))
return (-EFAULT);
return(0);
}
}
}
DPR_MGMT(("dgap_mgmt_ioctl finish.\n"));
return 0;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef __DGAP_MGMT_H
#define __DGAP_MGMT_H
#define MGMT_MGMT 0
#define MGMT_DOWNLD 1
int dgap_mgmt_open(struct inode *inode, struct file *file);
int dgap_mgmt_close(struct inode *inode, struct file *file);
#ifdef HAVE_UNLOCKED_IOCTL
long dgap_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
#else
int dgap_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef _DGAP_PARSE_H
#define _DGAP_PARSE_H
#include "dgap_driver.h"
extern int dgap_parsefile(char **in, int Remove);
extern struct cnode *dgap_find_config(int type, int bus, int slot);
extern uint dgap_config_get_number_of_ports(struct board_t *bd);
extern char *dgap_create_config_string(struct board_t *bd, char *string);
extern char *dgap_get_config_letters(struct board_t *bd, char *string);
extern uint dgap_config_get_useintr(struct board_t *bd);
extern uint dgap_config_get_altpin(struct board_t *bd);
#endif

View File

@ -0,0 +1,92 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
/* $Id: dgap_pci.h,v 1.1 2009/10/23 14:01:57 markh Exp $ */
#ifndef __DGAP_PCI_H
#define __DGAP_PCI_H
#define PCIMAX 32 /* maximum number of PCI boards */
#define DIGI_VID 0x114F
#define PCI_DEVICE_EPC_DID 0x0002
#define PCI_DEVICE_XEM_DID 0x0004
#define PCI_DEVICE_XR_DID 0x0005
#define PCI_DEVICE_CX_DID 0x0006
#define PCI_DEVICE_XRJ_DID 0x0009 /* PLX-based Xr adapter */
#define PCI_DEVICE_XR_IBM_DID 0x0011 /* IBM 8-port Async Adapter */
#define PCI_DEVICE_XR_BULL_DID 0x0013 /* BULL 8-port Async Adapter */
#define PCI_DEVICE_XR_SAIP_DID 0x001c /* SAIP card - Xr adapter */
#define PCI_DEVICE_XR_422_DID 0x0012 /* Xr-422 */
#define PCI_DEVICE_920_2_DID 0x0034 /* XR-Plus 920 K, 2 port */
#define PCI_DEVICE_920_4_DID 0x0026 /* XR-Plus 920 K, 4 port */
#define PCI_DEVICE_920_8_DID 0x0027 /* XR-Plus 920 K, 8 port */
#define PCI_DEVICE_EPCJ_DID 0x000a /* PLX 9060 chip for PCI */
#define PCI_DEVICE_CX_IBM_DID 0x001b /* IBM 128-port Async Adapter */
#define PCI_DEVICE_920_8_HP_DID 0x0058 /* HP XR-Plus 920 K, 8 port */
#define PCI_DEVICE_XEM_HP_DID 0x0059 /* HP Xem PCI */
#define PCI_DEVICE_XEM_NAME "AccelePort XEM"
#define PCI_DEVICE_CX_NAME "AccelePort CX"
#define PCI_DEVICE_XR_NAME "AccelePort Xr"
#define PCI_DEVICE_XRJ_NAME "AccelePort Xr (PLX)"
#define PCI_DEVICE_XR_SAIP_NAME "AccelePort Xr (SAIP)"
#define PCI_DEVICE_920_2_NAME "AccelePort Xr920 2 port"
#define PCI_DEVICE_920_4_NAME "AccelePort Xr920 4 port"
#define PCI_DEVICE_920_8_NAME "AccelePort Xr920 8 port"
#define PCI_DEVICE_XR_422_NAME "AccelePort Xr 422"
#define PCI_DEVICE_EPCJ_NAME "AccelePort EPC (PLX)"
#define PCI_DEVICE_XR_BULL_NAME "AccelePort Xr (BULL)"
#define PCI_DEVICE_XR_IBM_NAME "AccelePort Xr (IBM)"
#define PCI_DEVICE_CX_IBM_NAME "AccelePort CX (IBM)"
#define PCI_DEVICE_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
#define PCI_DEVICE_XEM_HP_NAME "AccelePort XEM (HP)"
/*
* On the PCI boards, there is no IO space allocated
* The I/O registers will be in the first 3 bytes of the
* upper 2MB of the 4MB memory space. The board memory
* will be mapped into the low 2MB of the 4MB memory space
*/
/* Potential location of PCI Bios from E0000 to FFFFF*/
#define PCI_BIOS_SIZE 0x00020000
/* Size of Memory and I/O for PCI (4MB) */
#define PCI_RAM_SIZE 0x00400000
/* Size of Memory (2MB) */
#define PCI_MEM_SIZE 0x00200000
/* Max PCI Window Size (2MB) */
#define PCI_WIN_SIZE 0x00200000
#define PCI_WIN_SHIFT 21 /* 21 bits max */
/* Offset of I/0 in Memory (2MB) */
#define PCI_IO_OFFSET 0x00200000
/* Size of IO (2MB) */
#define PCI_IO_SIZE 0x00200000
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*
*
* $Id: dgap_proc.h,v 1.1 2009/10/23 14:01:57 markh Exp $
*
* Description:
*
* Describes the private structures used to manipulate the "special"
* proc constructs (not read-only) used by the Digi Neo software.
* The concept is borrowed heavily from the "sysctl" interface of
* the kernel. I decided not to use the structures and functions
* provided by the kernel for two reasons:
*
* 1. Due to the planned use of "/proc" in the Neo driver, many
* of the functions of the "sysctl" interface would go unused.
* A simpler interface will be easier to maintain.
*
* 2. I'd rather divorce our "added package" from the kernel internals.
* If the "sysctl" structures should change, I will be insulated
* from those changes. These "/proc" entries won't be under the
* "sys" tree anyway, so there is no need to maintain a strict
* dependence relationship.
*
* Author:
*
* Scott H Kilau
*
*/
#ifndef _DGAP_RW_PROC_H
#define _DGAP_RW_PROC_H
/*
* The list of DGAP entries with r/w capabilities.
* These magic numbers are used for identification purposes.
*/
enum {
DGAP_INFO = 1, /* Get info about the running module */
DGAP_MKNOD = 2, /* Get info about driver devices */
DGAP_BOARD_INFO = 3, /* Get info about the specific board */
DGAP_BOARD_VPD = 4, /* Get info about the board's VPD */
DGAP_BOARD_VPDDATA = 5, /* Get info about the board's VPD */
DGAP_BOARD_TTYSTATS = 6, /* Get info about the board's tty stats */
DGAP_BOARD_TTYFLAGS = 7, /* Get info about the board's tty flags */
DGAP_BOARD_MKNOD = 8, /* Get info about board devices */
DGAP_PORT_INFO = 9, /* Get info about the specific port */
DGAP_PORT_SNIFF = 10, /* Sniff data in/out of specific port */
DGAP_PORT_CUSTOM_TTYNAME = 11, /* Get info about UDEV tty name */
DGAP_PORT_CUSTOM_PRNAME = 12, /* Get info about UDEV pr name */
DGAP_PORT_FEPSTATE = 13, /* Get info about Ports FEP state */
};
#define DGAP_MAX_PROC_ENTRIES 999
/*
* Directions for proc handlers
*/
enum {
INBOUND = 1, /* Data being written to kernel */
OUTBOUND = 2, /* Data being read from the kernel */
};
/*
* Each entry in a DGAP proc directory is described with a
* "dgap_proc_entry" structure. A collection of these
* entries (in an array) represents the members associated
* with a particular "/proc" directory, and is referred to
* as a table. All "tables" are terminated by an entry with
* zeros for every member.
*
* The structure members are as follows:
*
* int magic -- ID number associated with this particular
* entry. Should be unique across all of
* DGAP.
*
* const char *name -- ASCII name associated with the /proc entry.
*
* mode_t mode -- File access permisssions for the /proc entry.
*
* dgap_proc_entry *child -- When set, this entry refers to a directory,
* and points to the table which describes the
* entries in the subdirectory
*
* dgap_proc_handler *open_handler -- When set, points to the fxn which
* does any "extra" open stuff.
*
* dgap_proc_handler *close_handler -- When set, points to the fxn which
* does any "extra" close stuff.
*
* dgap_proc_handler *read_handler -- When set, points to the fxn which
* handle outbound data flow
*
* dgap_proc_handler *write_handler -- When set, points to the fxn which
* handles inbound data flow
*
* struct proc_dir_entry *de -- Pointer to the directory entry for this
* object once registered. Used to grab
* the handle of the object for
* unregistration
*
* void *data; When set, points to the parent structure
*
*/
struct dgap_proc_entry {
int magic; /* Integer identifier */
const char *name; /* ASCII identifier */
mode_t mode; /* File access permissions */
struct dgap_proc_entry *child; /* Child pointer */
int (*open_handler) (struct dgap_proc_entry *table, int dir, struct file *filp,
void *buffer, ssize_t *lenp, loff_t *ppos);
int (*close_handler) (struct dgap_proc_entry *table, int dir, struct file *filp,
void *buffer, ssize_t *lenp, loff_t *ppos);
int (*read_handler) (struct dgap_proc_entry *table, int dir, struct file *filp,
char __user *buffer, ssize_t *lenp, loff_t *ppos);
int (*write_handler) (struct dgap_proc_entry *table, int dir, struct file *filp,
const char __user *buffer, ssize_t *lenp, loff_t *ppos);
struct proc_dir_entry *de; /* proc entry pointer */
struct semaphore excl_sem; /* Protects exclusive access var */
int excl_cnt; /* Counts number of curr accesses */
void *data; /* Allows storing a pointer to parent */
};
void dgap_proc_register_basic_prescan(void);
void dgap_proc_unregister_all(void);
void dgap_proc_register_basic_postscan(int board_num);
void dgap_proc_register_channel_postscan(int board_num);
#endif /* _DGAP_RW_PROC_H */

View File

@ -0,0 +1,796 @@
/*
* Copyright 2004 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
*
* This is shared code between Digi's CVS archive and the
* Linux Kernel sources.
* Changing the source just for reformatting needlessly breaks
* our CVS diff history.
*
* Send any bug fixes/changes to: Eng.Linux at digi dot com.
* Thank you.
*
*
*
* $Id: dgap_sysfs.c,v 1.1 2009/10/23 14:01:57 markh Exp $
*/
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/serial_reg.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/kdev_t.h>
#include "dgap_driver.h"
#include "dgap_proc.h"
#include "dgap_mgmt.h"
#include "dgap_conf.h"
#include "dgap_parse.h"
static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
}
static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
}
static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
}
static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
}
static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
}
static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
static ssize_t dgap_driver_debug_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_debug);
}
static ssize_t dgap_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
{
sscanf(buf, "0x%x\n", &dgap_debug);
return count;
}
static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgap_driver_debug_show, dgap_driver_debug_store);
static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
}
static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
{
sscanf(buf, "0x%x\n", &dgap_rawreadok);
return count;
}
static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
}
static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
{
sscanf(buf, "%d\n", &dgap_poll_tick);
return count;
}
static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
{
int rc = 0;
struct device_driver *driverfs = &dgap_driver->driver;
rc |= driver_create_file(driverfs, &driver_attr_version);
rc |= driver_create_file(driverfs, &driver_attr_boards);
rc |= driver_create_file(driverfs, &driver_attr_maxboards);
rc |= driver_create_file(driverfs, &driver_attr_debug);
rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
rc |= driver_create_file(driverfs, &driver_attr_pollrate);
rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
rc |= driver_create_file(driverfs, &driver_attr_state);
if (rc) {
printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
}
}
void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
{
struct device_driver *driverfs = &dgap_driver->driver;
driver_remove_file(driverfs, &driver_attr_version);
driver_remove_file(driverfs, &driver_attr_boards);
driver_remove_file(driverfs, &driver_attr_maxboards);
driver_remove_file(driverfs, &driver_attr_debug);
driver_remove_file(driverfs, &driver_attr_rawreadok);
driver_remove_file(driverfs, &driver_attr_pollrate);
driver_remove_file(driverfs, &driver_attr_pollcounter);
driver_remove_file(driverfs, &driver_attr_state);
}
#define DGAP_VERIFY_BOARD(p, bd) \
if (!p) \
return (0); \
\
bd = dev_get_drvdata(p); \
if (!bd || bd->magic != DGAP_BOARD_MAGIC) \
return (0); \
if (bd->state != BOARD_READY) \
return (0); \
static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count,
"%d %s\n", bd->channels[i]->ch_portnum,
bd->channels[i]->ch_open_count ? "Open" : "Closed");
}
return count;
}
static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count,
"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
}
return count;
}
static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
if (bd->channels[i]->ch_open_count) {
count += snprintf(buf + count, PAGE_SIZE - count,
"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
(bd->channels[i]->ch_mistat & UART_MSR_RI) ? "RI" : "");
} else {
count += snprintf(buf + count, PAGE_SIZE - count,
"%d\n", bd->channels[i]->ch_portnum);
}
}
return count;
}
static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
}
return count;
}
static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
}
return count;
}
static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
}
return count;
}
static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
}
return count;
}
static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
}
return count;
}
static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
}
return count;
}
static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
int count = 0;
int i = 0;
DGAP_VERIFY_BOARD(p, bd);
for (i = 0; i < bd->nasync; i++) {
count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
}
return count;
}
static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
/* this function creates the sys files that will export each signal status
* to sysfs each value will be put in a separate filename
*/
void dgap_create_ports_sysfiles(struct board_t *bd)
{
int rc = 0;
dev_set_drvdata(&bd->pdev->dev, bd);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
if (rc) {
printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
}
}
/* removes all the sys files created for that port */
void dgap_remove_ports_sysfiles(struct board_t *bd)
{
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
}
static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
}
static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
}
static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
if (ch->ch_open_count) {
return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
(ch->ch_mistat & UART_MSR_RI) ? "RI" : "");
}
return 0;
}
static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
}
static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
}
static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
}
static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
}
static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
}
static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
}
static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
}
static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
{
struct board_t *bd;
struct channel_t *ch;
struct un_t *un;
int cn;
int bn;
struct cnode *cptr = NULL;
int found = FALSE;
int ncount = 0;
int starto = 0;
int i = 0;
if (!d)
return (0);
un = (struct un_t *) dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
return (0);
bd = ch->ch_bd;
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
return (0);
if (bd->state != BOARD_READY)
return (0);
bn = bd->boardnum;
cn = ch->ch_portnum;
for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
if ((cptr->type == BNODE) &&
((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
(cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
(cptr->u.board.type == PAPORT8))) {
found = TRUE;
if (cptr->u.board.v_start)
starto = cptr->u.board.start;
else
starto = 1;
}
if (cptr->type == TNODE && found == TRUE) {
char *ptr1;
if (strstr(cptr->u.ttyname, "tty")) {
ptr1 = cptr->u.ttyname;
ptr1 += 3;
}
else {
ptr1 = cptr->u.ttyname;
}
for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
if (cn == i) {
return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
(un->un_type == DGAP_PRINT) ? "pr" : "tty",
ptr1, i + starto);
}
}
}
if (cptr->type == CNODE) {
for (i = 0; i < cptr->u.conc.nport; i++) {
if (cn == (i + ncount)) {
return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
(un->un_type == DGAP_PRINT) ? "pr" : "tty",
cptr->u.conc.id,
i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
}
}
ncount += cptr->u.conc.nport;
}
if (cptr->type == MNODE) {
for (i = 0; i < cptr->u.module.nport; i++) {
if (cn == (i + ncount)) {
return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
(un->un_type == DGAP_PRINT) ? "pr" : "tty",
cptr->u.module.id,
i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
}
}
ncount += cptr->u.module.nport;
}
}
return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
(un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
}
static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
static struct attribute *dgap_sysfs_tty_entries[] = {
&dev_attr_state.attr,
&dev_attr_baud.attr,
&dev_attr_msignals.attr,
&dev_attr_iflag.attr,
&dev_attr_cflag.attr,
&dev_attr_oflag.attr,
&dev_attr_lflag.attr,
&dev_attr_digi_flag.attr,
&dev_attr_rxcount.attr,
&dev_attr_txcount.attr,
&dev_attr_custom_name.attr,
NULL
};
static struct attribute_group dgap_tty_attribute_group = {
.name = NULL,
.attrs = dgap_sysfs_tty_entries,
};
void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
{
int ret;
ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
if (ret) {
printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
return;
}
dev_set_drvdata(c, un);
}
void dgap_remove_tty_sysfs(struct device *c)
{
sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef __DGAP_SYSFS_H
#define __DGAP_SYSFS_H
#include "dgap_driver.h"
#include <linux/device.h>
struct board_t;
struct channel_t;
struct un_t;
struct pci_driver;
struct class_device;
extern void dgap_create_ports_sysfiles(struct board_t *bd);
extern void dgap_remove_ports_sysfiles(struct board_t *bd);
extern void dgap_create_driver_sysfiles(struct pci_driver *);
extern void dgap_remove_driver_sysfiles(struct pci_driver *);
extern int dgap_tty_class_init(void);
extern int dgap_tty_class_destroy(void);
extern void dgap_create_tty_sysfs(struct un_t *un, struct device *c);
extern void dgap_remove_tty_sysfs(struct device *c);
#endif

View File

@ -0,0 +1,186 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
*
* This is shared code between Digi's CVS archive and the
* Linux Kernel sources.
* Changing the source just for reformatting needlessly breaks
* our CVS diff history.
*
* Send any bug fixes/changes to: Eng.Linux at digi dot com.
* Thank you.
*
*/
/* $Id: dgap_trace.c,v 1.1 2009/10/23 14:01:57 markh Exp $ */
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/sched.h> /* For jiffies, task states */
#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
#include <linux/vmalloc.h>
#include "dgap_driver.h"
#define TRC_TO_CONSOLE 1
/* file level globals */
static char *dgap_trcbuf; /* the ringbuffer */
#if defined(TRC_TO_KMEM)
static int dgap_trcbufi = 0; /* index of the tilde at the end of */
#endif
extern int dgap_trcbuf_size; /* size of the ringbuffer */
#if defined(TRC_TO_KMEM)
static DEFINE_SPINLOCK(dgap_tracef_lock);
#endif
#if 0
#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
void dgap_tracef(const char *fmt, ...)
{
return;
}
#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
void dgap_tracef(const char *fmt, ...)
{
va_list ap;
char buf[TRC_MAXMSG+1];
size_t lenbuf;
int i;
static int failed = FALSE;
# if defined(TRC_TO_KMEM)
unsigned long flags;
#endif
if(failed)
return;
# if defined(TRC_TO_KMEM)
DGAP_LOCK(dgap_tracef_lock, flags);
#endif
/* Format buf using fmt and arguments contained in ap. */
va_start(ap, fmt);
i = vsprintf(buf, fmt, ap);
va_end(ap);
lenbuf = strlen(buf);
# if defined(TRC_TO_KMEM)
{
static int initd=0;
/*
* Now, in addition to (or instead of) printing this stuff out
* (which is a buffered operation), also tuck it away into a
* corner of memory which can be examined post-crash in kdb.
*/
if (!initd) {
dgap_trcbuf = (char *) vmalloc(dgap_trcbuf_size);
if(!dgap_trcbuf) {
failed = TRUE;
printk("dgap: tracing init failed!\n");
return;
}
memset(dgap_trcbuf, '\0', dgap_trcbuf_size);
dgap_trcbufi = 0;
initd++;
printk("dgap: tracing enabled - " TRC_DTRC
" 0x%lx 0x%x\n",
(unsigned long)dgap_trcbuf,
dgap_trcbuf_size);
}
# if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
/*
* This is the less CPU-intensive way to do things. We simply
* wrap around before we fall off the end of the buffer. A
* tilde (~) demarcates the current end of the trace.
*
* This method should be used if you are concerned about race
* conditions as it is less likely to affect the timing of
* things.
*/
if (dgap_trcbufi + lenbuf >= dgap_trcbuf_size) {
/* We are wrapping, so wipe out the last tilde. */
dgap_trcbuf[dgap_trcbufi] = '\0';
/* put the new string at the beginning of the buffer */
dgap_trcbufi = 0;
}
strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
dgap_trcbufi += lenbuf;
dgap_trcbuf[dgap_trcbufi] = '~';
# elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
/*
* This is the more CPU-intensive way to do things. If we
* venture into the last 1/8 of the buffer, we shift the
* last 7/8 of the buffer forward, wiping out the first 1/8.
* Advantage: No wrap-around, only truncation from the
* beginning.
*
* This method should not be used if you are concerned about
* timing changes affecting the behaviour of the driver (ie,
* race conditions).
*/
strcpy(&dgap_trcbuf[dgap_trcbufi], buf);
dgap_trcbufi += lenbuf;
dgap_trcbuf[dgap_trcbufi] = '~';
dgap_trcbuf[dgap_trcbufi+1] = '\0';
/* If we're near the end of the trace buffer... */
if (dgap_trcbufi > (dgap_trcbuf_size/8)*7) {
/* Wipe out the first eighth to make some more room. */
strcpy(dgap_trcbuf, &dgap_trcbuf[dgap_trcbuf_size/8]);
dgap_trcbufi = strlen(dgap_trcbuf)-1;
/* Plop overflow message at the top of the buffer. */
bcopy(TRC_OVERFLOW, dgap_trcbuf, strlen(TRC_OVERFLOW));
}
# else
# error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
# endif
}
DGAP_UNLOCK(dgap_tracef_lock, flags);
# endif /* defined(TRC_TO_KMEM) */
}
#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
#endif
/*
* dgap_tracer_free()
*
*
*/
void dgap_tracer_free(void)
{
if(dgap_trcbuf)
vfree(dgap_trcbuf);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*
*****************************************************************************
* Header file for dgap_trace.c
*
* $Id: dgap_trace.h,v 1.1 2009/10/23 14:01:57 markh Exp $
*/
#ifndef __DGAP_TRACE_H
#define __DGAP_TRACE_H
#include "dgap_driver.h"
void dgap_tracef(const char *fmt, ...);
void dgap_tracer_free(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef __DGAP_TTY_H
#define __DGAP_TTY_H
#include "dgap_driver.h"
int dgap_tty_register(struct board_t *brd);
int dgap_tty_preinit(void);
int dgap_tty_init(struct board_t *);
void dgap_tty_post_uninit(void);
void dgap_tty_uninit(struct board_t *);
void dgap_carrier(struct channel_t *ch);
void dgap_input(struct channel_t *ch);
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef __DGAP_TYPES_H
#define __DGAP_TYPES_H
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
/* Required for our shared headers! */
typedef unsigned char uchar;
#endif

376
drivers/staging/dgap/digi.h Normal file
View File

@ -0,0 +1,376 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: digi.h,v 1.1 2009/10/23 14:01:57 markh Exp $
*
* NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
*/
#ifndef __DIGI_H
#define __DIGI_H
/************************************************************************
*** Definitions for Digi ditty(1) command.
************************************************************************/
/*
* Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
*/
/************************************************************************
* This module provides application access to special Digi
* serial line enhancements which are not standard UNIX(tm) features.
************************************************************************/
#if !defined(TIOCMODG)
#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */
#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */
#ifndef TIOCM_LE
#define TIOCM_LE 0x01 /* line enable */
#define TIOCM_DTR 0x02 /* data terminal ready */
#define TIOCM_RTS 0x04 /* request to send */
#define TIOCM_ST 0x08 /* secondary transmit */
#define TIOCM_SR 0x10 /* secondary receive */
#define TIOCM_CTS 0x20 /* clear to send */
#define TIOCM_CAR 0x40 /* carrier detect */
#define TIOCM_RNG 0x80 /* ring indicator */
#define TIOCM_DSR 0x100 /* data set ready */
#define TIOCM_RI TIOCM_RNG /* ring (alternate) */
#define TIOCM_CD TIOCM_CAR /* carrier detect (alt) */
#endif
#endif
#if !defined(TIOCMSET)
#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */
#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */
#endif
#if !defined(TIOCMBIC)
#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */
#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */
#endif
#if !defined(TIOCSDTR)
#define TIOCSDTR ('e'<<8) | 0 /* set DTR */
#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */
#endif
/************************************************************************
* Ioctl command arguments for DIGI parameters.
************************************************************************/
#define DIGI_GETA ('e'<<8) | 94 /* Read params */
#define DIGI_SETA ('e'<<8) | 95 /* Set params */
#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */
#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */
#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */
/* Adapter Memory */
#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */
/* control characters */
#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */
/* control characters */
#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */
/* flow control chars */
#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */
/* flow control chars */
#define DIGI_GEDELAY ('d'<<8) | 246 /* Get edelay */
#define DIGI_SEDELAY ('d'<<8) | 247 /* Set edelay */
struct digiflow_t {
unsigned char startc; /* flow cntl start char */
unsigned char stopc; /* flow cntl stop char */
};
#ifdef FLOW_2200
#define F2200_GETA ('e'<<8) | 104 /* Get 2x36 flow cntl flags */
#define F2200_SETAW ('e'<<8) | 105 /* Set 2x36 flow cntl flags */
#define F2200_MASK 0x03 /* 2200 flow cntl bit mask */
#define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */
#define PCNTL_2200 0x02 /* 2x36 printer flow cntl */
#define F2200_XON 0xf8
#define P2200_XON 0xf9
#define F2200_XOFF 0xfa
#define P2200_XOFF 0xfb
#define FXOFF_MASK 0x03 /* 2200 flow status mask */
#define RCVD_FXOFF 0x01 /* 2x36 Terminal XOFF rcvd */
#define RCVD_PXOFF 0x02 /* 2x36 Printer XOFF rcvd */
#endif
/************************************************************************
* Values for digi_flags
************************************************************************/
#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */
#define DIGI_FAST 0x0002 /* Fast baud rates */
#define RTSPACE 0x0004 /* RTS input flow control */
#define CTSPACE 0x0008 /* CTS output flow control */
#define DSRPACE 0x0010 /* DSR output flow control */
#define DCDPACE 0x0020 /* DCD output flow control */
#define DTRPACE 0x0040 /* DTR input flow control */
#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */
#define DIGI_FORCEDCD 0x0100 /* Force carrier */
#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */
#define DIGI_AIXON 0x0400 /* Aux flow control in fep */
#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl*/
#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input*/
#define DIGI_DTR_TOGGLE 0x2000 /* Support DTR Toggle */
#define DIGI_422 0x4000 /* for 422/232 selectable panel */
#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */
/************************************************************************
* These options are not supported on the comxi.
************************************************************************/
#define DIGI_COMXI (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
#define DIGI_PLEN 28 /* String length */
#define DIGI_TSIZ 10 /* Terminal string len */
/************************************************************************
* Structure used with ioctl commands for DIGI parameters.
************************************************************************/
struct digi_t {
unsigned short digi_flags; /* Flags (see above) */
unsigned short digi_maxcps; /* Max printer CPS */
unsigned short digi_maxchar; /* Max chars in print queue */
unsigned short digi_bufsize; /* Buffer size */
unsigned char digi_onlen; /* Length of ON string */
unsigned char digi_offlen; /* Length of OFF string */
char digi_onstr[DIGI_PLEN]; /* Printer on string */
char digi_offstr[DIGI_PLEN]; /* Printer off string */
char digi_term[DIGI_TSIZ]; /* terminal string */
};
/************************************************************************
* KME definitions and structures.
************************************************************************/
#define RW_IDLE 0 /* Operation complete */
#define RW_READ 1 /* Read Concentrator Memory */
#define RW_WRITE 2 /* Write Concentrator Memory */
struct rw_t {
unsigned char rw_req; /* Request type */
unsigned char rw_board; /* Host Adapter board number */
unsigned char rw_conc; /* Concentrator number */
unsigned char rw_reserved; /* Reserved for expansion */
unsigned long rw_addr; /* Address in concentrator */
unsigned short rw_size; /* Read/write request length */
unsigned char rw_data[128]; /* Data to read/write */
};
/***********************************************************************
* Shrink Buffer and Board Information definitions and structures.
************************************************************************/
/* Board type return codes */
#define PCXI_TYPE 1 /* Board type at the designated port is a PC/Xi */
#define PCXM_TYPE 2 /* Board type at the designated port is a PC/Xm */
#define PCXE_TYPE 3 /* Board type at the designated port is a PC/Xe */
#define MCXI_TYPE 4 /* Board type at the designated port is a MC/Xi */
#define COMXI_TYPE 5 /* Board type at the designated port is a COM/Xi */
/* Non-Zero Result codes. */
#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
#define RESULT_TOOSML 4 /* Too small an area to shrink. */
#define RESULT_NOCHAN 5 /* Channel structure for the board was not found */
struct shrink_buf_struct {
unsigned long shrink_buf_vaddr; /* Virtual address of board */
unsigned long shrink_buf_phys; /* Physical address of board */
unsigned long shrink_buf_bseg; /* Amount of board memory */
unsigned long shrink_buf_hseg; /* '186 Begining of Dual-Port */
unsigned long shrink_buf_lseg; /* '186 Begining of freed memory */
unsigned long shrink_buf_mseg; /* Linear address from start of
dual-port were freed memory
begins, host viewpoint. */
unsigned long shrink_buf_bdparam; /* Parameter for xxmemon and
xxmemoff */
unsigned long shrink_buf_reserva; /* Reserved */
unsigned long shrink_buf_reservb; /* Reserved */
unsigned long shrink_buf_reservc; /* Reserved */
unsigned long shrink_buf_reservd; /* Reserved */
unsigned char shrink_buf_result; /* Reason for call failing
Zero is Good return */
unsigned char shrink_buf_init; /* Non-Zero if it caused an
xxinit call. */
unsigned char shrink_buf_anports; /* Number of async ports */
unsigned char shrink_buf_snports; /* Number of sync ports */
unsigned char shrink_buf_type; /* Board type 1 = PC/Xi,
2 = PC/Xm,
3 = PC/Xe
4 = MC/Xi
5 = COMX/i */
unsigned char shrink_buf_card; /* Card number */
};
/************************************************************************
* Structure to get driver status information
************************************************************************/
struct digi_dinfo {
unsigned long dinfo_nboards; /* # boards configured */
char dinfo_reserved[12]; /* for future expansion */
char dinfo_version[16]; /* driver version */
};
#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */
/************************************************************************
* Structure used with ioctl commands for per-board information
*
* physsize and memsize differ when board has "windowed" memory
************************************************************************/
struct digi_info {
unsigned long info_bdnum; /* Board number (0 based) */
unsigned long info_ioport; /* io port address */
unsigned long info_physaddr; /* memory address */
unsigned long info_physsize; /* Size of host mem window */
unsigned long info_memsize; /* Amount of dual-port mem */
/* on board */
unsigned short info_bdtype; /* Board type */
unsigned short info_nports; /* number of ports */
char info_bdstate; /* board state */
char info_reserved[7]; /* for future expansion */
};
#define DIGI_GETBD ('d'<<8) | 249 /* get board info */
struct digi_stat {
unsigned int info_chan; /* Channel number (0 based) */
unsigned int info_brd; /* Board number (0 based) */
unsigned long info_cflag; /* cflag for channel */
unsigned long info_iflag; /* iflag for channel */
unsigned long info_oflag; /* oflag for channel */
unsigned long info_mstat; /* mstat for channel */
unsigned long info_tx_data; /* tx_data for channel */
unsigned long info_rx_data; /* rx_data for channel */
unsigned long info_hflow; /* hflow for channel */
unsigned long info_reserved[8]; /* for future expansion */
};
#define DIGI_GETSTAT ('d'<<8) | 244 /* get board info */
/************************************************************************
*
* Structure used with ioctl commands for per-channel information
*
************************************************************************/
struct digi_ch {
unsigned long info_bdnum; /* Board number (0 based) */
unsigned long info_channel; /* Channel index number */
unsigned long info_ch_cflag; /* Channel cflag */
unsigned long info_ch_iflag; /* Channel iflag */
unsigned long info_ch_oflag; /* Channel oflag */
unsigned long info_chsize; /* Channel structure size */
unsigned long info_sleep_stat; /* sleep status */
dev_t info_dev; /* device number */
unsigned char info_initstate; /* Channel init state */
unsigned char info_running; /* Channel running state */
long reserved[8]; /* reserved for future use */
};
/*
* This structure is used with the DIGI_FEPCMD ioctl to
* tell the driver which port to send the command for.
*/
struct digi_cmd {
int cmd;
int word;
int ncmds;
int chan; /* channel index (zero based) */
int bdid; /* board index (zero based) */
};
/*
* info_sleep_stat defines
*/
#define INFO_RUNWAIT 0x0001
#define INFO_WOPEN 0x0002
#define INFO_TTIOW 0x0004
#define INFO_CH_RWAIT 0x0008
#define INFO_CH_WEMPTY 0x0010
#define INFO_CH_WLOW 0x0020
#define INFO_XXBUF_BUSY 0x0040
#define DIGI_GETCH ('d'<<8) | 245 /* get board info */
/* Board type definitions */
#define SUBTYPE 0007
#define T_PCXI 0000
#define T_PCXM 0001
#define T_PCXE 0002
#define T_PCXR 0003
#define T_SP 0004
#define T_SP_PLUS 0005
# define T_HERC 0000
# define T_HOU 0001
# define T_LON 0002
# define T_CHA 0003
#define FAMILY 0070
#define T_COMXI 0000
#define T_PCXX 0010
#define T_CX 0020
#define T_EPC 0030
#define T_PCLITE 0040
#define T_SPXX 0050
#define T_AVXX 0060
#define T_DXB 0070
#define T_A2K_4_8 0070
#define BUSTYPE 0700
#define T_ISABUS 0000
#define T_MCBUS 0100
#define T_EISABUS 0200
#define T_PCIBUS 0400
/* Board State Definitions */
#define BD_RUNNING 0x0
#define BD_REASON 0x7f
#define BD_NOTFOUND 0x1
#define BD_NOIOPORT 0x2
#define BD_NOMEM 0x3
#define BD_NOBIOS 0x4
#define BD_NOFEP 0x5
#define BD_FAILED 0x6
#define BD_ALLOCATED 0x7
#define BD_TRIBOOT 0x8
#define BD_BADKME 0x80
#define DIGI_LOOPBACK ('d'<<8) | 252 /* Enable/disable UART internal loopback */
#define DIGI_SPOLL ('d'<<8) | 254 /* change poller rate */
#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */
#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */
#define DIGI_RESET_PORT ('e'<<8) | 93 /* Reset port */
#endif /* DIGI_H */

View File

@ -0,0 +1,798 @@
/*
* Copyright 2003 Digi International (www.digi.com)
* Scott H Kilau <Scott_Kilau at digi dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: downld.c,v 1.6 2009/01/14 14:10:54 markh Exp $
*/
/*
** downld.c
**
** This is the daemon that sends the fep, bios, and concentrator images
** from user space to the driver.
** BUGS:
** If the file changes in the middle of the download, you probably
** will get what you deserve.
**
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include "dgap_types.h"
#include "digi.h"
#include "dgap_fep5.h"
#include "dgap_downld.h"
#include <string.h>
#include <malloc.h>
#include <stddef.h>
#include <unistd.h>
char *pgm;
void myperror();
/*
** This structure is used to keep track of the diferent images available
** to give to the driver. It is arranged so that the things that are
** constants or that have defaults are first inthe strucutre to simplify
** the table of initializers.
*/
struct image_info {
short type; /* bios, fep, conc */
short family; /* boards this applies to */
short subtype; /* subtype */
int len; /* size of image */
char *image; /* ioctl struct + image */
char *name;
char *fname; /* filename of binary (i.e. "asfep.bin") */
char *pathname; /* pathname to this binary ("/etc/dgap/xrfep.bin"); */
time_t mtime; /* Last modification time */
};
#define IBIOS 0
#define IFEP 1
#define ICONC 2
#define ICONFIG 3
#define IBAD 4
#define DEFAULT_LOC "/lib/firmware/dgap/"
struct image_info *image_list;
int nimages, count;
struct image_info images[] = {
{IBIOS, T_EPC, SUBTYPE, 0, NULL, "EPC/X", "fxbios.bin", DEFAULT_LOC "fxbios.bin", 0 },
{IFEP, T_EPC, SUBTYPE, 0, NULL, "EPC/X", "fxfep.bin", DEFAULT_LOC "fxfep.bin", 0 },
{ICONC, T_EPC, SUBTYPE, 0, NULL, "EPC/X", "fxcon.bin", DEFAULT_LOC "fxcon.bin", 0 },
{IBIOS, T_CX, SUBTYPE, 0, NULL, "C/X", "cxbios.bin", DEFAULT_LOC "cxbios.bin", 0 },
{IFEP, T_CX, SUBTYPE, 0, NULL, "C/X", "cxhost.bin", DEFAULT_LOC "cxhost.bin", 0 },
{IBIOS, T_CX, T_PCIBUS, 0, NULL, "C/X PCI", "cxpbios.bin", DEFAULT_LOC "cxpbios.bin", 0 },
{IFEP, T_CX, T_PCIBUS, 0, NULL, "C/X PCI", "cxpfep.bin", DEFAULT_LOC "cxpfep.bin", 0 },
{ICONC, T_CX, SUBTYPE, 0, NULL, "C/X", "cxcon.bin", DEFAULT_LOC "cxcon.bin", 0 },
{ICONC, T_CX, SUBTYPE, 0, NULL, "C/X", "ibmcxcon.bin", DEFAULT_LOC "ibmcxcon.bin", 0 },
{ICONC, T_CX, SUBTYPE, 0, NULL, "C/X", "ibmencon.bin", DEFAULT_LOC "ibmencon.bin", 0 },
{IBIOS, FAMILY, T_PCXR, 0, NULL, "PCXR", "xrbios.bin", DEFAULT_LOC "xrbios.bin", 0 },
{IFEP, FAMILY, T_PCXR, 0, NULL, "PCXR", "xrfep.bin", DEFAULT_LOC "xrfep.bin", 0 },
{IBIOS, T_PCLITE, SUBTYPE, 0, NULL, "X/em", "sxbios.bin", DEFAULT_LOC "sxbios.bin", 0 },
{IFEP, T_PCLITE, SUBTYPE, 0, NULL, "X/em", "sxfep.bin", DEFAULT_LOC "sxfep.bin", 0 },
{IBIOS, T_EPC, T_PCIBUS, 0, NULL, "PCI", "pcibios.bin", DEFAULT_LOC "pcibios.bin", 0 },
{IFEP, T_EPC, T_PCIBUS, 0, NULL, "PCI", "pcifep.bin", DEFAULT_LOC "pcifep.bin", 0 },
{ICONFIG, 0, 0, 0, NULL, NULL, "dgap.conf", "/etc/dgap.conf", 0 },
/* IBAD/NULL entry indicating end-of-table */
{IBAD, 0, 0, 0, NULL, NULL, NULL, NULL, 0 }
} ;
int errorprint = 1;
int nodldprint = 1;
int debugflag;
int fd;
struct downld_t *ip; /* Image pointer in current image */
struct downld_t *dp; /* conc. download */
/*
* The same for either the FEP or the BIOS.
* Append the downldio header, issue the ioctl, then free
* the buffer. Not horribly CPU efficient, but quite RAM efficient.
*/
void squirt(int req_type, int bdid, struct image_info *ii)
{
struct downldio *dliop;
int size_buf;
int sfd;
struct stat sb;
/*
* If this binary comes from a file, stat it to see how
* large it is. Yes, we intentionally do this each
* time for the binary may change between loads.
*/
if (ii->pathname) {
sfd = open(ii->pathname, O_RDONLY);
if (sfd < 0 ) {
myperror(ii->pathname);
goto squirt_end;
}
if (fstat(sfd, &sb) == -1 ) {
myperror(ii->pathname);
goto squirt_end;
}
ii->len = sb.st_size ;
}
size_buf = ii->len + sizeof(struct downldio);
/*
* This buffer will be freed at the end of this function. It is
* not resilient and should be around only long enough for the d/l
* to happen.
*/
dliop = (struct downldio *) malloc(size_buf);
if (dliop == NULL) {
fprintf(stderr,"%s: can't get %d bytes of memory; aborting\n",
pgm, size_buf);
exit (1);
}
/* Now, stick the image in fepimage. This can come from either
* the compiled-in image or from the filesystem.
*/
if (ii->pathname)
read(sfd, dliop->image.fi.fepimage, ii->len);
else
memcpy(dliop ->image.fi.fepimage, ii->image, ii->len);
dliop->req_type = req_type;
dliop->bdid = bdid;
dliop->image.fi.len = ii->len;
if (debugflag)
printf("sending %d bytes of %s %s from %s\n",
ii->len,
(ii->type == IFEP) ? "FEP" : (ii->type == IBIOS) ? "BIOS" : "CONFIG",
ii->name ? ii->name : "",
(ii->pathname) ? ii->pathname : "internal image" );
if (ioctl(fd, DIGI_DLREQ_SET, (char *) dliop) == -1) {
if(errorprint) {
fprintf(stderr,
"%s: warning - download ioctl failed\n",pgm);
errorprint = 0;
}
sleep(2);
}
squirt_end:
if (ii->pathname) {
close(sfd);
}
free(dliop);
}
/*
* See if we need to reload the download image in core
*
*/
void consider_file_rescan(struct image_info *ii)
{
int sfd ;
int len ;
struct stat sb;
/* This operation only makes sense when we're working from a file */
if (ii->pathname) {
sfd = open (ii->pathname, O_RDONLY) ;
if (sfd < 0 ) {
myperror(ii->pathname);
exit(1) ;
}
if( fstat(sfd,&sb) == -1 ) {
myperror(ii->pathname);
exit(1);
}
/* If the file hasn't changed since we last did this,
* and we have not done a free() on the image, bail
*/
if (ii->image && (sb.st_mtime == ii->mtime))
goto end_rescan;
ii->len = len = sb.st_size ;
/* Record the timestamp of the file */
ii->mtime = sb.st_mtime;
/* image should be NULL unless there is an image malloced
* in already. Before we malloc again, make sure we don't
* have a memory leak.
*/
if ( ii->image ) {
free( ii->image );
/* ii->image = NULL; */ /* not necessary */
}
/* This image will be kept only long enough for the
* download to happen. After sending the last block,
* it will be freed
*/
ii->image = malloc(len) ;
if (ii->image == NULL) {
fprintf(stderr,
"%s: can't get %d bytes of memory; aborting\n",
pgm, len);
exit (1);
}
if (read(sfd, ii->image, len) < len) {
fprintf(stderr,"%s: read error on %s; aborting\n",
pgm, ii->pathname);
exit (1);
}
end_rescan:
close(sfd);
}
}
/*
* Scan for images to match the driver requests
*/
struct image_info * find_conc_image()
{
int x ;
struct image_info *i = NULL ;
for ( x = 0; x < nimages; x++ ) {
i=&image_list[x];
if(i->type != ICONC)
continue;
consider_file_rescan(i) ;
ip = (struct downld_t *) image_list[x].image;
if (ip == NULL) continue;
/*
* When I removed Clusterport, I kept only the code that I
* was SURE wasn't ClusterPort. We may not need the next two
* lines of code.
*/
if ((dp->dl_type != 'P' ) && ( ip->dl_srev == dp->dl_srev ))
return i;
}
return NULL ;
}
int main(int argc, char **argv)
{
struct downldio dlio;
int offset, bsize;
int x;
char *down, *image, *fname;
struct image_info *ii;
pgm = argv[0];
dp = &dlio.image.dl; /* conc. download */
while((argc > 2) && !strcmp(argv[1],"-d")) {
debugflag++ ;
argc-- ;
argv++ ;
}
if(argc < 2) {
fprintf(stderr,
"usage: %s download-device [image-file] ...\n",
pgm);
exit(1);
}
/*
* Daemonize, unless debugging is turned on.
*/
if (debugflag == 0) {
switch (fork())
{
case 0:
break;
case -1:
return 1;
default:
return 0;
}
setsid();
/*
* The child no longer needs "stdin", "stdout", or "stderr",
* and should not block processes waiting for them to close.
*/
fclose(stdin);
fclose(stdout);
fclose(stderr);
}
while (1) {
if( (fd = open(argv[1], O_RDWR)) == -1 ) {
sleep(1);
}
else
break;
}
/*
** create a list of images to search through when trying to match
** requests from the driver. Put images from the command line in
** the list before built in images so that the command line images
** can override the built in ones.
*/
/* allocate space for the list */
nimages = argc - 2;
/* count the number of default list entries */
for (count = 0; images[count].type != IBAD; ++count) ;
nimages += count;
/* Really should just remove the variable "image_list".... robertl */
image_list = images ;
/* get the images from the command line */
for(x = 2; x < argc; x++) {
int xx;
/*
* strip off any leading path information for
* determining file type
*/
if( (fname = strrchr(argv[x],'/')) == NULL)
fname = argv[x];
else
fname++; /* skip the slash */
for (xx = 0; xx < count; xx++) {
if (strcmp(fname, images[xx].fname) == 0 ) {
images[xx].pathname = argv[x];
/* image should be NULL until */
/* space is malloced */
images[xx].image = NULL ;
}
}
}
sleep(3);
/*
** Endless loop: get a request from the fep, and service that request.
*/
for(;;) {
/* get the request */
if (debugflag)
printf("b4 get ioctl...");
if (ioctl(fd,DIGI_DLREQ_GET, &dlio) == -1 ) {
if (errorprint) {
fprintf(stderr,
"%s: warning - download ioctl failed\n",
pgm);
errorprint = 0;
}
sleep(2);
} else {
if (debugflag)
printf("dlio.req_type is %d bd %d\n",
dlio.req_type,dlio.bdid);
switch(dlio.req_type) {
case DLREQ_BIOS:
/*
** find the bios image for this type
*/
for ( x = 0; x < nimages; x++ ) {
if(image_list[x].type != IBIOS)
continue;
if ((dlio.image.fi.type & FAMILY) ==
image_list[x].family) {
if ( image_list[x].family == T_CX ) {
if ((dlio.image.fi.type & BUSTYPE)
== T_PCIBUS ) {
if ( image_list[x].subtype
== T_PCIBUS )
break;
}
else {
break;
}
}
else if ( image_list[x].family == T_EPC ) {
/* If subtype of image is T_PCIBUS, it is */
/* a PCI EPC image, so the board must */
/* have bus type T_PCIBUS to match */
if ((dlio.image.fi.type & BUSTYPE)
== T_PCIBUS ) {
if ( image_list[x].subtype
== T_PCIBUS )
break;
}
else {
/* NON PCI EPC doesn't use PCI image */
if ( image_list[x].subtype
!= T_PCIBUS )
break;
}
}
else
break;
}
else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
/* PCXR board will break out of the loop here */
if ( image_list[x].subtype == T_PCXR ) {
break;
}
}
}
if ( x >= nimages) {
/*
** no valid images exist
*/
if(nodldprint) {
fprintf(stderr,
"%s: cannot find correct BIOS image\n",
pgm);
nodldprint = 0;
}
dlio.image.fi.type = -1;
if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1) {
if (errorprint) {
fprintf(stderr,
"%s: warning - download ioctl failed\n",
pgm);
errorprint = 0;
}
sleep(2);
}
break;
}
squirt(dlio.req_type, dlio.bdid, &image_list[x]);
break ;
case DLREQ_FEP:
/*
** find the fep image for this type
*/
for ( x = 0; x < nimages; x++ ) {
if(image_list[x].type != IFEP)
continue;
if( (dlio.image.fi.type & FAMILY) ==
image_list[x].family ) {
if ( image_list[x].family == T_CX ) {
/* C/X PCI board */
if ((dlio.image.fi.type & BUSTYPE)
== T_PCIBUS ) {
if ( image_list[x].subtype
== T_PCIBUS )
break;
}
else {
/* Regular CX */
break;
}
}
else if ( image_list[x].family == T_EPC ) {
/* If subtype of image is T_PCIBUS, it is */
/* a PCI EPC image, so the board must */
/* have bus type T_PCIBUS to match */
if ((dlio.image.fi.type & BUSTYPE)
== T_PCIBUS ) {
if ( image_list[x].subtype
== T_PCIBUS )
break;
}
else {
/* NON PCI EPC doesn't use PCI image */
if ( image_list[x].subtype
!= T_PCIBUS )
break;
}
}
else
break;
}
else if ((dlio.image.fi.type & SUBTYPE) == image_list[x].subtype) {
/* PCXR board will break out of the loop here */
if ( image_list[x].subtype == T_PCXR ) {
break;
}
}
}
if ( x >= nimages) {
/*
** no valid images exist
*/
if(nodldprint) {
fprintf(stderr,
"%s: cannot find correct FEP image\n",
pgm);
nodldprint = 0;
}
dlio.image.fi.type=-1;
if( ioctl(fd,DIGI_DLREQ_SET,&dlio) == -1 ) {
if(errorprint) {
fprintf(stderr,
"%s: warning - download ioctl failed\n",
pgm);
errorprint=0;
}
sleep(2);
}
break;
}
squirt(dlio.req_type, dlio.bdid, &image_list[x]);
break;
case DLREQ_DEVCREATE:
{
char string[1024];
#if 0
sprintf(string, "%s /proc/dgap/%d/mknod", DEFSHELL, dlio.bdid);
#endif
sprintf(string, "%s /usr/sbin/dgap_updatedevs %d", DEFSHELL, dlio.bdid);
system(string);
if (debugflag)
printf("Created Devices.\n");
if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
if(errorprint) {
fprintf(stderr, "%s: warning - DEVCREATE ioctl failed\n",pgm);
errorprint = 0;
}
sleep(2);
}
if (debugflag)
printf("After ioctl set - Created Device.\n");
}
break;
case DLREQ_CONFIG:
for ( x = 0; x < nimages; x++ ) {
if(image_list[x].type != ICONFIG)
continue;
else
break;
}
if ( x >= nimages) {
/*
** no valid images exist
*/
if(nodldprint) {
fprintf(stderr,
"%s: cannot find correct CONFIG image\n",
pgm);
nodldprint = 0;
}
dlio.image.fi.type=-1;
if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
if(errorprint) {
fprintf(stderr,
"%s: warning - download ioctl failed\n",
pgm);
errorprint=0;
}
sleep(2);
}
break;
}
squirt(dlio.req_type, dlio.bdid, &image_list[x]);
break;
case DLREQ_CONC:
/*
** find the image needed for this download
*/
if ( dp->dl_seq == 0 ) {
/*
** find image for hardware rev range
*/
for ( x = 0; x < nimages; x++ ) {
ii=&image_list[x];
if(image_list[x].type != ICONC)
continue;
consider_file_rescan(ii) ;
ip = (struct downld_t *) image_list[x].image;
if (ip == NULL) continue;
/*
* When I removed Clusterport, I kept only the
* code that I was SURE wasn't ClusterPort.
* We may not need the next four lines of code.
*/
if ((dp->dl_type != 'P' ) &&
(ip->dl_lrev <= dp->dl_lrev ) &&
( dp->dl_lrev <= ip->dl_hrev))
break;
}
if ( x >= nimages ) {
/*
** No valid images exist
*/
if(nodldprint) {
fprintf(stderr,
"%s: cannot find correct download image %d\n",
pgm, dp->dl_lrev);
nodldprint=0;
}
continue;
}
} else {
/*
** find image version required
*/
if ((ii = find_conc_image()) == NULL ) {
/*
** No valid images exist
*/
fprintf(stderr,
"%s: can't find rest of download image??\n",
pgm);
continue;
}
}
/*
** download block of image
*/
offset = 1024 * dp->dl_seq;
/*
** test if block requested within image
*/
if ( offset < ii->len ) {
/*
** if it is, determine block size, set segment,
** set size, set pointers, and copy block
*/
if (( bsize = ii->len - offset ) > 1024 )
bsize = 1024;
/*
** copy image version info to download area
*/
dp->dl_srev = ip->dl_srev;
dp->dl_lrev = ip->dl_lrev;
dp->dl_hrev = ip->dl_hrev;
dp->dl_seg = (64 * dp->dl_seq) + ip->dl_seg;
dp->dl_size = bsize;
down = (char *)&dp->dl_data[0];
image = (char *)((char *)ip + offset);
memcpy(down, image, bsize);
}
else {
/*
** Image has been downloaded, set segment and
** size to indicate no more blocks
*/
dp->dl_seg = ip->dl_seg;
dp->dl_size = 0;
/* Now, we can release the concentrator */
/* image from memory if we're running */
/* from filesystem images */
if (ii->pathname)
if (ii->image) {
free(ii->image);
ii->image = NULL ;
}
}
if (debugflag)
printf(
"sending conc dl section %d to %s from %s\n",
dp->dl_seq, ii->name,
ii->pathname ? ii->pathname : "Internal Image");
if (ioctl(fd, DIGI_DLREQ_SET, &dlio) == -1 ) {
if (errorprint) {
fprintf(stderr,
"%s: warning - download ioctl failed\n",
pgm);
errorprint=0;
}
sleep(2);
}
break;
} /* switch */
}
if (debugflag > 1) {
printf("pausing: "); fflush(stdout);
fflush(stdin);
while(getchar() != '\n');
printf("continuing\n");
}
}
}
/*
** myperror()
**
** Same as normal perror(), but places the program name at the begining
** of the message.
*/
void myperror(char *s)
{
fprintf(stderr,"%s: %s: %s.\n",pgm, s, strerror(errno));
}