diff options
Diffstat (limited to 'drivers/staging/isdn')
43 files changed, 22739 insertions, 0 deletions
diff --git a/drivers/staging/isdn/Kconfig b/drivers/staging/isdn/Kconfig new file mode 100644 index 000000000000..faaf63887094 --- /dev/null +++ b/drivers/staging/isdn/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "ISDN CAPI drivers" + depends on ISDN_CAPI + +source "drivers/staging/isdn/avm/Kconfig" + +source "drivers/staging/isdn/gigaset/Kconfig" + +source "drivers/staging/isdn/hysdn/Kconfig" + +endmenu + diff --git a/drivers/staging/isdn/Makefile b/drivers/staging/isdn/Makefile new file mode 100644 index 000000000000..025504bae5df --- /dev/null +++ b/drivers/staging/isdn/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for the kernel ISDN subsystem and device drivers. + +# Object files in subdirectories + +obj-$(CONFIG_CAPI_AVM) += avm/ +obj-$(CONFIG_HYSDN) += hysdn/ +obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/ diff --git a/drivers/staging/isdn/TODO b/drivers/staging/isdn/TODO new file mode 100644 index 000000000000..9210d11eb68b --- /dev/null +++ b/drivers/staging/isdn/TODO @@ -0,0 +1,22 @@ +TODO: Remove in late 2019 unless there are users + + +I tried to find any indication of whether the capi drivers are +still in use, and have not found anything from a long time ago. + +With public ISDN networks almost completely shut down over the past 12 +months, there is very little you can actually do with this hardware. The +main remaining use case would be to connect ISDN voice phones to an +in-house installation with Asterisk or LCR, but anyone trying this in +turn seems to be using either the mISDN driver stack, or out-of-tree +drivers from the hardware vendors. + +I may of course have missed something, so I would suggest moving +these into drivers/staging/ just in case someone still uses one +of the three remaining in-kernel drivers (avm, hysdn, gigaset). + +If nobody complains, we can remove them entirely in six months, +or otherwise move the core code and any drivers that are still +needed back into drivers/isdn. + + Arnd Bergmann <arnd@arndb.de> diff --git a/drivers/staging/isdn/avm/Kconfig b/drivers/staging/isdn/avm/Kconfig new file mode 100644 index 000000000000..81483db067bb --- /dev/null +++ b/drivers/staging/isdn/avm/Kconfig @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# ISDN AVM drivers +# + +menuconfig CAPI_AVM + bool "Active AVM cards" + help + Enable support for AVM active ISDN cards. + +if CAPI_AVM + +config ISDN_DRV_AVMB1_B1ISA + tristate "AVM B1 ISA support" + depends on ISA + help + Enable support for the ISA version of the AVM B1 card. + +config ISDN_DRV_AVMB1_B1PCI + tristate "AVM B1 PCI support" + depends on PCI + help + Enable support for the PCI version of the AVM B1 card. + +config ISDN_DRV_AVMB1_B1PCIV4 + bool "AVM B1 PCI V4 support" + depends on ISDN_DRV_AVMB1_B1PCI + help + Enable support for the V4 version of AVM B1 PCI card. + +config ISDN_DRV_AVMB1_T1ISA + tristate "AVM T1/T1-B ISA support" + depends on ISA + help + Enable support for the AVM T1 T1B card. + Note: This is a PRI card and handle 30 B-channels. + +config ISDN_DRV_AVMB1_B1PCMCIA + tristate "AVM B1/M1/M2 PCMCIA support" + depends on PCMCIA + help + Enable support for the PCMCIA version of the AVM B1 card. + +config ISDN_DRV_AVMB1_AVM_CS + tristate "AVM B1/M1/M2 PCMCIA cs module" + depends on ISDN_DRV_AVMB1_B1PCMCIA + help + Enable the PCMCIA client driver for the AVM B1/M1/M2 + PCMCIA cards. + +config ISDN_DRV_AVMB1_T1PCI + tristate "AVM T1/T1-B PCI support" + depends on PCI + help + Enable support for the AVM T1 T1B card. + Note: This is a PRI card and handle 30 B-channels. + +config ISDN_DRV_AVMB1_C4 + tristate "AVM C4/C2 support" + depends on PCI + help + Enable support for the AVM C4/C2 PCI cards. + These cards handle 4/2 BRI ISDN lines (8/4 channels). + +endif # CAPI_AVM diff --git a/drivers/staging/isdn/avm/Makefile b/drivers/staging/isdn/avm/Makefile new file mode 100644 index 000000000000..3830a0573fcc --- /dev/null +++ b/drivers/staging/isdn/avm/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for the AVM ISDN device drivers + +# Each configuration option enables a list of files. + +obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o +obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o +obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o +obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o +obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o +obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o +obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o diff --git a/drivers/staging/isdn/avm/avm_cs.c b/drivers/staging/isdn/avm/avm_cs.c new file mode 100644 index 000000000000..62b8030ee331 --- /dev/null +++ b/drivers/staging/isdn/avm/avm_cs.c @@ -0,0 +1,166 @@ +/* $Id: avm_cs.c,v 1.4.6.3 2001/09/23 22:24:33 kai Exp $ + * + * A PCMCIA client driver for AVM B1/M1/M2 + * + * Copyright 1999 by Carsten Paeth <calle@calle.de> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ptrace.h> +#include <linux/string.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/major.h> +#include <asm/io.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/ciscode.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> + +#include <linux/skbuff.h> +#include <linux/capi.h> +#include <linux/b1lli.h> +#include <linux/b1pcmcia.h> + +/*====================================================================*/ + +MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2"); +MODULE_AUTHOR("Carsten Paeth"); +MODULE_LICENSE("GPL"); + +/*====================================================================*/ + +static int avmcs_config(struct pcmcia_device *link); +static void avmcs_release(struct pcmcia_device *link); +static void avmcs_detach(struct pcmcia_device *p_dev); + +static int avmcs_probe(struct pcmcia_device *p_dev) +{ + /* General socket configuration */ + p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + p_dev->config_index = 1; + p_dev->config_regs = PRESENT_OPTION; + + return avmcs_config(p_dev); +} /* avmcs_attach */ + + +static void avmcs_detach(struct pcmcia_device *link) +{ + avmcs_release(link); +} /* avmcs_detach */ + +static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data) +{ + p_dev->resource[0]->end = 16; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + + return pcmcia_request_io(p_dev); +} + +static int avmcs_config(struct pcmcia_device *link) +{ + int i = -1; + char devname[128]; + int cardtype; + int (*addcard)(unsigned int port, unsigned irq); + + devname[0] = 0; + if (link->prod_id[1]) + strlcpy(devname, link->prod_id[1], sizeof(devname)); + + /* + * find IO port + */ + if (pcmcia_loop_config(link, avmcs_configcheck, NULL)) + return -ENODEV; + + do { + if (!link->irq) { + /* undo */ + pcmcia_disable_device(link); + break; + } + + /* + * configure the PCMCIA socket + */ + i = pcmcia_enable_device(link); + if (i != 0) { + pcmcia_disable_device(link); + break; + } + + } while (0); + + if (devname[0]) { + char *s = strrchr(devname, ' '); + if (!s) + s = devname; + else s++; + if (strcmp("M1", s) == 0) { + cardtype = AVM_CARDTYPE_M1; + } else if (strcmp("M2", s) == 0) { + cardtype = AVM_CARDTYPE_M2; + } else { + cardtype = AVM_CARDTYPE_B1; + } + } else + cardtype = AVM_CARDTYPE_B1; + + /* If any step failed, release any partially configured state */ + if (i != 0) { + avmcs_release(link); + return -ENODEV; + } + + + switch (cardtype) { + case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; + case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; + default: + case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; + } + if ((i = (*addcard)(link->resource[0]->start, link->irq)) < 0) { + dev_err(&link->dev, + "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n", + (unsigned int) link->resource[0]->start, link->irq); + avmcs_release(link); + return -ENODEV; + } + return 0; + +} /* avmcs_config */ + + +static void avmcs_release(struct pcmcia_device *link) +{ + b1pcmcia_delcard(link->resource[0]->start, link->irq); + pcmcia_disable_device(link); +} /* avmcs_release */ + + +static const struct pcmcia_device_id avmcs_ids[] = { + PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), + PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430), + PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); + +static struct pcmcia_driver avmcs_driver = { + .owner = THIS_MODULE, + .name = "avm_cs", + .probe = avmcs_probe, + .remove = avmcs_detach, + .id_table = avmcs_ids, +}; +module_pcmcia_driver(avmcs_driver); diff --git a/drivers/staging/isdn/avm/avmcard.h b/drivers/staging/isdn/avm/avmcard.h new file mode 100644 index 000000000000..cdfa89c71997 --- /dev/null +++ b/drivers/staging/isdn/avm/avmcard.h @@ -0,0 +1,581 @@ +/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ + * + * Copyright 1999 by Carsten Paeth <calle@calle.de> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#ifndef _AVMCARD_H_ +#define _AVMCARD_H_ + +#include <linux/spinlock.h> +#include <linux/list.h> +#include <linux/interrupt.h> + +#define AVMB1_PORTLEN 0x1f +#define AVM_MAXVERSION 8 +#define AVM_NCCI_PER_CHANNEL 4 + +/* + * Versions + */ + +#define VER_DRIVER 0 +#define VER_CARDTYPE 1 +#define VER_HWID 2 +#define VER_SERIAL 3 +#define VER_OPTION 4 +#define VER_PROTO 5 +#define VER_PROFILE 6 +#define VER_CAPI 7 + +enum avmcardtype { + avm_b1isa, + avm_b1pci, + avm_b1pcmcia, + avm_m1, + avm_m2, + avm_t1isa, + avm_t1pci, + avm_c4, + avm_c2 +}; + +typedef struct avmcard_dmabuf { + long size; + u8 *dmabuf; + dma_addr_t dmaaddr; +} avmcard_dmabuf; + +typedef struct avmcard_dmainfo { + u32 recvlen; + avmcard_dmabuf recvbuf; + + avmcard_dmabuf sendbuf; + struct sk_buff_head send_queue; + + struct pci_dev *pcidev; +} avmcard_dmainfo; + +typedef struct avmctrl_info { + char cardname[32]; + + int versionlen; + char versionbuf[1024]; + char *version[AVM_MAXVERSION]; + + char infobuf[128]; /* for function procinfo */ + + struct avmcard *card; + struct capi_ctr capi_ctrl; + + struct list_head ncci_head; +} avmctrl_info; + +typedef struct avmcard { + char name[32]; + + spinlock_t lock; + unsigned int port; + unsigned irq; + unsigned long membase; + enum avmcardtype cardtype; + unsigned char revision; + unsigned char class; + int cardnr; /* for t1isa */ + + char msgbuf[128]; /* capimsg msg part */ + char databuf[2048]; /* capimsg data part */ + + void __iomem *mbase; + volatile u32 csr; + avmcard_dmainfo *dma; + + struct avmctrl_info *ctrlinfo; + + u_int nr_controllers; + u_int nlogcontr; + struct list_head list; +} avmcard; + +extern int b1_irq_table[16]; + +/* + * LLI Messages to the ISDN-ControllerISDN Controller + */ + +#define SEND_POLL 0x72 /* + * after load <- RECEIVE_POLL + */ +#define SEND_INIT 0x11 /* + * first message <- RECEIVE_INIT + * int32 NumApplications int32 + * NumNCCIs int32 BoardNumber + */ +#define SEND_REGISTER 0x12 /* + * register an application int32 + * ApplIDId int32 NumMessages + * int32 NumB3Connections int32 + * NumB3Blocks int32 B3Size + * + * AnzB3Connection != 0 && + * AnzB3Blocks >= 1 && B3Size >= 1 + */ +#define SEND_RELEASE 0x14 /* + * deregister an application int32 + * ApplID + */ +#define SEND_MESSAGE 0x15 /* + * send capi-message int32 length + * capi-data ... + */ +#define SEND_DATA_B3_REQ 0x13 /* + * send capi-data-message int32 + * MsgLength capi-data ... int32 + * B3Length data .... + */ + +#define SEND_CONFIG 0x21 /* + */ + +#define SEND_POLLACK 0x73 /* T1 Watchdog */ + +/* + * LLI Messages from the ISDN-ControllerISDN Controller + */ + +#define RECEIVE_POLL 0x32 /* + * <- after SEND_POLL + */ +#define RECEIVE_INIT 0x27 /* + * <- after SEND_INIT int32 length + * byte total length b1struct board + * driver revision b1struct card + * type b1struct reserved b1struct + * serial number b1struct driver + * capability b1struct d-channel + * protocol b1struct CAPI-2.0 + * profile b1struct capi version + */ +#define RECEIVE_MESSAGE 0x21 /* + * <- after SEND_MESSAGE int32 + * AppllID int32 Length capi-data + * .... + */ +#define RECEIVE_DATA_B3_IND 0x22 /* + * received data int32 AppllID + * int32 Length capi-data ... + * int32 B3Length data ... + */ +#define RECEIVE_START 0x23 /* + * Handshake + */ +#define RECEIVE_STOP 0x24 /* + * Handshake + */ +#define RECEIVE_NEW_NCCI 0x25 /* + * int32 AppllID int32 NCCI int32 + * WindowSize + */ +#define RECEIVE_FREE_NCCI 0x26 /* + * int32 AppllID int32 NCCI + */ +#define RECEIVE_RELEASE 0x26 /* + * int32 AppllID int32 0xffffffff + */ +#define RECEIVE_TASK_READY 0x31 /* + * int32 tasknr + * int32 Length Taskname ... + */ +#define RECEIVE_DEBUGMSG 0x71 /* + * int32 Length message + * + */ +#define RECEIVE_POLLDWORD 0x75 /* t1pci in dword mode */ + +#define WRITE_REGISTER 0x00 +#define READ_REGISTER 0x01 + +/* + * port offsets + */ + +#define B1_READ 0x00 +#define B1_WRITE 0x01 +#define B1_INSTAT 0x02 +#define B1_OUTSTAT 0x03 +#define B1_ANALYSE 0x04 +#define B1_REVISION 0x05 +#define B1_RESET 0x10 + + +#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l) +#define B1_STAT1(cardtype) (0x80E00000l) + +/* ---------------------------------------------------------------- */ + +static inline unsigned char b1outp(unsigned int base, + unsigned short offset, + unsigned char value) +{ + outb(value, base + offset); + return inb(base + B1_ANALYSE); +} + + +static inline int b1_rx_full(unsigned int base) +{ + return inb(base + B1_INSTAT) & 0x1; +} + +static inline unsigned char b1_get_byte(unsigned int base) +{ + unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ + while (!b1_rx_full(base) && time_before(jiffies, stop)); + if (b1_rx_full(base)) + return inb(base + B1_READ); + printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base); + return 0; +} + +static inline unsigned int b1_get_word(unsigned int base) +{ + unsigned int val = 0; + val |= b1_get_byte(base); + val |= (b1_get_byte(base) << 8); + val |= (b1_get_byte(base) << 16); + val |= (b1_get_byte(base) << 24); + return val; +} + +static inline int b1_tx_empty(unsigned int base) +{ + return inb(base + B1_OUTSTAT) & 0x1; +} + +static inline void b1_put_byte(unsigned int base, unsigned char val) +{ + while (!b1_tx_empty(base)); + b1outp(base, B1_WRITE, val); +} + +static inline int b1_save_put_byte(unsigned int base, unsigned char val) +{ + unsigned long stop = jiffies + 2 * HZ; + while (!b1_tx_empty(base) && time_before(jiffies, stop)); + if (!b1_tx_empty(base)) return -1; + b1outp(base, B1_WRITE, val); + return 0; +} + +static inline void b1_put_word(unsigned int base, unsigned int val) +{ + b1_put_byte(base, val & 0xff); + b1_put_byte(base, (val >> 8) & 0xff); + b1_put_byte(base, (val >> 16) & 0xff); + b1_put_byte(base, (val >> 24) & 0xff); +} + +static inline unsigned int b1_get_slice(unsigned int base, + unsigned char *dp) +{ + unsigned int len, i; + + len = i = b1_get_word(base); + while (i-- > 0) *dp++ = b1_get_byte(base); + return len; +} + +static inline void b1_put_slice(unsigned int base, + unsigned char *dp, unsigned int len) +{ + unsigned i = len; + b1_put_word(base, i); + while (i-- > 0) + b1_put_byte(base, *dp++); +} + +static void b1_wr_reg(unsigned int base, + unsigned int reg, + unsigned int value) +{ + b1_put_byte(base, WRITE_REGISTER); + b1_put_word(base, reg); + b1_put_word(base, value); +} + +static inline unsigned int b1_rd_reg(unsigned int base, + unsigned int reg) +{ + b1_put_byte(base, READ_REGISTER); + b1_put_word(base, reg); + return b1_get_word(base); + +} + +static inline void b1_reset(unsigned int base) +{ + b1outp(base, B1_RESET, 0); + mdelay(55 * 2); /* 2 TIC's */ + + b1outp(base, B1_RESET, 1); + mdelay(55 * 2); /* 2 TIC's */ + + b1outp(base, B1_RESET, 0); + mdelay(55 * 2); /* 2 TIC's */ +} + +static inline unsigned char b1_disable_irq(unsigned int base) +{ + return b1outp(base, B1_INSTAT, 0x00); +} + +/* ---------------------------------------------------------------- */ + +static inline void b1_set_test_bit(unsigned int base, + enum avmcardtype cardtype, + int onoff) +{ + b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); +} + +static inline int b1_get_test_bit(unsigned int base, + enum avmcardtype cardtype) +{ + return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; +} + +/* ---------------------------------------------------------------- */ + +#define T1_FASTLINK 0x00 +#define T1_SLOWLINK 0x08 + +#define T1_READ B1_READ +#define T1_WRITE B1_WRITE +#define T1_INSTAT B1_INSTAT +#define T1_OUTSTAT B1_OUTSTAT +#define T1_IRQENABLE 0x05 +#define T1_FIFOSTAT 0x06 +#define T1_RESETLINK 0x10 +#define T1_ANALYSE 0x11 +#define T1_IRQMASTER 0x12 +#define T1_IDENT 0x17 +#define T1_RESETBOARD 0x1f + +#define T1F_IREADY 0x01 +#define T1F_IHALF 0x02 +#define T1F_IFULL 0x04 +#define T1F_IEMPTY 0x08 +#define T1F_IFLAGS 0xF0 + +#define T1F_OREADY 0x10 +#define T1F_OHALF 0x20 +#define T1F_OEMPTY 0x40 +#define T1F_OFULL 0x80 +#define T1F_OFLAGS 0xF0 + +/* there are HEMA cards with 1k and 4k FIFO out */ +#define FIFO_OUTBSIZE 256 +#define FIFO_INPBSIZE 512 + +#define HEMA_VERSION_ID 0 +#define HEMA_PAL_ID 0 + +static inline void t1outp(unsigned int base, + unsigned short offset, + unsigned char value) +{ + outb(value, base + offset); +} + +static inline unsigned char t1inp(unsigned int base, + unsigned short offset) +{ + return inb(base + offset); +} + +static inline int t1_isfastlink(unsigned int base) +{ + return (inb(base + T1_IDENT) & ~0x82) == 1; +} + +static inline unsigned char t1_fifostatus(unsigned int base) +{ + return inb(base + T1_FIFOSTAT); +} + +static inline unsigned int t1_get_slice(unsigned int base, + unsigned char *dp) +{ + unsigned int len, i; +#ifdef FASTLINK_DEBUG + unsigned wcnt = 0, bcnt = 0; +#endif + + len = i = b1_get_word(base); + if (t1_isfastlink(base)) { + int status; + while (i > 0) { + status = t1_fifostatus(base) & (T1F_IREADY | T1F_IHALF); + if (i >= FIFO_INPBSIZE) status |= T1F_IFULL; + + switch (status) { + case T1F_IREADY | T1F_IHALF | T1F_IFULL: + insb(base + B1_READ, dp, FIFO_INPBSIZE); + dp += FIFO_INPBSIZE; + i -= FIFO_INPBSIZE; +#ifdef FASTLINK_DEBUG + wcnt += FIFO_INPBSIZE; +#endif + break; + case T1F_IREADY | T1F_IHALF: + insb(base + B1_READ, dp, i); +#ifdef FASTLINK_DEBUG + wcnt += i; +#endif + dp += i; + i = 0; + break; + default: + *dp++ = b1_get_byte(base); + i--; +#ifdef FASTLINK_DEBUG + bcnt++; +#endif + break; + } + } +#ifdef FASTLINK_DEBUG + if (wcnt) + printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n", + base, len, wcnt, bcnt); +#endif + } else { + while (i-- > 0) + *dp++ = b1_get_byte(base); + } + return len; +} + +static inline void t1_put_slice(unsigned int base, + unsigned char *dp, unsigned int len) +{ + unsigned i = len; + b1_put_word(base, i); + if (t1_isfastlink(base)) { + int status; + while (i > 0) { + status = t1_fifostatus(base) & (T1F_OREADY | T1F_OHALF); + if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY; + switch (status) { + case T1F_OREADY | T1F_OHALF | T1F_OEMPTY: + outsb(base + B1_WRITE, dp, FIFO_OUTBSIZE); + dp += FIFO_OUTBSIZE; + i -= FIFO_OUTBSIZE; + break; + case T1F_OREADY | T1F_OHALF: + outsb(base + B1_WRITE, dp, i); + dp += i; + i = 0; + break; + default: + b1_put_byte(base, *dp++); + i--; + break; + } + } + } else { + while (i-- > 0) + b1_put_byte(base, *dp++); + } +} + +static inline void t1_disable_irq(unsigned int base) +{ + t1outp(base, T1_IRQMASTER, 0x00); +} + +static inline void t1_reset(unsigned int base) +{ + /* reset T1 Controller */ + b1_reset(base); + |