|
@@ -25,6 +25,7 @@
|
|
|
#include <linux/mm.h>
|
|
|
#include <linux/ioport.h>
|
|
|
#include <linux/errno.h>
|
|
|
+#include <linux/firmware.h>
|
|
|
#include <linux/signal.h>
|
|
|
#include <linux/sched.h>
|
|
|
#include <linux/timer.h>
|
|
@@ -47,8 +48,12 @@
|
|
|
#include <asm/io.h>
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
|
+#include "moxa.h"
|
|
|
+
|
|
|
#define MOXA_VERSION "5.1k"
|
|
|
|
|
|
+#define MOXA_FW_HDRLEN 32
|
|
|
+
|
|
|
#define MOXAMAJOR 172
|
|
|
#define MOXACUMAJOR 173
|
|
|
|
|
@@ -92,6 +97,8 @@ static struct pci_device_id moxa_pcibrds[] = {
|
|
|
MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
|
|
|
#endif /* CONFIG_PCI */
|
|
|
|
|
|
+struct moxa_port;
|
|
|
+
|
|
|
static struct moxa_board_conf {
|
|
|
int boardType;
|
|
|
int numPorts;
|
|
@@ -99,6 +106,8 @@ static struct moxa_board_conf {
|
|
|
|
|
|
int loadstat;
|
|
|
|
|
|
+ struct moxa_port *ports;
|
|
|
+
|
|
|
void __iomem *basemem;
|
|
|
void __iomem *intNdx;
|
|
|
void __iomem *intPend;
|
|
@@ -156,6 +165,7 @@ struct moxa_port {
|
|
|
#define WAKEUP_CHARS 256
|
|
|
|
|
|
static int ttymajor = MOXAMAJOR;
|
|
|
+static int moxaCard;
|
|
|
/* Variables for insmod */
|
|
|
#ifdef MODULE
|
|
|
static unsigned long baseaddr[MAX_BOARDS];
|
|
@@ -208,7 +218,6 @@ static void moxa_receive_data(struct moxa_port *);
|
|
|
/*
|
|
|
* moxa board interface functions:
|
|
|
*/
|
|
|
-static void MoxaDriverInit(void);
|
|
|
static int MoxaDriverIoctl(unsigned int, unsigned long, int);
|
|
|
static int MoxaDriverPoll(void);
|
|
|
static int MoxaPortsOfCard(int);
|
|
@@ -263,6 +272,489 @@ static struct moxa_port moxa_ports[MAX_PORTS];
|
|
|
static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
|
|
|
static DEFINE_SPINLOCK(moxa_lock);
|
|
|
|
|
|
+static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
|
|
|
+{
|
|
|
+ switch (brd->boardType) {
|
|
|
+ case MOXA_BOARD_C218_ISA:
|
|
|
+ case MOXA_BOARD_C218_PCI:
|
|
|
+ if (model != 1)
|
|
|
+ goto err;
|
|
|
+ break;
|
|
|
+ case MOXA_BOARD_CP204J:
|
|
|
+ if (model != 3)
|
|
|
+ goto err;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ if (model != 2)
|
|
|
+ goto err;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_check_fw(const void *ptr)
|
|
|
+{
|
|
|
+ const __le16 *lptr = ptr;
|
|
|
+
|
|
|
+ if (*lptr != cpu_to_le16(0x7980))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ void __iomem *baseAddr = brd->basemem;
|
|
|
+ u16 tmp;
|
|
|
+
|
|
|
+ writeb(HW_reset, baseAddr + Control_reg); /* reset */
|
|
|
+ msleep(10);
|
|
|
+ memset_io(baseAddr, 0, 4096);
|
|
|
+ memcpy_toio(baseAddr, buf, len); /* download BIOS */
|
|
|
+ writeb(0, baseAddr + Control_reg); /* restart */
|
|
|
+
|
|
|
+ msleep(2000);
|
|
|
+
|
|
|
+ switch (brd->boardType) {
|
|
|
+ case MOXA_BOARD_C218_ISA:
|
|
|
+ case MOXA_BOARD_C218_PCI:
|
|
|
+ tmp = readw(baseAddr + C218_key);
|
|
|
+ if (tmp != C218_KeyCode)
|
|
|
+ goto err;
|
|
|
+ break;
|
|
|
+ case MOXA_BOARD_CP204J:
|
|
|
+ tmp = readw(baseAddr + C218_key);
|
|
|
+ if (tmp != CP204J_KeyCode)
|
|
|
+ goto err;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ tmp = readw(baseAddr + C320_key);
|
|
|
+ if (tmp != C320_KeyCode)
|
|
|
+ goto err;
|
|
|
+ tmp = readw(baseAddr + C320_status);
|
|
|
+ if (tmp != STS_init) {
|
|
|
+ printk(KERN_ERR "moxa: bios upload failed -- CPU/Basic "
|
|
|
+ "module not found\n");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ printk(KERN_ERR "moxa: bios upload failed -- board not found\n");
|
|
|
+ return -EIO;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ void __iomem *baseAddr = brd->basemem;
|
|
|
+
|
|
|
+ if (len < 7168) {
|
|
|
+ printk(KERN_ERR "moxa: invalid 320 bios -- too short\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ writew(len - 7168 - 2, baseAddr + C320bapi_len);
|
|
|
+ writeb(1, baseAddr + Control_reg); /* Select Page 1 */
|
|
|
+ memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
|
|
|
+ writeb(2, baseAddr + Control_reg); /* Select Page 2 */
|
|
|
+ memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_load_c218(struct moxa_board_conf *brd, const void *ptr,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ void __iomem *baseAddr = brd->basemem;
|
|
|
+ const u16 *uptr = ptr;
|
|
|
+ size_t wlen, len2, j;
|
|
|
+ unsigned int i, retry;
|
|
|
+ u16 usum, keycode;
|
|
|
+
|
|
|
+ if (brd->boardType == MOXA_BOARD_CP204J)
|
|
|
+ keycode = CP204J_KeyCode;
|
|
|
+ else
|
|
|
+ keycode = C218_KeyCode;
|
|
|
+ usum = 0;
|
|
|
+ wlen = len >> 1;
|
|
|
+ for (i = 0; i < wlen; i++)
|
|
|
+ usum += le16_to_cpu(uptr[i]);
|
|
|
+ retry = 0;
|
|
|
+ do {
|
|
|
+ wlen = len >> 1;
|
|
|
+ j = 0;
|
|
|
+ while (wlen) {
|
|
|
+ len2 = (wlen > 2048) ? 2048 : wlen;
|
|
|
+ wlen -= len2;
|
|
|
+ memcpy_toio(baseAddr + C218_LoadBuf, ptr + j,
|
|
|
+ len2 << 1);
|
|
|
+ j += len2 << 1;
|
|
|
+
|
|
|
+ writew(len2, baseAddr + C218DLoad_len);
|
|
|
+ writew(0, baseAddr + C218_key);
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
+ if (readw(baseAddr + C218_key) == keycode)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + C218_key) != keycode)
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ writew(0, baseAddr + C218DLoad_len);
|
|
|
+ writew(usum, baseAddr + C218check_sum);
|
|
|
+ writew(0, baseAddr + C218_key);
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
+ if (readw(baseAddr + C218_key) == keycode)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ retry++;
|
|
|
+ } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
|
|
|
+ if (readb(baseAddr + C218chksum_ok) != 1)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ writew(0, baseAddr + C218_key);
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
+ if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ writew(1, baseAddr + Disable_IRQ);
|
|
|
+ writew(0, baseAddr + Magic_no);
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
+ if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ moxaCard = 1;
|
|
|
+ brd->intNdx = baseAddr + IRQindex;
|
|
|
+ brd->intPend = baseAddr + IRQpending;
|
|
|
+ brd->intTable = baseAddr + IRQtable;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_load_c320(struct moxa_board_conf *brd, const void *ptr,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ void __iomem *baseAddr = brd->basemem;
|
|
|
+ const u16 *uptr = ptr;
|
|
|
+ size_t wlen, len2, j;
|
|
|
+ unsigned int i, retry;
|
|
|
+ u16 usum;
|
|
|
+
|
|
|
+ usum = 0;
|
|
|
+ wlen = len >> 1;
|
|
|
+ for (i = 0; i < wlen; i++)
|
|
|
+ usum += le16_to_cpu(uptr[i]);
|
|
|
+ retry = 0;
|
|
|
+ do {
|
|
|
+ wlen = len >> 1;
|
|
|
+ j = 0;
|
|
|
+ while (wlen) {
|
|
|
+ len2 = (wlen > 2048) ? 2048 : wlen;
|
|
|
+ wlen -= len2;
|
|
|
+ memcpy_toio(baseAddr + C320_LoadBuf, ptr + j,
|
|
|
+ len2 << 1);
|
|
|
+ j += len2 << 1;
|
|
|
+ writew(len2, baseAddr + C320DLoad_len);
|
|
|
+ writew(0, baseAddr + C320_key);
|
|
|
+ for (i = 0; i < 10; i++) {
|
|
|
+ if (readw(baseAddr + C320_key) == C320_KeyCode)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + C320_key) != C320_KeyCode)
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ writew(0, baseAddr + C320DLoad_len);
|
|
|
+ writew(usum, baseAddr + C320check_sum);
|
|
|
+ writew(0, baseAddr + C320_key);
|
|
|
+ for (i = 0; i < 10; i++) {
|
|
|
+ if (readw(baseAddr + C320_key) == C320_KeyCode)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ retry++;
|
|
|
+ } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
|
|
|
+ if (readb(baseAddr + C320chksum_ok) != 1)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ writew(0, baseAddr + C320_key);
|
|
|
+ for (i = 0; i < 600; i++) {
|
|
|
+ if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */
|
|
|
+ writew(0x3800, baseAddr + TMS320_PORT1);
|
|
|
+ writew(0x3900, baseAddr + TMS320_PORT2);
|
|
|
+ writew(28499, baseAddr + TMS320_CLOCK);
|
|
|
+ } else {
|
|
|
+ writew(0x3200, baseAddr + TMS320_PORT1);
|
|
|
+ writew(0x3400, baseAddr + TMS320_PORT2);
|
|
|
+ writew(19999, baseAddr + TMS320_CLOCK);
|
|
|
+ }
|
|
|
+ writew(1, baseAddr + Disable_IRQ);
|
|
|
+ writew(0, baseAddr + Magic_no);
|
|
|
+ for (i = 0; i < 500; i++) {
|
|
|
+ if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ j = readw(baseAddr + Module_cnt);
|
|
|
+ if (j <= 0)
|
|
|
+ return -EIO;
|
|
|
+ brd->numPorts = j * 8;
|
|
|
+ writew(j, baseAddr + Module_no);
|
|
|
+ writew(0, baseAddr + Magic_no);
|
|
|
+ for (i = 0; i < 600; i++) {
|
|
|
+ if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
+ break;
|
|
|
+ msleep(10);
|
|
|
+ }
|
|
|
+ if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
+ return -EIO;
|
|
|
+ moxaCard = 1;
|
|
|
+ brd->intNdx = baseAddr + IRQindex;
|
|
|
+ brd->intPend = baseAddr + IRQpending;
|
|
|
+ brd->intTable = baseAddr + IRQtable;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ void __iomem *ofsAddr, *baseAddr = brd->basemem;
|
|
|
+ struct moxa_port *port;
|
|
|
+ int retval, i;
|
|
|
+
|
|
|
+ if (len % 2) {
|
|
|
+ printk(KERN_ERR "moxa: C2XX bios length is not even\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (brd->boardType) {
|
|
|
+ case MOXA_BOARD_C218_ISA:
|
|
|
+ case MOXA_BOARD_C218_PCI:
|
|
|
+ case MOXA_BOARD_CP204J:
|
|
|
+ retval = moxa_load_c218(brd, ptr, len);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+ port = brd->ports;
|
|
|
+ for (i = 0; i < brd->numPorts; i++, port++) {
|
|
|
+ port->chkPort = 1;
|
|
|
+ port->curBaud = 9600L;
|
|
|
+ port->DCDState = 0;
|
|
|
+ port->tableAddr = baseAddr + Extern_table +
|
|
|
+ Extern_size * i;
|
|
|
+ ofsAddr = port->tableAddr;
|
|
|
+ writew(C218rx_mask, ofsAddr + RX_mask);
|
|
|
+ writew(C218tx_mask, ofsAddr + TX_mask);
|
|
|
+ writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
|
|
|
+ writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
|
|
|
+
|
|
|
+ writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
|
|
|
+ writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ retval = moxa_load_c320(brd, ptr, len); /* fills in numPorts */
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+ port = brd->ports;
|
|
|
+ for (i = 0; i < brd->numPorts; i++, port++) {
|
|
|
+ port->chkPort = 1;
|
|
|
+ port->curBaud = 9600L;
|
|
|
+ port->DCDState = 0;
|
|
|
+ port->tableAddr = baseAddr + Extern_table +
|
|
|
+ Extern_size * i;
|
|
|
+ ofsAddr = port->tableAddr;
|
|
|
+ switch (brd->numPorts) {
|
|
|
+ case 8:
|
|
|
+ writew(C320p8rx_mask, ofsAddr + RX_mask);
|
|
|
+ writew(C320p8tx_mask, ofsAddr + TX_mask);
|
|
|
+ writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
|
|
|
+ writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
|
|
|
+ writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
|
|
|
+ writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
|
|
|
+
|
|
|
+ break;
|
|
|
+ case 16:
|
|
|
+ writew(C320p16rx_mask, ofsAddr + RX_mask);
|
|
|
+ writew(C320p16tx_mask, ofsAddr + TX_mask);
|
|
|
+ writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
|
|
|
+ writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
|
|
|
+ writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
|
|
|
+ writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 24:
|
|
|
+ writew(C320p24rx_mask, ofsAddr + RX_mask);
|
|
|
+ writew(C320p24tx_mask, ofsAddr + TX_mask);
|
|
|
+ writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
|
|
|
+ writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
|
|
|
+ writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
|
|
|
+ writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
|
|
|
+ break;
|
|
|
+ case 32:
|
|
|
+ writew(C320p32rx_mask, ofsAddr + RX_mask);
|
|
|
+ writew(C320p32tx_mask, ofsAddr + TX_mask);
|
|
|
+ writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
|
|
|
+ writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
|
|
|
+ writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
|
|
|
+ writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
|
|
|
+ writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ brd->loadstat = 1;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
|
|
|
+{
|
|
|
+ void *ptr = fw->data;
|
|
|
+ char rsn[64];
|
|
|
+ u16 lens[5];
|
|
|
+ size_t len;
|
|
|
+ unsigned int a, lenp, lencnt;
|
|
|
+ int ret = -EINVAL;
|
|
|
+ struct {
|
|
|
+ __le32 magic; /* 0x34303430 */
|
|
|
+ u8 reserved1[2];
|
|
|
+ u8 type; /* UNIX = 3 */
|
|
|
+ u8 model; /* C218T=1, C320T=2, CP204=3 */
|
|
|
+ u8 reserved2[8];
|
|
|
+ __le16 len[5];
|
|
|
+ } *hdr = ptr;
|
|
|
+
|
|
|
+ BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
|
|
|
+
|
|
|
+ if (fw->size < MOXA_FW_HDRLEN) {
|
|
|
+ strcpy(rsn, "too short (even header won't fit)");
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ if (hdr->magic != cpu_to_le32(0x30343034)) {
|
|
|
+ sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ if (hdr->type != 3) {
|
|
|
+ sprintf(rsn, "not for linux, type is %u", hdr->type);
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ if (moxa_check_fw_model(brd, hdr->model)) {
|
|
|
+ sprintf(rsn, "not for this card, model is %u", hdr->model);
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ len = MOXA_FW_HDRLEN;
|
|
|
+ lencnt = hdr->model == 2 ? 5 : 3;
|
|
|
+ for (a = 0; a < ARRAY_SIZE(lens); a++) {
|
|
|
+ lens[a] = le16_to_cpu(hdr->len[a]);
|
|
|
+ if (lens[a] && len + lens[a] <= fw->size &&
|
|
|
+ moxa_check_fw(&fw->data[len]))
|
|
|
+ printk(KERN_WARNING "moxa firmware: unexpected input "
|
|
|
+ "at offset %u, but going on\n", (u32)len);
|
|
|
+ if (!lens[a] && a < lencnt) {
|
|
|
+ sprintf(rsn, "too few entries in fw file");
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ len += lens[a];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (len != fw->size) {
|
|
|
+ sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
|
|
|
+ (u32)len);
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ ptr += MOXA_FW_HDRLEN;
|
|
|
+ lenp = 0; /* bios */
|
|
|
+
|
|
|
+ strcpy(rsn, "read above");
|
|
|
+
|
|
|
+ ret = moxa_load_bios(brd, ptr, lens[lenp]);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ /* we skip the tty section (lens[1]), since we don't need it */
|
|
|
+ ptr += lens[lenp] + lens[lenp + 1];
|
|
|
+ lenp += 2; /* comm */
|
|
|
+
|
|
|
+ if (hdr->model == 2) {
|
|
|
+ ret = moxa_load_320b(brd, ptr, lens[lenp]);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+ /* skip another tty */
|
|
|
+ ptr += lens[lenp] + lens[lenp + 1];
|
|
|
+ lenp += 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = moxa_load_code(brd, ptr, lens[lenp]);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
|
|
|
+{
|
|
|
+ const struct firmware *fw;
|
|
|
+ const char *file;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ switch (brd->boardType) {
|
|
|
+ case MOXA_BOARD_C218_ISA:
|
|
|
+ case MOXA_BOARD_C218_PCI:
|
|
|
+ file = "c218tunx.cod";
|
|
|
+ break;
|
|
|
+ case MOXA_BOARD_CP204J:
|
|
|
+ file = "cp204unx.cod";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ file = "c320tunx.cod";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = request_firmware(&fw, file, dev);
|
|
|
+ if (ret) {
|
|
|
+ printk(KERN_ERR "request_firmware failed\n");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = moxa_load_fw(brd, fw);
|
|
|
+
|
|
|
+ release_firmware(fw);
|
|
|
+end:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_PCI
|
|
|
static int __devinit moxa_pci_probe(struct pci_dev *pdev,
|
|
|
const struct pci_device_id *ent)
|
|
@@ -290,6 +782,7 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
|
|
|
}
|
|
|
|
|
|
board = &moxa_boards[i];
|
|
|
+ board->ports = &moxa_ports[i * MAX_PORTS_PER_BOARD];
|
|
|
|
|
|
retval = pci_request_region(pdev, 2, "moxa-base");
|
|
|
if (retval) {
|
|
@@ -319,9 +812,16 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
|
|
|
}
|
|
|
board->busType = MOXA_BUS_TYPE_PCI;
|
|
|
|
|
|
+ retval = moxa_init_board(board, &pdev->dev);
|
|
|
+ if (retval)
|
|
|
+ goto err_base;
|
|
|
+
|
|
|
pci_set_drvdata(pdev, board);
|
|
|
|
|
|
return (0);
|
|
|
+err_base:
|
|
|
+ iounmap(board->basemem);
|
|
|
+ board->basemem = NULL;
|
|
|
err_reg:
|
|
|
pci_release_region(pdev, 2);
|
|
|
err:
|
|
@@ -406,6 +906,7 @@ static int __init moxa_init(void)
|
|
|
isabrds + 1, moxa_brdname[type[i] - 1],
|
|
|
baseaddr[i]);
|
|
|
brd->boardType = type[i];
|
|
|
+ brd->ports = &moxa_ports[isabrds * MAX_PORTS_PER_BOARD];
|
|
|
brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
|
|
|
numports[i];
|
|
|
brd->busType = MOXA_BUS_TYPE_ISA;
|
|
@@ -415,6 +916,11 @@ static int __init moxa_init(void)
|
|
|
baseaddr[i]);
|
|
|
continue;
|
|
|
}
|
|
|
+ if (moxa_init_board(brd, NULL)) {
|
|
|
+ iounmap(brd->basemem);
|
|
|
+ brd->basemem = NULL;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
brd++;
|
|
|
isabrds++;
|
|
@@ -1062,308 +1568,17 @@ static void moxa_receive_data(struct moxa_port *ch)
|
|
|
if (tp)
|
|
|
ts = tp->termios;
|
|
|
/**************************************************
|
|
|
- if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
|
|
|
- *****************************************************/
|
|
|
- if (!tp || !ts) {
|
|
|
- MoxaPortFlushData(ch->port, 0);
|
|
|
- return;
|
|
|
- }
|
|
|
- spin_lock_irqsave(&moxa_lock, flags);
|
|
|
- MoxaPortReadData(ch->port, tp);
|
|
|
- spin_unlock_irqrestore(&moxa_lock, flags);
|
|
|
- tty_schedule_flip(tp);
|
|
|
-}
|
|
|
-
|
|
|
-#define Magic_code 0x404
|
|
|
-
|
|
|
-/*
|
|
|
- * System Configuration
|
|
|
- */
|
|
|
-/*
|
|
|
- * for C218 BIOS initialization
|
|
|
- */
|
|
|
-#define C218_ConfBase 0x800
|
|
|
-#define C218_status (C218_ConfBase + 0) /* BIOS running status */
|
|
|
-#define C218_diag (C218_ConfBase + 2) /* diagnostic status */
|
|
|
-#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */
|
|
|
-#define C218DLoad_len (C218_ConfBase + 6) /* WORD */
|
|
|
-#define C218check_sum (C218_ConfBase + 8) /* BYTE */
|
|
|
-#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
|
|
|
-#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
|
|
|
-#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
|
|
|
-#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
|
|
|
-#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
|
|
|
-
|
|
|
-#define C218_LoadBuf 0x0F00
|
|
|
-#define C218_KeyCode 0x218
|
|
|
-#define CP204J_KeyCode 0x204
|
|
|
-
|
|
|
-/*
|
|
|
- * for C320 BIOS initialization
|
|
|
- */
|
|
|
-#define C320_ConfBase 0x800
|
|
|
-#define C320_LoadBuf 0x0f00
|
|
|
-#define STS_init 0x05 /* for C320_status */
|
|
|
-
|
|
|
-#define C320_status C320_ConfBase + 0 /* BIOS running status */
|
|
|
-#define C320_diag C320_ConfBase + 2 /* diagnostic status */
|
|
|
-#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */
|
|
|
-#define C320DLoad_len C320_ConfBase + 6 /* WORD */
|
|
|
-#define C320check_sum C320_ConfBase + 8 /* WORD */
|
|
|
-#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
|
|
|
-#define C320bapi_len C320_ConfBase + 0x0c /* WORD */
|
|
|
-#define C320UART_no C320_ConfBase + 0x0e /* WORD */
|
|
|
-
|
|
|
-#define C320_KeyCode 0x320
|
|
|
-
|
|
|
-#define FixPage_addr 0x0000 /* starting addr of static page */
|
|
|
-#define DynPage_addr 0x2000 /* starting addr of dynamic page */
|
|
|
-#define C218_start 0x3000 /* starting addr of C218 BIOS prg */
|
|
|
-#define Control_reg 0x1ff0 /* select page and reset control */
|
|
|
-#define HW_reset 0x80
|
|
|
-
|
|
|
-/*
|
|
|
- * Function Codes
|
|
|
- */
|
|
|
-#define FC_CardReset 0x80
|
|
|
-#define FC_ChannelReset 1 /* C320 firmware not supported */
|
|
|
-#define FC_EnableCH 2
|
|
|
-#define FC_DisableCH 3
|
|
|
-#define FC_SetParam 4
|
|
|
-#define FC_SetMode 5
|
|
|
-#define FC_SetRate 6
|
|
|
-#define FC_LineControl 7
|
|
|
-#define FC_LineStatus 8
|
|
|
-#define FC_XmitControl 9
|
|
|
-#define FC_FlushQueue 10
|
|
|
-#define FC_SendBreak 11
|
|
|
-#define FC_StopBreak 12
|
|
|
-#define FC_LoopbackON 13
|
|
|
-#define FC_LoopbackOFF 14
|
|
|
-#define FC_ClrIrqTable 15
|
|
|
-#define FC_SendXon 16
|
|
|
-#define FC_SetTermIrq 17 /* C320 firmware not supported */
|
|
|
-#define FC_SetCntIrq 18 /* C320 firmware not supported */
|
|
|
-#define FC_SetBreakIrq 19
|
|
|
-#define FC_SetLineIrq 20
|
|
|
-#define FC_SetFlowCtl 21
|
|
|
-#define FC_GenIrq 22
|
|
|
-#define FC_InCD180 23
|
|
|
-#define FC_OutCD180 24
|
|
|
-#define FC_InUARTreg 23
|
|
|
-#define FC_OutUARTreg 24
|
|
|
-#define FC_SetXonXoff 25
|
|
|
-#define FC_OutCD180CCR 26
|
|
|
-#define FC_ExtIQueue 27
|
|
|
-#define FC_ExtOQueue 28
|
|
|
-#define FC_ClrLineIrq 29
|
|
|
-#define FC_HWFlowCtl 30
|
|
|
-#define FC_GetClockRate 35
|
|
|
-#define FC_SetBaud 36
|
|
|
-#define FC_SetDataMode 41
|
|
|
-#define FC_GetCCSR 43
|
|
|
-#define FC_GetDataError 45
|
|
|
-#define FC_RxControl 50
|
|
|
-#define FC_ImmSend 51
|
|
|
-#define FC_SetXonState 52
|
|
|
-#define FC_SetXoffState 53
|
|
|
-#define FC_SetRxFIFOTrig 54
|
|
|
-#define FC_SetTxFIFOCnt 55
|
|
|
-#define FC_UnixRate 56
|
|
|
-#define FC_UnixResetTimer 57
|
|
|
-
|
|
|
-#define RxFIFOTrig1 0
|
|
|
-#define RxFIFOTrig4 1
|
|
|
-#define RxFIFOTrig8 2
|
|
|
-#define RxFIFOTrig14 3
|
|
|
-
|
|
|
-/*
|
|
|
- * Dual-Ported RAM
|
|
|
- */
|
|
|
-#define DRAM_global 0
|
|
|
-#define INT_data (DRAM_global + 0)
|
|
|
-#define Config_base (DRAM_global + 0x108)
|
|
|
-
|
|
|
-#define IRQindex (INT_data + 0)
|
|
|
-#define IRQpending (INT_data + 4)
|
|
|
-#define IRQtable (INT_data + 8)
|
|
|
-
|
|
|
-/*
|
|
|
- * Interrupt Status
|
|
|
- */
|
|
|
-#define IntrRx 0x01 /* receiver data O.K. */
|
|
|
-#define IntrTx 0x02 /* transmit buffer empty */
|
|
|
-#define IntrFunc 0x04 /* function complete */
|
|
|
-#define IntrBreak 0x08 /* received break */
|
|
|
-#define IntrLine 0x10 /* line status change
|
|
|
- for transmitter */
|
|
|
-#define IntrIntr 0x20 /* received INTR code */
|
|
|
-#define IntrQuit 0x40 /* received QUIT code */
|
|
|
-#define IntrEOF 0x80 /* received EOF code */
|
|
|
-
|
|
|
-#define IntrRxTrigger 0x100 /* rx data count reach tigger value */
|
|
|
-#define IntrTxTrigger 0x200 /* tx data count below trigger value */
|
|
|
-
|
|
|
-#define Magic_no (Config_base + 0)
|
|
|
-#define Card_model_no (Config_base + 2)
|
|
|
-#define Total_ports (Config_base + 4)
|
|
|
-#define Module_cnt (Config_base + 8)
|
|
|
-#define Module_no (Config_base + 10)
|
|
|
-#define Timer_10ms (Config_base + 14)
|
|
|
-#define Disable_IRQ (Config_base + 20)
|
|
|
-#define TMS320_PORT1 (Config_base + 22)
|
|
|
-#define TMS320_PORT2 (Config_base + 24)
|
|
|
-#define TMS320_CLOCK (Config_base + 26)
|
|
|
-
|
|
|
-/*
|
|
|
- * DATA BUFFER in DRAM
|
|
|
- */
|
|
|
-#define Extern_table 0x400 /* Base address of the external table
|
|
|
- (24 words * 64) total 3K bytes
|
|
|
- (24 words * 128) total 6K bytes */
|
|
|
-#define Extern_size 0x60 /* 96 bytes */
|
|
|
-#define RXrptr 0x00 /* read pointer for RX buffer */
|
|
|
-#define RXwptr 0x02 /* write pointer for RX buffer */
|
|
|
-#define TXrptr 0x04 /* read pointer for TX buffer */
|
|
|
-#define TXwptr 0x06 /* write pointer for TX buffer */
|
|
|
-#define HostStat 0x08 /* IRQ flag and general flag */
|
|
|
-#define FlagStat 0x0A
|
|
|
-#define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
|
|
|
- /* x x x x | | | | */
|
|
|
- /* | | | + CTS flow */
|
|
|
- /* | | +--- RTS flow */
|
|
|
- /* | +------ TX Xon/Xoff */
|
|
|
- /* +--------- RX Xon/Xoff */
|
|
|
-#define Break_cnt 0x0E /* received break count */
|
|
|
-#define CD180TXirq 0x10 /* if non-0: enable TX irq */
|
|
|
-#define RX_mask 0x12
|
|
|
-#define TX_mask 0x14
|
|
|
-#define Ofs_rxb 0x16
|
|
|
-#define Ofs_txb 0x18
|
|
|
-#define Page_rxb 0x1A
|
|
|
-#define Page_txb 0x1C
|
|
|
-#define EndPage_rxb 0x1E
|
|
|
-#define EndPage_txb 0x20
|
|
|
-#define Data_error 0x22
|
|
|
-#define RxTrigger 0x28
|
|
|
-#define TxTrigger 0x2a
|
|
|
-
|
|
|
-#define rRXwptr 0x34
|
|
|
-#define Low_water 0x36
|
|
|
-
|
|
|
-#define FuncCode 0x40
|
|
|
-#define FuncArg 0x42
|
|
|
-#define FuncArg1 0x44
|
|
|
-
|
|
|
-#define C218rx_size 0x2000 /* 8K bytes */
|
|
|
-#define C218tx_size 0x8000 /* 32K bytes */
|
|
|
-
|
|
|
-#define C218rx_mask (C218rx_size - 1)
|
|
|
-#define C218tx_mask (C218tx_size - 1)
|
|
|
-
|
|
|
-#define C320p8rx_size 0x2000
|
|
|
-#define C320p8tx_size 0x8000
|
|
|
-#define C320p8rx_mask (C320p8rx_size - 1)
|
|
|
-#define C320p8tx_mask (C320p8tx_size - 1)
|
|
|
-
|
|
|
-#define C320p16rx_size 0x2000
|
|
|
-#define C320p16tx_size 0x4000
|
|
|
-#define C320p16rx_mask (C320p16rx_size - 1)
|
|
|
-#define C320p16tx_mask (C320p16tx_size - 1)
|
|
|
-
|
|
|
-#define C320p24rx_size 0x2000
|
|
|
-#define C320p24tx_size 0x2000
|
|
|
-#define C320p24rx_mask (C320p24rx_size - 1)
|
|
|
-#define C320p24tx_mask (C320p24tx_size - 1)
|
|
|
-
|
|
|
-#define C320p32rx_size 0x1000
|
|
|
-#define C320p32tx_size 0x1000
|
|
|
-#define C320p32rx_mask (C320p32rx_size - 1)
|
|
|
-#define C320p32tx_mask (C320p32tx_size - 1)
|
|
|
-
|
|
|
-#define Page_size 0x2000
|
|
|
-#define Page_mask (Page_size - 1)
|
|
|
-#define C218rx_spage 3
|
|
|
-#define C218tx_spage 4
|
|
|
-#define C218rx_pageno 1
|
|
|
-#define C218tx_pageno 4
|
|
|
-#define C218buf_pageno 5
|
|
|
-
|
|
|
-#define C320p8rx_spage 3
|
|
|
-#define C320p8tx_spage 4
|
|
|
-#define C320p8rx_pgno 1
|
|
|
-#define C320p8tx_pgno 4
|
|
|
-#define C320p8buf_pgno 5
|
|
|
-
|
|
|
-#define C320p16rx_spage 3
|
|
|
-#define C320p16tx_spage 4
|
|
|
-#define C320p16rx_pgno 1
|
|
|
-#define C320p16tx_pgno 2
|
|
|
-#define C320p16buf_pgno 3
|
|
|
-
|
|
|
-#define C320p24rx_spage 3
|
|
|
-#define C320p24tx_spage 4
|
|
|
-#define C320p24rx_pgno 1
|
|
|
-#define C320p24tx_pgno 1
|
|
|
-#define C320p24buf_pgno 2
|
|
|
-
|
|
|
-#define C320p32rx_spage 3
|
|
|
-#define C320p32tx_ofs C320p32rx_size
|
|
|
-#define C320p32tx_spage 3
|
|
|
-#define C320p32buf_pgno 1
|
|
|
-
|
|
|
-/*
|
|
|
- * Host Status
|
|
|
- */
|
|
|
-#define WakeupRx 0x01
|
|
|
-#define WakeupTx 0x02
|
|
|
-#define WakeupBreak 0x08
|
|
|
-#define WakeupLine 0x10
|
|
|
-#define WakeupIntr 0x20
|
|
|
-#define WakeupQuit 0x40
|
|
|
-#define WakeupEOF 0x80 /* used in VTIME control */
|
|
|
-#define WakeupRxTrigger 0x100
|
|
|
-#define WakeupTxTrigger 0x200
|
|
|
-/*
|
|
|
- * Flag status
|
|
|
- */
|
|
|
-#define Rx_over 0x01
|
|
|
-#define Xoff_state 0x02
|
|
|
-#define Tx_flowOff 0x04
|
|
|
-#define Tx_enable 0x08
|
|
|
-#define CTS_state 0x10
|
|
|
-#define DSR_state 0x20
|
|
|
-#define DCD_state 0x80
|
|
|
-/*
|
|
|
- * FlowControl
|
|
|
- */
|
|
|
-#define CTS_FlowCtl 1
|
|
|
-#define RTS_FlowCtl 2
|
|
|
-#define Tx_FlowCtl 4
|
|
|
-#define Rx_FlowCtl 8
|
|
|
-#define IXM_IXANY 0x10
|
|
|
-
|
|
|
-#define LowWater 128
|
|
|
-
|
|
|
-#define DTR_ON 1
|
|
|
-#define RTS_ON 2
|
|
|
-#define CTS_ON 1
|
|
|
-#define DSR_ON 2
|
|
|
-#define DCD_ON 8
|
|
|
-
|
|
|
-/* mode definition */
|
|
|
-#define MX_CS8 0x03
|
|
|
-#define MX_CS7 0x02
|
|
|
-#define MX_CS6 0x01
|
|
|
-#define MX_CS5 0x00
|
|
|
-
|
|
|
-#define MX_STOP1 0x00
|
|
|
-#define MX_STOP15 0x04
|
|
|
-#define MX_STOP2 0x08
|
|
|
-
|
|
|
-#define MX_PARNONE 0x00
|
|
|
-#define MX_PAREVEN 0x40
|
|
|
-#define MX_PARODD 0xC0
|
|
|
+ if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
|
|
|
+ *****************************************************/
|
|
|
+ if (!tp || !ts) {
|
|
|
+ MoxaPortFlushData(ch->port, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ spin_lock_irqsave(&moxa_lock, flags);
|
|
|
+ MoxaPortReadData(ch->port, tp);
|
|
|
+ spin_unlock_irqrestore(&moxa_lock, flags);
|
|
|
+ tty_schedule_flip(tp);
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
* Query
|
|
@@ -1378,55 +1593,22 @@ struct mon_str {
|
|
|
#define DCD_changed 0x01
|
|
|
#define DCD_oldstate 0x80
|
|
|
|
|
|
-static unsigned char moxaBuff[10240];
|
|
|
static int moxaLowWaterChk;
|
|
|
-static int moxaCard;
|
|
|
static struct mon_str moxaLog;
|
|
|
static int moxaFuncTout = HZ / 2;
|
|
|
|
|
|
static void moxafunc(void __iomem *, int, ushort);
|
|
|
static void moxa_wait_finish(void __iomem *);
|
|
|
static void moxa_low_water_check(void __iomem *);
|
|
|
-static int moxaloadbios(int, unsigned char __user *, int);
|
|
|
-static int moxafindcard(int);
|
|
|
-static int moxaload320b(int, unsigned char __user *, int);
|
|
|
-static int moxaloadcode(int, unsigned char __user *, int);
|
|
|
-static int moxaloadc218(int, void __iomem *, int);
|
|
|
-static int moxaloadc320(int, void __iomem *, int, int *);
|
|
|
|
|
|
/*****************************************************************************
|
|
|
* Driver level functions: *
|
|
|
- * 1. MoxaDriverInit(void); *
|
|
|
* 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); *
|
|
|
* 3. MoxaDriverPoll(void); *
|
|
|
*****************************************************************************/
|
|
|
-void MoxaDriverInit(void)
|
|
|
-{
|
|
|
- struct moxa_port *p;
|
|
|
- unsigned int i;
|
|
|
-
|
|
|
- moxaFuncTout = HZ / 2; /* 500 mini-seconds */
|
|
|
- moxaCard = 0;
|
|
|
- moxaLog.tick = 0;
|
|
|
- moxaLowWaterChk = 0;
|
|
|
- for (i = 0; i < MAX_PORTS; i++) {
|
|
|
- p = &moxa_ports[i];
|
|
|
- p->chkPort = 0;
|
|
|
- p->lowChkFlag = 0;
|
|
|
- p->lineCtrl = 0;
|
|
|
- moxaLog.rxcnt[i] = 0;
|
|
|
- moxaLog.txcnt[i] = 0;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
#define MOXA 0x400
|
|
|
#define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */
|
|
|
#define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */
|
|
|
-#define MOXA_INIT_DRIVER (MOXA + 6) /* moxaCard=0 */
|
|
|
-#define MOXA_LOAD_BIOS (MOXA + 9) /* download BIOS */
|
|
|
-#define MOXA_FIND_BOARD (MOXA + 10) /* Check if MOXA card exist? */
|
|
|
-#define MOXA_LOAD_C320B (MOXA + 11) /* download 320B firmware */
|
|
|
-#define MOXA_LOAD_CODE (MOXA + 12) /* download firmware */
|
|
|
#define MOXA_GETDATACOUNT (MOXA + 23)
|
|
|
#define MOXA_GET_IOQUEUE (MOXA + 27)
|
|
|
#define MOXA_FLUSH_QUEUE (MOXA + 28)
|
|
@@ -1435,14 +1617,6 @@ void MoxaDriverInit(void)
|
|
|
#define MOXA_GET_CUMAJOR (MOXA + 64)
|
|
|
#define MOXA_GETMSTATUS (MOXA + 65)
|
|
|
|
|
|
-struct dl_str {
|
|
|
- char __user *buf;
|
|
|
- int len;
|
|
|
- int cardno;
|
|
|
-};
|
|
|
-
|
|
|
-static struct dl_str dltmp;
|
|
|
-
|
|
|
void MoxaPortFlushData(int port, int mode)
|
|
|
{
|
|
|
void __iomem *ofsAddr;
|
|
@@ -1464,23 +1638,12 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
|
|
|
void __user *argp = (void __user *)arg;
|
|
|
|
|
|
if (port == MAX_PORTS) {
|
|
|
- if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
|
|
|
- (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
|
|
|
- (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
|
|
|
- (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
|
|
|
+ if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_GETDATACOUNT) &&
|
|
|
+ (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
|
|
|
(cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
|
|
|
return (-EINVAL);
|
|
|
}
|
|
|
switch (cmd) {
|
|
|
- case MOXA_GET_CONF:
|
|
|
- if(copy_to_user(argp, &moxa_boards, MAX_BOARDS *
|
|
|
- sizeof(struct moxa_board_conf)))
|
|
|
- return -EFAULT;
|
|
|
- return (0);
|
|
|
- case MOXA_INIT_DRIVER:
|
|
|
- if ((int) arg == 0x404)
|
|
|
- MoxaDriverInit();
|
|
|
- return (0);
|
|
|
case MOXA_GETDATACOUNT:
|
|
|
moxaLog.tick = jiffies;
|
|
|
if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str)))
|
|
@@ -1547,40 +1710,10 @@ copy:
|
|
|
return -EFAULT;
|
|
|
}
|
|
|
return 0;
|
|
|
- } default:
|
|
|
- return (-ENOIOCTLCMD);
|
|
|
- case MOXA_LOAD_BIOS:
|
|
|
- case MOXA_FIND_BOARD:
|
|
|
- case MOXA_LOAD_C320B:
|
|
|
- case MOXA_LOAD_CODE:
|
|
|
- if (!capable(CAP_SYS_RAWIO))
|
|
|
- return -EPERM;
|
|
|
- break;
|
|
|
}
|
|
|
-
|
|
|
- if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
|
|
|
- return -EFAULT;
|
|
|
- if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- switch(cmd)
|
|
|
- {
|
|
|
- case MOXA_LOAD_BIOS:
|
|
|
- i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
|
|
|
- return (i);
|
|
|
- case MOXA_FIND_BOARD:
|
|
|
- return moxafindcard(dltmp.cardno);
|
|
|
- case MOXA_LOAD_C320B:
|
|
|
- moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
|
|
|
- default: /* to keep gcc happy */
|
|
|
- return (0);
|
|
|
- case MOXA_LOAD_CODE:
|
|
|
- i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
|
|
|
- if (i == -1)
|
|
|
- return (-EFAULT);
|
|
|
- return (i);
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
+ return -ENOIOCTLCMD;
|
|
|
}
|
|
|
|
|
|
int MoxaDriverPoll(void)
|
|
@@ -1935,7 +2068,6 @@ int MoxaPortsOfCard(int cardno)
|
|
|
*/
|
|
|
int MoxaPortIsValid(int port)
|
|
|
{
|
|
|
-
|
|
|
if (moxaCard == 0)
|
|
|
return (0);
|
|
|
if (moxa_ports[port].chkPort == 0)
|
|
@@ -2490,335 +2622,6 @@ static void moxa_low_water_check(void __iomem *ofsAddr)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
|
|
|
-{
|
|
|
- void __iomem *baseAddr;
|
|
|
- int i;
|
|
|
-
|
|
|
- if(len < 0 || len > sizeof(moxaBuff))
|
|
|
- return -EINVAL;
|
|
|
- if(copy_from_user(moxaBuff, tmp, len))
|
|
|
- return -EFAULT;
|
|
|
- baseAddr = moxa_boards[cardno].basemem;
|
|
|
- writeb(HW_reset, baseAddr + Control_reg); /* reset */
|
|
|
- msleep(10);
|
|
|
- for (i = 0; i < 4096; i++)
|
|
|
- writeb(0, baseAddr + i); /* clear fix page */
|
|
|
- for (i = 0; i < len; i++)
|
|
|
- writeb(moxaBuff[i], baseAddr + i); /* download BIOS */
|
|
|
- writeb(0, baseAddr + Control_reg); /* restart */
|
|
|
- return (0);
|
|
|
-}
|
|
|
-
|
|
|
-static int moxafindcard(int cardno)
|
|
|
-{
|
|
|
- void __iomem *baseAddr;
|
|
|
- ushort tmp;
|
|
|
-
|
|
|
- baseAddr = moxa_boards[cardno].basemem;
|
|
|
- switch (moxa_boards[cardno].boardType) {
|
|
|
- case MOXA_BOARD_C218_ISA:
|
|
|
- case MOXA_BOARD_C218_PCI:
|
|
|
- if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- break;
|
|
|
- case MOXA_BOARD_CP204J:
|
|
|
- if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
|
|
|
- return (-2);
|
|
|
- }
|
|
|
- }
|
|
|
- return (0);
|
|
|
-}
|
|
|
-
|
|
|
-static int moxaload320b(int cardno, unsigned char __user *tmp, int len)
|
|
|
-{
|
|
|
- void __iomem *baseAddr;
|
|
|
- int i;
|
|
|
-
|
|
|
- if(len < 0 || len > sizeof(moxaBuff))
|
|
|
- return -EINVAL;
|
|
|
- if(copy_from_user(moxaBuff, tmp, len))
|
|
|
- return -EFAULT;
|
|
|
- baseAddr = moxa_boards[cardno].basemem;
|
|
|
- writew(len - 7168 - 2, baseAddr + C320bapi_len);
|
|
|
- writeb(1, baseAddr + Control_reg); /* Select Page 1 */
|
|
|
- for (i = 0; i < 7168; i++)
|
|
|
- writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
|
|
|
- writeb(2, baseAddr + Control_reg); /* Select Page 2 */
|
|
|
- for (i = 0; i < (len - 7168); i++)
|
|
|
- writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
|
|
|
- return (0);
|
|
|
-}
|
|
|
-
|
|
|
-static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
|
|
|
-{
|
|
|
- void __iomem *baseAddr, *ofsAddr;
|
|
|
- int retval, port, i;
|
|
|
-
|
|
|
- if(len < 0 || len > sizeof(moxaBuff))
|
|
|
- return -EINVAL;
|
|
|
- if(copy_from_user(moxaBuff, tmp, len))
|
|
|
- return -EFAULT;
|
|
|
- baseAddr = moxa_boards[cardno].basemem;
|
|
|
- switch (moxa_boards[cardno].boardType) {
|
|
|
- case MOXA_BOARD_C218_ISA:
|
|
|
- case MOXA_BOARD_C218_PCI:
|
|
|
- case MOXA_BOARD_CP204J:
|
|
|
- retval = moxaloadc218(cardno, baseAddr, len);
|
|
|
- if (retval)
|
|
|
- return (retval);
|
|
|
- port = cardno * MAX_PORTS_PER_BOARD;
|
|
|
- for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
|
|
|
- struct moxa_port *p = &moxa_ports[port];
|
|
|
-
|
|
|
- p->chkPort = 1;
|
|
|
- p->curBaud = 9600L;
|
|
|
- p->DCDState = 0;
|
|
|
- p->tableAddr = baseAddr + Extern_table + Extern_size * i;
|
|
|
- ofsAddr = p->tableAddr;
|
|
|
- writew(C218rx_mask, ofsAddr + RX_mask);
|
|
|
- writew(C218tx_mask, ofsAddr + TX_mask);
|
|
|
- writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
|
|
|
- writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
|
|
|
-
|
|
|
- writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
|
|
|
- writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
|
|
|
-
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- retval = moxaloadc320(cardno, baseAddr, len,
|
|
|
- &moxa_boards[cardno].numPorts);
|
|
|
- if (retval)
|
|
|
- return (retval);
|
|
|
- port = cardno * MAX_PORTS_PER_BOARD;
|
|
|
- for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
|
|
|
- struct moxa_port *p = &moxa_ports[port];
|
|
|
-
|
|
|
- p->chkPort = 1;
|
|
|
- p->curBaud = 9600L;
|
|
|
- p->DCDState = 0;
|
|
|
- p->tableAddr = baseAddr + Extern_table + Extern_size * i;
|
|
|
- ofsAddr = p->tableAddr;
|
|
|
- if (moxa_boards[cardno].numPorts == 8) {
|
|
|
- writew(C320p8rx_mask, ofsAddr + RX_mask);
|
|
|
- writew(C320p8tx_mask, ofsAddr + TX_mask);
|
|
|
- writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
|
|
|
- writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
|
|
|
- writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
|
|
|
- writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
|
|
|
-
|
|
|
- } else if (moxa_boards[cardno].numPorts == 16) {
|
|
|
- writew(C320p16rx_mask, ofsAddr + RX_mask);
|
|
|
- writew(C320p16tx_mask, ofsAddr + TX_mask);
|
|
|
- writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
|
|
|
- writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
|
|
|
- writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
|
|
|
- writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
|
|
|
-
|
|
|
- } else if (moxa_boards[cardno].numPorts == 24) {
|
|
|
- writew(C320p24rx_mask, ofsAddr + RX_mask);
|
|
|
- writew(C320p24tx_mask, ofsAddr + TX_mask);
|
|
|
- writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
|
|
|
- writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
|
|
|
- writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
|
|
|
- writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
|
|
|
- } else if (moxa_boards[cardno].numPorts == 32) {
|
|
|
- writew(C320p32rx_mask, ofsAddr + RX_mask);
|
|
|
- writew(C320p32tx_mask, ofsAddr + TX_mask);
|
|
|
- writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
|
|
|
- writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
|
|
|
- writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
|
|
|
- writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
|
|
|
- writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- moxa_boards[cardno].loadstat = 1;
|
|
|
- return (0);
|
|
|
-}
|
|
|
-
|
|
|
-static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
|
|
|
-{
|
|
|
- char retry;
|
|
|
- int i, j, len1, len2;
|
|
|
- ushort usum, *ptr, keycode;
|
|
|
-
|
|
|
- if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
|
|
|
- keycode = CP204J_KeyCode;
|
|
|
- else
|
|
|
- keycode = C218_KeyCode;
|
|
|
- usum = 0;
|
|
|
- len1 = len >> 1;
|
|
|
- ptr = (ushort *) moxaBuff;
|
|
|
- for (i = 0; i < len1; i++)
|
|
|
- usum += le16_to_cpu(*(ptr + i));
|
|
|
- retry = 0;
|
|
|
- do {
|
|
|
- len1 = len >> 1;
|
|
|
- j = 0;
|
|
|
- while (len1) {
|
|
|
- len2 = (len1 > 2048) ? 2048 : len1;
|
|
|
- len1 -= len2;
|
|
|
- for (i = 0; i < len2 << 1; i++)
|
|
|
- writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
|
|
|
- j += i;
|
|
|
-
|
|
|
- writew(len2, baseAddr + C218DLoad_len);
|
|
|
- writew(0, baseAddr + C218_key);
|
|
|
- for (i = 0; i < 100; i++) {
|
|
|
- if (readw(baseAddr + C218_key) == keycode)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + C218_key) != keycode) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- }
|
|
|
- writew(0, baseAddr + C218DLoad_len);
|
|
|
- writew(usum, baseAddr + C218check_sum);
|
|
|
- writew(0, baseAddr + C218_key);
|
|
|
- for (i = 0; i < 100; i++) {
|
|
|
- if (readw(baseAddr + C218_key) == keycode)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- retry++;
|
|
|
- } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
|
|
|
- if (readb(baseAddr + C218chksum_ok) != 1) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- writew(0, baseAddr + C218_key);
|
|
|
- for (i = 0; i < 100; i++) {
|
|
|
- if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + Magic_no) != Magic_code) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- writew(1, baseAddr + Disable_IRQ);
|
|
|
- writew(0, baseAddr + Magic_no);
|
|
|
- for (i = 0; i < 100; i++) {
|
|
|
- if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + Magic_no) != Magic_code) {
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- moxaCard = 1;
|
|
|
- moxa_boards[cardno].intNdx = baseAddr + IRQindex;
|
|
|
- moxa_boards[cardno].intPend = baseAddr + IRQpending;
|
|
|
- moxa_boards[cardno].intTable = baseAddr + IRQtable;
|
|
|
- return (0);
|
|
|
-}
|
|
|
-
|
|
|
-static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts)
|
|
|
-{
|
|
|
- ushort usum;
|
|
|
- int i, j, wlen, len2, retry;
|
|
|
- ushort *uptr;
|
|
|
-
|
|
|
- usum = 0;
|
|
|
- wlen = len >> 1;
|
|
|
- uptr = (ushort *) moxaBuff;
|
|
|
- for (i = 0; i < wlen; i++)
|
|
|
- usum += le16_to_cpu(uptr[i]);
|
|
|
- retry = 0;
|
|
|
- j = 0;
|
|
|
- do {
|
|
|
- while (wlen) {
|
|
|
- if (wlen > 2048)
|
|
|
- len2 = 2048;
|
|
|
- else
|
|
|
- len2 = wlen;
|
|
|
- wlen -= len2;
|
|
|
- len2 <<= 1;
|
|
|
- for (i = 0; i < len2; i++)
|
|
|
- writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
|
|
|
- len2 >>= 1;
|
|
|
- j += i;
|
|
|
- writew(len2, baseAddr + C320DLoad_len);
|
|
|
- writew(0, baseAddr + C320_key);
|
|
|
- for (i = 0; i < 10; i++) {
|
|
|
- if (readw(baseAddr + C320_key) == C320_KeyCode)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + C320_key) != C320_KeyCode)
|
|
|
- return (-1);
|
|
|
- }
|
|
|
- writew(0, baseAddr + C320DLoad_len);
|
|
|
- writew(usum, baseAddr + C320check_sum);
|
|
|
- writew(0, baseAddr + C320_key);
|
|
|
- for (i = 0; i < 10; i++) {
|
|
|
- if (readw(baseAddr + C320_key) == C320_KeyCode)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- retry++;
|
|
|
- } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
|
|
|
- if (readb(baseAddr + C320chksum_ok) != 1)
|
|
|
- return (-1);
|
|
|
- writew(0, baseAddr + C320_key);
|
|
|
- for (i = 0; i < 600; i++) {
|
|
|
- if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
- return (-100);
|
|
|
-
|
|
|
- if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */
|
|
|
- writew(0x3800, baseAddr + TMS320_PORT1);
|
|
|
- writew(0x3900, baseAddr + TMS320_PORT2);
|
|
|
- writew(28499, baseAddr + TMS320_CLOCK);
|
|
|
- } else {
|
|
|
- writew(0x3200, baseAddr + TMS320_PORT1);
|
|
|
- writew(0x3400, baseAddr + TMS320_PORT2);
|
|
|
- writew(19999, baseAddr + TMS320_CLOCK);
|
|
|
- }
|
|
|
- writew(1, baseAddr + Disable_IRQ);
|
|
|
- writew(0, baseAddr + Magic_no);
|
|
|
- for (i = 0; i < 500; i++) {
|
|
|
- if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
- return (-102);
|
|
|
-
|
|
|
- j = readw(baseAddr + Module_cnt);
|
|
|
- if (j <= 0)
|
|
|
- return (-101);
|
|
|
- *numPorts = j * 8;
|
|
|
- writew(j, baseAddr + Module_no);
|
|
|
- writew(0, baseAddr + Magic_no);
|
|
|
- for (i = 0; i < 600; i++) {
|
|
|
- if (readw(baseAddr + Magic_no) == Magic_code)
|
|
|
- break;
|
|
|
- msleep(10);
|
|
|
- }
|
|
|
- if (readw(baseAddr + Magic_no) != Magic_code)
|
|
|
- return (-102);
|
|
|
- moxaCard = 1;
|
|
|
- moxa_boards[cardno].intNdx = baseAddr + IRQindex;
|
|
|
- moxa_boards[cardno].intPend = baseAddr + IRQpending;
|
|
|
- moxa_boards[cardno].intTable = baseAddr + IRQtable;
|
|
|
- return (0);
|
|
|
-}
|
|
|
-
|
|
|
static void MoxaSetFifo(int port, int enable)
|
|
|
{
|
|
|
void __iomem *ofsAddr = moxa_ports[port].tableAddr;
|