^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* $Id: cosa.c,v 1.31 2000/03/08 17:47:16 kas Exp $ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * The driver for the SRP and COSA synchronous serial cards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * HARDWARE INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Both cards are developed at the Institute of Computer Science,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Masaryk University (https://www.ics.muni.cz/). The hardware is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * developed by Jiri Novotny <novotny@ics.muni.cz>. More information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * and the photo of both cards is available at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * http://www.pavoucek.cz/cosa.html. The card documentation, firmwares
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * For Linux-specific utilities, see below in the "Software info" section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * If you want to order the card, contact Jiri Novotny.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The SRP (serial port?, the Czech word "srp" means "sickle") card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * is a 2-port intelligent (with its own 8-bit CPU) synchronous serial card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * with V.24 interfaces up to 80kb/s each.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * The COSA (communication serial adapter?, the Czech word "kosa" means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * "scythe") is a next-generation sync/async board with two interfaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * - currently any of V.24, X.21, V.35 and V.36 can be selected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * It has a 16-bit SAB80166 CPU and can do up to 10 Mb/s per channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * The 8-channels version is in development.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * Both types have downloadable firmware and communicate via ISA DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * COSA can be also a bus-mastering device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * SOFTWARE INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * The homepage of the Linux driver is at https://www.fi.muni.cz/~kas/cosa/.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * The CVS tree of Linux driver can be viewed there, as well as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * firmware binaries and user-space utilities for downloading the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * into the card and setting up the card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * The Linux driver (unlike the present *BSD drivers :-) can work even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * for the COSA and SRP in one computer and allows each channel to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * in one of the two modes (character or network device).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * AUTHOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * The Linux driver was written by Jan "Yenya" Kasprzak <kas@fi.muni.cz>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * You can mail me bugfixes and even success reports. I am especially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * interested in the SMP and/or muliti-channel success/failure reports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * (I wonder if I did the locking properly :-).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * THE AUTHOR USED THE FOLLOWING SOURCES WHEN PROGRAMMING THE DRIVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * The COSA/SRP NetBSD driver by Zdenek Salvet and Ivos Cernohlavek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * The skeleton.c by Donald Becker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * The SDL Riscom/N2 driver by Mike Natale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * The Comtrol Hostess SV11 driver by Alan Cox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <linux/hdlc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #undef COSA_SLOW_IO /* for testing purposes only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #include "cosa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Maximum length of the identification string. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define COSA_MAX_ID_STRING 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Maximum length of the channel name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define COSA_MAX_NAME (sizeof("cosaXXXcXXX")+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* Per-channel data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct channel_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int usage; /* Usage count; >0 for chrdev, -1 for netdev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int num; /* Number of the channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct cosa_data *cosa; /* Pointer to the per-card structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int txsize; /* Size of transmitted data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) char *txbuf; /* Transmit buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) char name[COSA_MAX_NAME]; /* channel name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* The HW layer interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* routine called from the RX interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) char *(*setup_rx)(struct channel_data *channel, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* routine called when the RX is done (from the EOT interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int (*rx_done)(struct channel_data *channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* routine called when the TX is done (from the EOT interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int (*tx_done)(struct channel_data *channel, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Character device parts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct mutex rlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct semaphore wsem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) char *rxdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int rxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) wait_queue_head_t txwaitq, rxwaitq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int tx_status, rx_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* generic HDLC device parts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct net_device *netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct sk_buff *rx_skb, *tx_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* cosa->firmware_status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define COSA_FW_RESET (1<<0) /* Is the ROM monitor active? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define COSA_FW_DOWNLOAD (1<<1) /* Is the microcode downloaded? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define COSA_FW_START (1<<2) /* Is the microcode running? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct cosa_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int num; /* Card number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) char name[COSA_MAX_NAME]; /* Card name - e.g "cosa0" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned int datareg, statusreg; /* I/O ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned short irq, dma; /* IRQ and DMA number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned short startaddr; /* Firmware start address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned short busmaster; /* Use busmastering? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int nchannels; /* # of channels on this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int driver_status; /* For communicating with firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int firmware_status; /* Downloaded, reseted, etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned long rxbitmap, txbitmap;/* Bitmap of channels who are willing to send/receive data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned long rxtx; /* RX or TX in progress? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int usage; /* usage count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int txchan, txsize, rxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct channel_data *rxchan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) char *bouncebuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) char *txbuf, *rxbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct channel_data *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) spinlock_t lock; /* For exclusive operations on this structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) char id_string[COSA_MAX_ID_STRING]; /* ROM monitor ID string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) char *type; /* card type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * Define this if you want all the possible ports to be autoprobed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * It is here but it probably is not a good idea to use this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* #define COSA_ISA_AUTOPROBE 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Character device major number. 117 was allocated for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * The value of 0 means to allocate a first free one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static DEFINE_MUTEX(cosa_chardev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int cosa_major = 117;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Encoding of the minor numbers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * The lowest CARD_MINOR_BITS bits means the channel on the single card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * the highest bits means the card number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define CARD_MINOR_BITS 4 /* How many bits in minor number are reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * for the single card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * The following depends on CARD_MINOR_BITS. Unfortunately, the "MODULE_STRING"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * macro doesn't like anything other than the raw number as an argument :-(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define MAX_CARDS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* #define MAX_CARDS (1 << (8-CARD_MINOR_BITS)) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define DRIVER_RX_READY 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define DRIVER_TX_READY 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define DRIVER_TXMAP_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define DRIVER_TXMAP_MASK 0x0c /* FIXME: 0xfc for 8-channel version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * for cosa->rxtx - indicates whether either transmit or receive is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * in progress. These values are mean number of the bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define TXBIT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define RXBIT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define IRQBIT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define COSA_MTU 2000 /* FIXME: I don't know this exactly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #undef DEBUG_DATA //1 /* Dump the data read or written to the channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #undef DEBUG_IRQS //1 /* Print the message when the IRQ is received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #undef DEBUG_IO //1 /* Dump the I/O traffic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define TX_TIMEOUT (5*HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* Maybe the following should be allocated dynamically */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static struct cosa_data cosa_cards[MAX_CARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int nr_cards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #ifdef COSA_ISA_AUTOPROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int io[MAX_CARDS+1] = { 0x220, 0x228, 0x210, 0x218, 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* NOTE: DMA is not autoprobed!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int dma[MAX_CARDS+1] = { 1, 7, 1, 7, 1, 7, 1, 7, 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int io[MAX_CARDS+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int dma[MAX_CARDS+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* IRQ can be safely autoprobed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* for class stuff*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static struct class *cosa_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) module_param_hw_array(io, int, ioport, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) MODULE_PARM_DESC(io, "The I/O bases of the COSA or SRP cards");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) module_param_hw_array(irq, int, irq, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) MODULE_PARM_DESC(irq, "The IRQ lines of the COSA or SRP cards");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) module_param_hw_array(dma, int, dma, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) MODULE_PARM_DESC(dma, "The DMA channels of the COSA or SRP cards");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, <kas@fi.muni.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) MODULE_DESCRIPTION("Modular driver for the COSA or SRP synchronous card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* I use this mainly for testing purposes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #ifdef COSA_SLOW_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define cosa_outb outb_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #define cosa_outw outw_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #define cosa_inb inb_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #define cosa_inw inw_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define cosa_outb outb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define cosa_outw outw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define cosa_inb inb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define cosa_inw inw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define is_8bit(cosa) (!(cosa->datareg & 0x08))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define cosa_getstatus(cosa) (cosa_inb(cosa->statusreg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #define cosa_putstatus(cosa, stat) (cosa_outb(stat, cosa->statusreg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #define cosa_getdata16(cosa) (cosa_inw(cosa->datareg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #define cosa_getdata8(cosa) (cosa_inb(cosa->datareg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #define cosa_putdata16(cosa, dt) (cosa_outw(dt, cosa->datareg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define cosa_putdata8(cosa, dt) (cosa_outb(dt, cosa->datareg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Initialization stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int cosa_probe(int ioaddr, int irq, int dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* HW interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void cosa_enable_rx(struct channel_data *chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static void cosa_disable_rx(struct channel_data *chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static int cosa_start_tx(struct channel_data *channel, char *buf, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static void cosa_kick(struct cosa_data *cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int cosa_dma_able(struct channel_data *chan, char *buf, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* Network device stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int cosa_net_attach(struct net_device *dev, unsigned short encoding,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned short parity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int cosa_net_open(struct net_device *d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static int cosa_net_close(struct net_device *d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void cosa_net_timeout(struct net_device *d, unsigned int txqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static netdev_tx_t cosa_net_tx(struct sk_buff *skb, struct net_device *d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static char *cosa_net_setup_rx(struct channel_data *channel, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int cosa_net_rx_done(struct channel_data *channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int cosa_net_tx_done(struct channel_data *channel, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Character device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static char *chrdev_setup_rx(struct channel_data *channel, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int chrdev_rx_done(struct channel_data *channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int chrdev_tx_done(struct channel_data *channel, int size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static ssize_t cosa_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) char __user *buf, size_t count, loff_t *ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static ssize_t cosa_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) const char __user *buf, size_t count, loff_t *ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static unsigned int cosa_poll(struct file *file, poll_table *poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int cosa_open(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int cosa_release(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static long cosa_chardev_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #ifdef COSA_FASYNC_WORKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int cosa_fasync(struct inode *inode, struct file *file, int on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static const struct file_operations cosa_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .read = cosa_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .write = cosa_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .poll = cosa_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .unlocked_ioctl = cosa_chardev_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .open = cosa_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .release = cosa_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #ifdef COSA_FASYNC_WORKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .fasync = cosa_fasync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* Ioctls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int cosa_start(struct cosa_data *cosa, int address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int cosa_reset(struct cosa_data *cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int cosa_download(struct cosa_data *cosa, void __user *a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int cosa_readmem(struct cosa_data *cosa, void __user *a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* COSA/SRP ROM monitor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int download(struct cosa_data *cosa, const char __user *data, int addr, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int startmicrocode(struct cosa_data *cosa, int address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* Auxiliary functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int get_wait_data(struct cosa_data *cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static int put_wait_data(struct cosa_data *cosa, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static int puthexnumber(struct cosa_data *cosa, int number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static void put_driver_status(struct cosa_data *cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static void put_driver_status_nolock(struct cosa_data *cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* Interrupt handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static irqreturn_t cosa_interrupt(int irq, void *cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* I/O ops debugging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void debug_data_in(struct cosa_data *cosa, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void debug_data_out(struct cosa_data *cosa, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void debug_data_cmd(struct cosa_data *cosa, int data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static void debug_status_in(struct cosa_data *cosa, int status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static void debug_status_out(struct cosa_data *cosa, int status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static inline struct channel_data* dev_to_chan(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return (struct channel_data *)dev_to_hdlc(dev)->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* ---------- Initialization stuff ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int __init cosa_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (cosa_major > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) pr_warn("unable to get major %d\n", cosa_major);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pr_warn("unable to register chardev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (i=0; i<MAX_CARDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) cosa_cards[i].num = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) cosa_probe(io[i], irq[i], dma[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!nr_cards) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) pr_warn("no devices found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unregister_chrdev(cosa_major, "cosa");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) cosa_class = class_create(THIS_MODULE, "cosa");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (IS_ERR(cosa_class)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) err = PTR_ERR(cosa_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) goto out_chrdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) for (i = 0; i < nr_cards; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) device_create(cosa_class, NULL, MKDEV(cosa_major, i), NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) "cosa%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) out_chrdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) unregister_chrdev(cosa_major, "cosa");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) module_init(cosa_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static void __exit cosa_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct cosa_data *cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) for (i = 0; i < nr_cards; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) device_destroy(cosa_class, MKDEV(cosa_major, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) class_destroy(cosa_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) for (cosa = cosa_cards; nr_cards--; cosa++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Clean up the per-channel data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) for (i = 0; i < cosa->nchannels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Chardev driver has no alloc'd per-channel data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) unregister_hdlc_device(cosa->chan[i].netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) free_netdev(cosa->chan[i].netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* Clean up the per-card data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) kfree(cosa->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) kfree(cosa->bouncebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) free_irq(cosa->irq, cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) free_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) release_region(cosa->datareg, is_8bit(cosa) ? 2 : 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) unregister_chrdev(cosa_major, "cosa");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) module_exit(cosa_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static const struct net_device_ops cosa_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .ndo_open = cosa_net_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .ndo_stop = cosa_net_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .ndo_start_xmit = hdlc_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .ndo_do_ioctl = cosa_net_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .ndo_tx_timeout = cosa_net_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int cosa_probe(int base, int irq, int dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct cosa_data *cosa = cosa_cards+nr_cards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) memset(cosa, 0, sizeof(struct cosa_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* Checking validity of parameters: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) pr_info("invalid IRQ %d\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* I/O address should be between 0x100 and 0x3ff and should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * multiple of 8. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (base < 0x100 || base > 0x3ff || base & 0x7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pr_info("invalid I/O address 0x%x\n", base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* DMA should be 0,1 or 3-7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (dma < 0 || dma == 4 || dma > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) pr_info("invalid DMA %d\n", dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* and finally, on 16-bit COSA DMA should be 4-7 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * I/O base should not be multiple of 0x10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) base, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) cosa->dma = dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) cosa->datareg = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) cosa->statusreg = is_8bit(cosa)?base+1:base+2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) spin_lock_init(&cosa->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!request_region(base, is_8bit(cosa)?2:4,"cosa"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) printk(KERN_DEBUG "probe at 0x%x failed.\n", base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* Test the validity of identification string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!strncmp(cosa->id_string, "SRP", 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) cosa->type = "srp";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) else if (!strncmp(cosa->id_string, "COSA", 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) cosa->type = is_8bit(cosa)? "cosa8": "cosa16";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* Print a warning only if we are not autoprobing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) #ifndef COSA_ISA_AUTOPROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pr_info("valid signature not found at 0x%x\n", base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* Update the name of the region now we know the type of card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) release_region(base, is_8bit(cosa)?2:4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) printk(KERN_DEBUG "changing name at 0x%x failed.\n", base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* Now do IRQ autoprobe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) unsigned long irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* pr_info("IRQ autoprobe\n"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) irqs = probe_irq_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * Enable interrupt on tx buffer empty (it sure is)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * really sure ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * FIXME: When this code is not used as module, we should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * probably call udelay() instead of the interruptible sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) cosa_putstatus(cosa, SR_TX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) schedule_timeout(msecs_to_jiffies(300));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) irq = probe_irq_off(irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Disable all IRQs from the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* Empty the received data register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) cosa_getdata8(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) pr_info("multiple interrupts obtained (%d, board at 0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) irq, cosa->datareg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (irq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pr_info("no interrupt obtained (board at 0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cosa->datareg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* return -1; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) cosa->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) cosa->num = nr_cards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) cosa->usage = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) cosa->nchannels = 2; /* FIXME: how to determine this? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (request_irq(cosa->irq, cosa_interrupt, 0, cosa->type, cosa)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (request_dma(cosa->dma, cosa->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto err_out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL|GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (!cosa->bouncebuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto err_out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) sprintf(cosa->name, "cosa%d", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* Initialize the per-channel data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) cosa->chan = kcalloc(cosa->nchannels, sizeof(struct channel_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!cosa->chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) goto err_out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) for (i = 0; i < cosa->nchannels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct channel_data *chan = &cosa->chan[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) chan->cosa = cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) chan->num = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) sprintf(chan->name, "cosa%dc%d", chan->cosa->num, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* Initialize the chardev data structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) mutex_init(&chan->rlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) sema_init(&chan->wsem, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* Register the network interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!(chan->netdev = alloc_hdlcdev(chan))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) pr_warn("%s: alloc_hdlcdev failed\n", chan->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) goto err_hdlcdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) dev_to_hdlc(chan->netdev)->xmit = cosa_net_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) chan->netdev->netdev_ops = &cosa_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) chan->netdev->watchdog_timeo = TX_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) chan->netdev->base_addr = chan->cosa->datareg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) chan->netdev->irq = chan->cosa->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) chan->netdev->dma = chan->cosa->dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) err = register_hdlc_device(chan->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) netdev_warn(chan->netdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) "register_hdlc_device() failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) free_netdev(chan->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) goto err_hdlcdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) pr_info("cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) cosa->num, cosa->id_string, cosa->type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return nr_cards++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) err_hdlcdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) while (i-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) unregister_hdlc_device(cosa->chan[i].netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) free_netdev(cosa->chan[i].netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) kfree(cosa->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) err_out3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) kfree(cosa->bouncebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) err_out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) free_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) err_out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) free_irq(cosa->irq, cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) release_region(cosa->datareg,is_8bit(cosa)?2:4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) pr_notice("cosa%d: allocating resources failed\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*---------- network device ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static int cosa_net_attach(struct net_device *dev, unsigned short encoding,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned short parity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static int cosa_net_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct channel_data *chan = dev_to_chan(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (!(chan->cosa->firmware_status & COSA_FW_START)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) pr_notice("%s: start the firmware first (status %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) chan->cosa->name, chan->cosa->firmware_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) spin_lock_irqsave(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (chan->usage != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) pr_warn("%s: cosa_net_open called with usage count %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) chan->name, chan->usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) spin_unlock_irqrestore(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) chan->setup_rx = cosa_net_setup_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) chan->tx_done = cosa_net_tx_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) chan->rx_done = cosa_net_rx_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) chan->usage = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) chan->cosa->usage++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) spin_unlock_irqrestore(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) err = hdlc_open(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) spin_lock_irqsave(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) chan->usage = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) chan->cosa->usage--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) spin_unlock_irqrestore(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) cosa_enable_rx(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static netdev_tx_t cosa_net_tx(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct channel_data *chan = dev_to_chan(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) chan->tx_skb = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) cosa_start_tx(chan, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static void cosa_net_timeout(struct net_device *dev, unsigned int txqueue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct channel_data *chan = dev_to_chan(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (test_bit(RXBIT, &chan->cosa->rxtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) chan->netdev->stats.rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) chan->netdev->stats.rx_missed_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) chan->netdev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) chan->netdev->stats.tx_aborted_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) cosa_kick(chan->cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (chan->tx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) dev_kfree_skb(chan->tx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) chan->tx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static int cosa_net_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct channel_data *chan = dev_to_chan(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) hdlc_close(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) cosa_disable_rx(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) spin_lock_irqsave(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (chan->rx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) kfree_skb(chan->rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) chan->rx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (chan->tx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) kfree_skb(chan->tx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) chan->tx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) chan->usage = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) chan->cosa->usage--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) spin_unlock_irqrestore(&chan->cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static char *cosa_net_setup_rx(struct channel_data *chan, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * We can safely fall back to non-dma-able memory, because we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * the cosa->bouncebuf pre-allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) kfree_skb(chan->rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) chan->rx_skb = dev_alloc_skb(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (chan->rx_skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) pr_notice("%s: Memory squeeze, dropping packet\n", chan->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) chan->netdev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) netif_trans_update(chan->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return skb_put(chan->rx_skb, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static int cosa_net_rx_done(struct channel_data *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!chan->rx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) pr_warn("%s: rx_done with empty skb!\n", chan->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) chan->netdev->stats.rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) chan->netdev->stats.rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) chan->rx_skb->protocol = hdlc_type_trans(chan->rx_skb, chan->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) chan->rx_skb->dev = chan->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) skb_reset_mac_header(chan->rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) chan->netdev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) chan->netdev->stats.rx_bytes += chan->cosa->rxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) netif_rx(chan->rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) chan->rx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* ARGSUSED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) static int cosa_net_tx_done(struct channel_data *chan, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (!chan->tx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) pr_warn("%s: tx_done with empty skb!\n", chan->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) chan->netdev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) chan->netdev->stats.tx_aborted_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) dev_consume_skb_irq(chan->tx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) chan->tx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) chan->netdev->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) chan->netdev->stats.tx_bytes += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) netif_wake_queue(chan->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /*---------- Character device ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static ssize_t cosa_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) char __user *buf, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct channel_data *chan = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct cosa_data *cosa = chan->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) char *kbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (!(cosa->firmware_status & COSA_FW_START)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) pr_notice("%s: start the firmware first (status %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) cosa->name, cosa->firmware_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (mutex_lock_interruptible(&chan->rlock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (chan->rxdata == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) mutex_unlock(&chan->rlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) chan->rx_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) cosa_enable_rx(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) add_wait_queue(&chan->rxwaitq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) while (!chan->rx_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (signal_pending(current) && chan->rx_status == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) chan->rx_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) remove_wait_queue(&chan->rxwaitq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) mutex_unlock(&chan->rlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) remove_wait_queue(&chan->rxwaitq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) kbuf = chan->rxdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) count = chan->rxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) mutex_unlock(&chan->rlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (copy_to_user(buf, kbuf, count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static char *chrdev_setup_rx(struct channel_data *chan, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* Expect size <= COSA_MTU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) chan->rxsize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return chan->rxdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int chrdev_rx_done(struct channel_data *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (chan->rx_status) { /* Reader has died */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) kfree(chan->rxdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) up(&chan->wsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) chan->rx_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) wake_up_interruptible(&chan->rxwaitq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static ssize_t cosa_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) const char __user *buf, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct channel_data *chan = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct cosa_data *cosa = chan->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) char *kbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!(cosa->firmware_status & COSA_FW_START)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) pr_notice("%s: start the firmware first (status %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) cosa->name, cosa->firmware_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (down_interruptible(&chan->wsem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (count > COSA_MTU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) count = COSA_MTU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /* Allocate the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (kbuf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) up(&chan->wsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (copy_from_user(kbuf, buf, count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) up(&chan->wsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) chan->tx_status=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) cosa_start_tx(chan, kbuf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) add_wait_queue(&chan->txwaitq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) while (!chan->tx_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (signal_pending(current) && chan->tx_status == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) chan->tx_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) remove_wait_queue(&chan->txwaitq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) chan->tx_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) up(&chan->wsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) remove_wait_queue(&chan->txwaitq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) up(&chan->wsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) kfree(kbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static int chrdev_tx_done(struct channel_data *chan, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (chan->tx_status) { /* Writer was interrupted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) kfree(chan->txbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) up(&chan->wsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) chan->tx_status = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) wake_up_interruptible(&chan->txwaitq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static __poll_t cosa_poll(struct file *file, poll_table *poll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) pr_info("cosa_poll is here\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static int cosa_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct cosa_data *cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct channel_data *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) mutex_lock(&cosa_chardev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if ((n=iminor(file_inode(file))>>CARD_MINOR_BITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) >= nr_cards) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) cosa = cosa_cards+n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if ((n=iminor(file_inode(file))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) chan = cosa->chan + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) file->private_data = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (chan->usage < 0) { /* in netdev mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) cosa->usage++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) chan->usage++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) chan->tx_done = chrdev_tx_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) chan->setup_rx = chrdev_setup_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) chan->rx_done = chrdev_rx_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) mutex_unlock(&cosa_chardev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static int cosa_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct channel_data *channel = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct cosa_data *cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) cosa = channel->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) cosa->usage--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) channel->usage--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) #ifdef COSA_FASYNC_WORKING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static struct fasync_struct *fasync[256] = { NULL, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /* To be done ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) static int cosa_fasync(struct inode *inode, struct file *file, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int port = iminor(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return fasync_helper(inode, file, on, &fasync[port]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* ---------- Ioctls ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * Ioctl subroutines can safely be made inline, because they are called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * only from cosa_ioctl().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static inline int cosa_reset(struct cosa_data *cosa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) char idstring[COSA_MAX_ID_STRING];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (cosa->usage > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) cosa->num, cosa->usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (cosa_reset_and_read_id(cosa, idstring) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) pr_notice("cosa%d: reset failed\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) pr_info("cosa%d: resetting device: %s\n", cosa->num, idstring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) cosa->firmware_status |= COSA_FW_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* High-level function to download data into COSA memory. Calls download() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct cosa_download d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (cosa->usage > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) pr_info("%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) cosa->name, cosa->usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (!(cosa->firmware_status & COSA_FW_RESET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) pr_notice("%s: reset the card first (status %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) cosa->name, cosa->firmware_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (copy_from_user(&d, arg, sizeof(d)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (d.addr < 0 || d.addr > COSA_MAX_FIRMWARE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (d.len < 0 || d.len > COSA_MAX_FIRMWARE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* If something fails, force the user to reset the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_DOWNLOAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) i = download(cosa, d.code, d.len, d.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (i < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) pr_notice("cosa%d: microcode download failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) cosa->num, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) cosa->num, d.len, d.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* High-level function to read COSA memory. Calls readmem() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) struct cosa_download d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (cosa->usage > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) pr_info("cosa%d: WARNING: readmem requested with cosa->usage > 1 (%d). Odd things may happen.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) cosa->num, cosa->usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (!(cosa->firmware_status & COSA_FW_RESET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) pr_notice("%s: reset the card first (status %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) cosa->name, cosa->firmware_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (copy_from_user(&d, arg, sizeof(d)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /* If something fails, force the user to reset the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) cosa->firmware_status &= ~COSA_FW_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) i = readmem(cosa, d.code, d.len, d.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (i < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) pr_notice("cosa%d: reading memory failed: %d\n", cosa->num, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) pr_info("cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) cosa->num, d.len, d.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) cosa->firmware_status |= COSA_FW_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) /* High-level function to start microcode. Calls startmicrocode(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static inline int cosa_start(struct cosa_data *cosa, int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (cosa->usage > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) cosa->num, cosa->usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) != (COSA_FW_RESET|COSA_FW_DOWNLOAD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) pr_notice("%s: download the microcode and/or reset the card first (status %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) cosa->name, cosa->firmware_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) cosa->firmware_status &= ~COSA_FW_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if ((i=startmicrocode(cosa, address)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) cosa->num, address, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) pr_info("cosa%d: starting microcode at 0x%04x\n", cosa->num, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) cosa->startaddr = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) cosa->firmware_status |= COSA_FW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /* Buffer of size at least COSA_MAX_ID_STRING is expected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) static inline int cosa_getidstr(struct cosa_data *cosa, char __user *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) int l = strlen(cosa->id_string)+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (copy_to_user(string, cosa->id_string, l))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) /* Buffer of size at least COSA_MAX_ID_STRING is expected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) static inline int cosa_gettype(struct cosa_data *cosa, char __user *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) int l = strlen(cosa->type)+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (copy_to_user(string, cosa->type, l))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int cosa_ioctl_common(struct cosa_data *cosa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct channel_data *channel, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) case COSAIORSET: /* Reset the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return cosa_reset(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) case COSAIOSTRT: /* Start the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return cosa_start(cosa, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) case COSAIODOWNLD: /* Download the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return cosa_download(cosa, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case COSAIORMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return cosa_readmem(cosa, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) case COSAIORTYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return cosa_gettype(cosa, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) case COSAIORIDSTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return cosa_getidstr(cosa, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case COSAIONRCARDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return nr_cards;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) case COSAIONRCHANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) return cosa->nchannels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) case COSAIOBMSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (is_8bit(cosa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (arg != COSA_BM_OFF && arg != COSA_BM_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) cosa->busmaster = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) case COSAIOBMGET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return cosa->busmaster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct channel_data *chan = dev_to_chan(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) rv = cosa_ioctl_common(chan->cosa, chan, cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) (unsigned long)ifr->ifr_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (rv != -ENOIOCTLCMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return hdlc_ioctl(dev, ifr, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static long cosa_chardev_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) struct channel_data *channel = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct cosa_data *cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) mutex_lock(&cosa_chardev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) cosa = channel->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) ret = cosa_ioctl_common(cosa, channel, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) mutex_unlock(&cosa_chardev_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /*---------- HW layer interface ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) * The higher layer can bind itself to the HW layer by setting the callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * in the channel_data structure and by using these routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) static void cosa_enable_rx(struct channel_data *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct cosa_data *cosa = chan->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (!test_and_set_bit(chan->num, &cosa->rxbitmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) put_driver_status(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static void cosa_disable_rx(struct channel_data *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct cosa_data *cosa = chan->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (test_and_clear_bit(chan->num, &cosa->rxbitmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) put_driver_status(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * FIXME: This routine probably should check for cosa_start_tx() called when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) * the previous transmit is still unfinished. In this case the non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * return value should indicate to the caller that the queuing(sp?) up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * the transmit has failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) struct cosa_data *cosa = chan->cosa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) #ifdef DEBUG_DATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) pr_info("cosa%dc%d: starting tx(0x%x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) chan->cosa->num, chan->num, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) for (i=0; i<len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) pr_cont(" %02x", buf[i]&0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) chan->txbuf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) chan->txsize = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (len > COSA_MTU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) chan->txsize = COSA_MTU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /* Tell the firmware we are ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) set_bit(chan->num, &cosa->txbitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) put_driver_status(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) static void put_driver_status(struct cosa_data *cosa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) | (cosa->txbitmap ? DRIVER_TX_READY : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) &DRIVER_TXMAP_MASK : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (!cosa->rxtx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (cosa->rxbitmap|cosa->txbitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (!cosa->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) cosa_putstatus(cosa, SR_RX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) debug_status_out(cosa, SR_RX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) cosa->enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) } else if (cosa->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) cosa->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) debug_status_out(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) cosa_putdata8(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) debug_data_cmd(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) static void put_driver_status_nolock(struct cosa_data *cosa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) | (cosa->txbitmap ? DRIVER_TX_READY : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) &DRIVER_TXMAP_MASK : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (cosa->rxbitmap|cosa->txbitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) cosa_putstatus(cosa, SR_RX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) debug_status_out(cosa, SR_RX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) cosa->enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) debug_status_out(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) cosa->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) cosa_putdata8(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) debug_data_cmd(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * The "kickme" function: When the DMA times out, this is called to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * clean up the driver status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) * FIXME: Preliminary support, the interface is probably wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) static void cosa_kick(struct cosa_data *cosa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) unsigned long flags, flags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) char *s = "(probably) IRQ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (test_bit(RXBIT, &cosa->rxtx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) s = "RX DMA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) if (test_bit(TXBIT, &cosa->rxtx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) s = "TX DMA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) pr_info("%s: %s timeout - restarting\n", cosa->name, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) cosa->rxtx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) flags1 = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) disable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) clear_dma_ff(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) release_dma_lock(flags1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) /* FIXME: Anything else? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) (void) cosa_getdata8(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) cosa_putdata8(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) put_driver_status_nolock(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) * Check if the whole buffer is DMA-able. It means it is below the 16M of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) * physical memory and doesn't span the 64k boundary. For now it seems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * SKB's never do this, but we'll check this anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) static int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) unsigned long b = (unsigned long)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (b+len >= MAX_DMA_ADDRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if ((b^ (b+len)) & 0x10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (count++ < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) pr_info("%s: packet spanning a 64k boundary\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) chan->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) /* ---------- The SRP/COSA ROM monitor functions ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * Downloading SRP microcode: say "w" to SRP monitor, it answers by "w=",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * drivers need to say 4-digit hex number meaning start address of the microcode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * separated by a single space. Monitor replies by saying " =". Now driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * has to write 4-digit hex number meaning the last byte address ended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * by a single space. Monitor has to reply with a space. Now the download
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * begins. After the download monitor replies with "\r\n." (CR LF dot).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) static int download(struct cosa_data *cosa, const char __user *microcode, int length, int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (put_wait_data(cosa, 'w') == -1) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if ((i=get_wait_data(cosa)) != 'w') { printk("dnld: 0x%04x\n",i); return -2;}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (get_wait_data(cosa) != '=') return -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (puthexnumber(cosa, address) < 0) return -4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) if (put_wait_data(cosa, ' ') == -1) return -10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (get_wait_data(cosa) != ' ') return -11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (get_wait_data(cosa) != '=') return -12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (puthexnumber(cosa, address+length-1) < 0) return -13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (put_wait_data(cosa, ' ') == -1) return -18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (get_wait_data(cosa) != ' ') return -19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) while (length--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) #ifndef SRP_DOWNLOAD_AT_BOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (get_user(c, microcode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return -23; /* ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) c = *microcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (put_wait_data(cosa, c) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) return -20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) microcode++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (get_wait_data(cosa) != '\r') return -21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (get_wait_data(cosa) != '\n') return -22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (get_wait_data(cosa) != '.') return -23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) printk(KERN_DEBUG "cosa%d: download completed.\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * Starting microcode is done via the "g" command of the SRP monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * The chat should be the following: "g" "g=" "<addr><CR>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) * "<CR><CR><LF><CR><LF>".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) static int startmicrocode(struct cosa_data *cosa, int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (put_wait_data(cosa, 'g') == -1) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if (get_wait_data(cosa) != 'g') return -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (get_wait_data(cosa) != '=') return -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (puthexnumber(cosa, address) < 0) return -4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (put_wait_data(cosa, '\r') == -1) return -5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (get_wait_data(cosa) != '\r') return -6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (get_wait_data(cosa) != '\r') return -7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (get_wait_data(cosa) != '\n') return -8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (get_wait_data(cosa) != '\r') return -9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (get_wait_data(cosa) != '\n') return -10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) printk(KERN_DEBUG "cosa%d: microcode started\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) * Reading memory is done via the "r" command of the SRP monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) * The chat is the following "r" "r=" "<addr> " " =" "<last_byte> " " "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) * Then driver can read the data and the conversation is finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) * by SRP monitor sending "<CR><LF>." (dot at the end).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * This routine is not needed during the normal operation and serves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) * for debugging purposes only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) static int readmem(struct cosa_data *cosa, char __user *microcode, int length, int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (put_wait_data(cosa, 'r') == -1) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if ((get_wait_data(cosa)) != 'r') return -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if ((get_wait_data(cosa)) != '=') return -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (puthexnumber(cosa, address) < 0) return -4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (put_wait_data(cosa, ' ') == -1) return -5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (get_wait_data(cosa) != ' ') return -6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) if (get_wait_data(cosa) != '=') return -7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (puthexnumber(cosa, address+length-1) < 0) return -8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (put_wait_data(cosa, ' ') == -1) return -9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (get_wait_data(cosa) != ' ') return -10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) while (length--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if ((i=get_wait_data(cosa)) == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) pr_info("0x%04x bytes remaining\n", length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) return -11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) c=i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) #if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (put_user(c, microcode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) return -23; /* ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) *microcode = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) microcode++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (get_wait_data(cosa) != '\r') return -21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (get_wait_data(cosa) != '\n') return -22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (get_wait_data(cosa) != '.') return -23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) printk(KERN_DEBUG "cosa%d: readmem completed.\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * This function resets the device and reads the initial prompt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) * of the device's ROM monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) int i=0, id=0, prev=0, curr=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) /* Reset the card ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) cosa_getdata8(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) cosa_putstatus(cosa, SR_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /* Disable all IRQs from the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * Try to read the ID string. The card then prints out the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * identification string ended by the "\n\x2e".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) * The following loop is indexed through i (instead of id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) * to avoid looping forever when for any reason
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) * the port returns '\r', '\n' or '\x2e' permanently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) for (i=0; i<COSA_MAX_ID_STRING-1; i++, prev=curr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if ((curr = get_wait_data(cosa)) == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) curr &= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (curr != '\r' && curr != '\n' && curr != 0x2e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) idstring[id++] = curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if (curr == 0x2e && prev == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) /* Perhaps we should fail when i==COSA_MAX_ID_STRING-1 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) idstring[id] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) /* ---------- Auxiliary routines for COSA/SRP monitor ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) * This routine gets the data byte from the card waiting for the SR_RX_RDY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * bit to be set in a loop. It should be used in the exceptional cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * only (for example when resetting the card or downloading the firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) static int get_wait_data(struct cosa_data *cosa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) int retries = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) while (--retries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) /* read data and return them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (cosa_getstatus(cosa) & SR_RX_RDY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) short r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) r = cosa_getdata8(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) pr_info("get_wait_data returning after %d retries\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 999-retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) /* sleep if not ready to read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) schedule_timeout_interruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) pr_info("timeout in get_wait_data (status 0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) cosa_getstatus(cosa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) * This routine puts the data byte to the card waiting for the SR_TX_RDY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) * bit to be set in a loop. It should be used in the exceptional cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) * only (for example when resetting the card or downloading the firmware).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static int put_wait_data(struct cosa_data *cosa, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) int retries = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) while (--retries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) /* read data and return them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (cosa_getstatus(cosa) & SR_TX_RDY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) cosa_putdata8(cosa, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) pr_info("Putdata: %d retries\n", 999-retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) /* sleep if not ready to read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) schedule_timeout_interruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) pr_info("cosa%d: timeout in put_wait_data (status 0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) cosa->num, cosa_getstatus(cosa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * The following routine puts the hexadecimal number into the SRP monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) * and verifies the proper echo of the sent bytes. Returns 0 on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * negative number on failure (-1,-3,-5,-7) means that put_wait_data() failed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) * (-2,-4,-6,-8) means that reading echo failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) static int puthexnumber(struct cosa_data *cosa, int number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) char temp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) /* Well, I should probably replace this by something faster. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) sprintf(temp, "%04X", number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) for (i=0; i<4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (put_wait_data(cosa, temp[i]) == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) pr_notice("cosa%d: puthexnumber failed to write byte %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) cosa->num, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return -1-2*i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) if (get_wait_data(cosa) != temp[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) cosa->num, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) return -2-2*i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /* ---------- Interrupt routines ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) * There are three types of interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) * At the beginning of transmit - this handled is in tx_interrupt(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) * at the beginning of receive - it is in rx_interrupt() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) * at the end of transmit/receive - it is the eot_interrupt() function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * These functions are multiplexed by cosa_interrupt() according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * COSA status byte. I have moved the rx/tx/eot interrupt handling into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * separate functions to make it more readable. These functions are inline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) * so there should be no overhead of function call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) * In the COSA bus-master mode, we need to tell the card the address of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) * buffer. Unfortunately, COSA may be too slow for us, so we must busy-wait.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) * It's time to use the bottom half :-(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) * Transmit interrupt routine - called when COSA is willing to obtain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) * data from the OS. The most tricky part of the routine is selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) * of channel we (OS) want to send packet for. For SRP we should probably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) * use the round-robin approach. The newer COSA firmwares have a simple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) * flow-control - in the status word has bits 2 and 3 set to 1 means that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * channel 0 or 1 doesn't want to receive data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) * It seems there is a bug in COSA firmware (need to trace it further):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) * When the driver status says that the kernel has no more data for transmit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * (e.g. at the end of TX DMA) and then the kernel changes its mind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) * (e.g. new packet is queued to hard_start_xmit()), the card issues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * the TX interrupt but does not mark the channel as ready-to-transmit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) * The fix seems to be to push the packet to COSA despite its request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) * We first try to obey the card's opinion, and then fall back to forced TX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) static inline void tx_interrupt(struct cosa_data *cosa, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) unsigned long flags, flags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) #ifdef DEBUG_IRQS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) pr_info("cosa%d: SR_DOWN_REQUEST status=0x%04x\n", cosa->num, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) set_bit(TXBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (!test_bit(IRQBIT, &cosa->rxtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) /* flow control, see the comment above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) int i=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (!cosa->txbitmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) cosa->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) put_driver_status_nolock(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) clear_bit(TXBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) cosa->txchan++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if (cosa->txchan >= cosa->nchannels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) cosa->txchan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (!(cosa->txbitmap & (1<<cosa->txchan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) if (~status & (1 << (cosa->txchan+DRIVER_TXMAP_SHIFT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) /* in second pass, accept first ready-to-TX channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) if (i > cosa->nchannels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) /* Can be safely ignored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) #ifdef DEBUG_IRQS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) printk(KERN_DEBUG "%s: Forcing TX "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) "to not-ready channel %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) cosa->name, cosa->txchan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) cosa->txsize = cosa->chan[cosa->txchan].txsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) if (cosa_dma_able(cosa->chan+cosa->txchan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) cosa->chan[cosa->txchan].txbuf, cosa->txsize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) cosa->txbuf = cosa->chan[cosa->txchan].txbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) memcpy(cosa->bouncebuf, cosa->chan[cosa->txchan].txbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) cosa->txsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) cosa->txbuf = cosa->bouncebuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) if (is_8bit(cosa)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) if (!test_bit(IRQBIT, &cosa->rxtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) cosa_putstatus(cosa, SR_TX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) ((cosa->txsize >> 8) & 0x1f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) debug_status_out(cosa, SR_TX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) ((cosa->txsize >> 8) & 0x1f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) debug_data_in(cosa, cosa_getdata8(cosa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) cosa_getdata8(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) set_bit(IRQBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) clear_bit(IRQBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) cosa_putdata8(cosa, cosa->txsize&0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) debug_status_out(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) debug_data_out(cosa, cosa->txsize&0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) cosa_putstatus(cosa, SR_TX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) | (cosa->txsize & 0x1fff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) debug_status_out(cosa, SR_TX_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) debug_data_out(cosa, ((cosa->txchan<<13) & 0xe000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) | (cosa->txsize & 0x1fff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) debug_data_in(cosa, cosa_getdata8(cosa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) debug_status_out(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) cosa_getdata8(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) cosa_putstatus(cosa, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (cosa->busmaster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) unsigned long addr = virt_to_bus(cosa->txbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) int count=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) pr_info("busmaster IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) if (count > 1000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) pr_info("status %x\n", cosa_getstatus(cosa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) pr_info("ready after %d loops\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) cosa_putdata16(cosa, (addr >> 16)&0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if (count > 1000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) pr_info("ready after %d loops\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) cosa_putdata16(cosa, addr &0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) flags1 = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) enable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) release_dma_lock(flags1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) /* start the DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) flags1 = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) disable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) clear_dma_ff(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) set_dma_mode(cosa->dma, DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) set_dma_count(cosa->dma, cosa->txsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) enable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) release_dma_lock(flags1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) static inline void rx_interrupt(struct cosa_data *cosa, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) #ifdef DEBUG_IRQS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) pr_info("cosa%d: SR_UP_REQUEST\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) set_bit(RXBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (is_8bit(cosa)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if (!test_bit(IRQBIT, &cosa->rxtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) set_bit(IRQBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) put_driver_status_nolock(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) cosa->rxsize = cosa_getdata8(cosa) <<8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) debug_data_in(cosa, cosa->rxsize >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) clear_bit(IRQBIT, &cosa->rxtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) cosa->rxsize |= cosa_getdata8(cosa) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) debug_data_in(cosa, cosa->rxsize & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) pr_info("cosa%d: receive rxsize = (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) cosa->num, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) cosa->rxsize = cosa_getdata16(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) debug_data_in(cosa, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) pr_info("cosa%d: receive rxsize = (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) cosa->num, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) pr_warn("%s: rx for unknown channel (0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) cosa->name, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) goto reject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) cosa->rxchan = cosa->chan + ((cosa->rxsize & 0xe000) >> 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) cosa->rxsize &= 0x1fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) cosa->rxbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) if (cosa->rxchan->setup_rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) cosa->rxbuf = cosa->rxchan->setup_rx(cosa->rxchan, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) if (!cosa->rxbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) reject: /* Reject the packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) pr_info("cosa%d: rejecting packet on channel %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) cosa->num, cosa->rxchan->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) cosa->rxbuf = cosa->bouncebuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) /* start the DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) flags = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) disable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) clear_dma_ff(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) set_dma_mode(cosa->dma, DMA_MODE_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) if (cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize & 0x1fff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) set_dma_addr(cosa->dma, virt_to_bus(cosa->rxbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) set_dma_addr(cosa->dma, virt_to_bus(cosa->bouncebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) set_dma_count(cosa->dma, (cosa->rxsize&0x1fff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) enable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) if (!is_8bit(cosa) && (status & SR_TX_RDY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) cosa_putdata8(cosa, DRIVER_RX_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) if (!is_8bit(cosa) && (status & SR_TX_RDY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) debug_data_cmd(cosa, DRIVER_RX_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) static inline void eot_interrupt(struct cosa_data *cosa, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) unsigned long flags, flags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) spin_lock_irqsave(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) flags1 = claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) disable_dma(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) clear_dma_ff(cosa->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) release_dma_lock(flags1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) if (test_bit(TXBIT, &cosa->rxtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) struct channel_data *chan = cosa->chan+cosa->txchan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) if (chan->tx_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) if (chan->tx_done(chan, cosa->txsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) clear_bit(chan->num, &cosa->txbitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) } else if (test_bit(RXBIT, &cosa->rxtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) #ifdef DEBUG_DATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) pr_info("cosa%dc%d: done rx(0x%x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) cosa->num, cosa->rxchan->num, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) for (i=0; i<cosa->rxsize; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) pr_cont(" %02x", cosa->rxbuf[i]&0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) /* Packet for unknown channel? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) if (cosa->rxbuf == cosa->bouncebuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) if (cosa->rxchan->rx_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) if (cosa->rxchan->rx_done(cosa->rxchan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) * cleared anyway). We should do it as soon as possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) * so that we can tell the COSA we are done and to give it a time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * for recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) cosa->rxtx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) put_driver_status_nolock(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) spin_unlock_irqrestore(&cosa->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) static irqreturn_t cosa_interrupt(int irq, void *cosa_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) unsigned status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) struct cosa_data *cosa = cosa_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) status = cosa_getstatus(cosa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) #ifdef DEBUG_IRQS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) pr_info("cosa%d: got IRQ, status 0x%02x\n", cosa->num, status & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) debug_status_in(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) switch (status & SR_CMD_FROM_SRP_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) case SR_DOWN_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) tx_interrupt(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) case SR_UP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) rx_interrupt(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) case SR_END_OF_TRANSFER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) eot_interrupt(cosa, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) /* We may be too fast for SRP. Try to wait a bit more. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) if (count++ < 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) pr_info("cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) cosa->num, status & 0xff, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) #ifdef DEBUG_IRQS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) if (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) pr_info("%s: %d-times got unknown status in IRQ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) cosa->name, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) pr_info("%s: returning from IRQ\n", cosa->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) /* ---------- I/O debugging routines ---------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) * These routines can be used to monitor COSA/SRP I/O and to printk()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) * the data being transferred on the data and status I/O port in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) * readable way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) #ifdef DEBUG_IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) static void debug_status_in(struct cosa_data *cosa, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) switch (status & SR_CMD_FROM_SRP_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) case SR_UP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) s = "RX_REQ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) case SR_DOWN_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) s = "TX_REQ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) case SR_END_OF_TRANSFER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) s = "ET_REQ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) s = "NO_REQ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) pr_info("%s: IO: status -> 0x%02x (%s%s%s%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) cosa->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) status & SR_USR_RQ ? "USR_RQ|" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) status & SR_TX_RDY ? "TX_RDY|" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) status & SR_RX_RDY ? "RX_RDY|" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) static void debug_status_out(struct cosa_data *cosa, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) pr_info("%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) cosa->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) status & SR_RX_DMA_ENA ? "RXDMA|" : "!rxdma|",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) status & SR_TX_DMA_ENA ? "TXDMA|" : "!txdma|",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) status & SR_RST ? "RESET|" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) status & SR_USR_INT_ENA ? "USRINT|" : "!usrint|",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) status & SR_TX_INT_ENA ? "TXINT|" : "!txint|",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) status & SR_RX_INT_ENA ? "RXINT" : "!rxint");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) static void debug_data_in(struct cosa_data *cosa, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) pr_info("%s: IO: data -> 0x%04x\n", cosa->name, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) static void debug_data_out(struct cosa_data *cosa, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) pr_info("%s: IO: data <- 0x%04x\n", cosa->name, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) static void debug_data_cmd(struct cosa_data *cosa, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) pr_info("%s: IO: data <- 0x%04x (%s|%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) cosa->name, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) /* EOF -- this file has not been truncated */