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:
parent
6b5ad9d269
commit
c84b8b503e
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
@ -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
|
@ -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
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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));
|
||||
}
|
Loading…
Reference in New Issue