^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) /* sb1000.c: A General Instruments SB1000 driver for linux. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) Written 1998 by Franco Venturi.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) Copyright 1998 by Franco Venturi.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) Copyright 1994,1995 by Donald Becker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Copyright 1993 United States Government as represented by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Director, National Security Agency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) This driver is for the General Instruments SB1000 (internal SURFboard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) The author may be reached as fventuri@mediaone.net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 981115 Steven Hirsch <shirsch@adelphia.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) Linus changed the timer interface. Should work on all recent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) development kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) 980608 Steven Hirsch <shirsch@adelphia.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) Small changes to make it work with 2.1.x kernels. Hopefully,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) nothing major will change before official release of Linux 2.2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) Merged with 2.2 - Alan Cox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/if_cablemodem.h> /* for SIOGCM/SIOSCM stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/delay.h> /* for udelay() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #ifdef SB1000_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int sb1000_debug = SB1000_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static const int sb1000_debug = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static const int SB1000_IO_EXTENT = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* SB1000 Maximum Receive Unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const int SB1000_MRU = 1500; /* octects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define NPIDS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct sb1000_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct sk_buff *rx_skb[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) short rx_dlen[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int rx_frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) short rx_error_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) short rx_error_dpc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned char rx_session_id[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned char rx_frame_id[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned char rx_pkt_type[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* prototypes for Linux interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) extern int sb1000_probe(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int sb1000_open(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int sb1000_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static netdev_tx_t sb1000_start_xmit(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static irqreturn_t sb1000_interrupt(int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int sb1000_close(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* SB1000 hardware routines to be used during open/configuration phases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int card_wait_for_busy_clear(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int card_wait_for_ready(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned char in[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int card_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) const unsigned char out[], unsigned char in[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* SB1000 hardware routines to be used during frame rx interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static int sb1000_wait_for_ready(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int sb1000_wait_for_ready_clear(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void sb1000_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) const unsigned char out[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void sb1000_read_status(const int ioaddr[], unsigned char in[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void sb1000_issue_read_command(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* SB1000 commands for open/configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int sb1000_reset(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int sb1000_check_CRC(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline int sb1000_start_get_set_command(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int sb1000_end_get_set_command(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int sb1000_activate(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int sb1000_get_firmware_version(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const char* name, unsigned char version[], int do_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int sb1000_get_frequency(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int* frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int sb1000_set_frequency(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int sb1000_get_PIDs(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) short PID[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int sb1000_set_PIDs(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) const short PID[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* SB1000 commands for frame rx interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int sb1000_rx(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void sb1000_error_dpc(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static const struct pnp_device_id sb1000_pnp_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { "GIC1000", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { "", 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static const struct net_device_ops sb1000_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .ndo_open = sb1000_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .ndo_start_xmit = sb1000_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .ndo_do_ioctl = sb1000_dev_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .ndo_stop = sb1000_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .ndo_set_mac_address = eth_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .ndo_validate_addr = eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned short ioaddr[2], irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned int serial_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (pnp_device_attach(pdev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (pnp_activate_dev(pdev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto out_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!pnp_port_valid(pdev, 0) || !pnp_port_valid(pdev, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!pnp_irq_valid(pdev, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) serial_number = pdev->card->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ioaddr[0] = pnp_port_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ioaddr[1] = pnp_port_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) irq = pnp_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!request_region(ioaddr[0], 16, "sb1000"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (!request_region(ioaddr[1], 16, "sb1000"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) goto out_release_region0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dev = alloc_etherdev(sizeof(struct sb1000_private));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) goto out_release_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) dev->base_addr = ioaddr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) dev->mem_start = ioaddr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dev->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (sb1000_debug > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dev->mem_start, serial_number, dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * The SB1000 is an rx-only cable modem device. The uplink is a modem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * and we do not want to arp on it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dev->flags = IFF_POINTOPOINT|IFF_NOARP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) SET_NETDEV_DEV(dev, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (sb1000_debug > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) printk(KERN_NOTICE "%s", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev->netdev_ops = &sb1000_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* hardware address is 0:0:serial_number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dev->dev_addr[2] = serial_number >> 24 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) dev->dev_addr[3] = serial_number >> 16 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) dev->dev_addr[4] = serial_number >> 8 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dev->dev_addr[5] = serial_number >> 0 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) pnp_set_drvdata(pdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) error = register_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) goto out_free_netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) out_free_netdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) out_release_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) release_region(ioaddr[1], 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) out_release_region0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) release_region(ioaddr[0], 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) out_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) pnp_disable_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) out_detach:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pnp_device_detach(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) sb1000_remove_one(struct pnp_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct net_device *dev = pnp_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) release_region(dev->base_addr, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) release_region(dev->mem_start, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static struct pnp_driver sb1000_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .name = "sb1000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .id_table = sb1000_pnp_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .probe = sb1000_probe_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .remove = sb1000_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * SB1000 hardware routines to be used during open/configuration phases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static const int TimeOutJiffies = (875 * HZ) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Card Wait For Busy Clear (cannot be used during an interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) card_wait_for_busy_clear(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) unsigned char a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) a = inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) timeout = jiffies + TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) while (a & 0x80 || a & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* a little sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) yield();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) a = inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) printk(KERN_WARNING "%s: card_wait_for_busy_clear timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Card Wait For Ready (cannot be used during an interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) unsigned char a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) a = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) timeout = jiffies + TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) while (a & 0x80 || !(a & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* a little sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) yield();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) a = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) printk(KERN_WARNING "%s: card_wait_for_ready timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) in[1] = inb(ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) in[2] = inb(ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) in[3] = inb(ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) in[4] = inb(ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) in[0] = inb(ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) in[6] = inb(ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) in[5] = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Card Send Command (cannot be used during an interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) card_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) const unsigned char out[], unsigned char in[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if ((status = card_wait_for_busy_clear(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) outb(0xa0, ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) outb(out[2], ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) outb(out[3], ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) outb(out[4], ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) outb(out[5], ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) outb(out[1], ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) outb(0xa0, ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) outb(out[0], ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (out[0] != 0x20 && out[0] != 0x30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if ((status = card_wait_for_ready(ioaddr, name, in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) printk(KERN_DEBUG "%s: card_send_command "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) "out: %02x%02x%02x%02x%02x%02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) "in: %02x%02x%02x%02x%02x%02x%02x\n", name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) out[0], out[1], out[2], out[3], out[4], out[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) in[0], in[1], in[2], in[3], in[4], in[5], in[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) printk(KERN_DEBUG "%s: card_send_command "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) "out: %02x%02x%02x%02x%02x%02x\n", name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) out[0], out[1], out[2], out[3], out[4], out[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (out[1] != 0x1b) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (out[0] >= 0x80 && in[0] != (out[1] | 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * SB1000 hardware routines to be used during frame rx interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static const int Sb1000TimeOutJiffies = 7 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* Card Wait For Ready (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) sb1000_wait_for_ready(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) while (inb(ioaddr[1] + 6) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) printk(KERN_WARNING "%s: sb1000_wait_for_ready timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) while (!(inb(ioaddr[1] + 6) & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) printk(KERN_WARNING "%s: sb1000_wait_for_ready timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* Card Wait For Ready Clear (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) sb1000_wait_for_ready_clear(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) while (inb(ioaddr[1] + 6) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) while (inb(ioaddr[1] + 6) & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* Card Send Command (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) sb1000_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) const unsigned char out[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) outb(out[2], ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) outb(out[3], ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) outb(out[4], ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) outb(out[5], ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) outb(out[1], ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) outb(out[0], ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) printk(KERN_DEBUG "%s: sb1000_send_command out: %02x%02x%02x%02x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) "%02x%02x\n", name, out[0], out[1], out[2], out[3], out[4], out[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Card Read Status (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) sb1000_read_status(const int ioaddr[], unsigned char in[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) in[1] = inb(ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) in[2] = inb(ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) in[3] = inb(ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) in[4] = inb(ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) in[0] = inb(ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* Issue Read Command (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) sb1000_issue_read_command(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) outb(0xa0, ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) sb1000_send_command(ioaddr, name, Command0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * SB1000 commands for open/configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* reset SB1000 card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) sb1000_reset(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int port, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) port = ioaddr[1] + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) outb(0x4, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) outb(0x0, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) outb(0x4, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) outb(0x0, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) udelay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (st[3] != 0xf0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* check SB1000 firmware CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) sb1000_check_CRC(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* check CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (st[1] != st[3] || st[2] != st[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sb1000_start_get_set_command(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return card_send_command(ioaddr, name, Command0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) sb1000_end_get_set_command(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return card_send_command(ioaddr, name, Command1, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) sb1000_activate(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) status = card_send_command(ioaddr, name, Command0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) status = card_send_command(ioaddr, name, Command1, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (st[3] != 0xf1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) status = sb1000_start_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return sb1000_start_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* get SB1000 firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) sb1000_get_firmware_version(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) unsigned char version[], int do_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (st[0] != 0xa3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) version[0] = st[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) version[1] = st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (do_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* get SB1000 frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) *frequency = ((st[1] << 8 | st[2]) << 8 | st[3]) << 8 | st[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* set SB1000 frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) unsigned char Command0[6] = {0x80, 0x29, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) const int FrequencyLowerLimit = 57000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) const int FrequencyUpperLimit = 804000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (frequency < FrequencyLowerLimit || frequency > FrequencyUpperLimit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) printk(KERN_ERR "%s: frequency chosen (%d kHz) is not in the range "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) "[%d,%d] kHz\n", name, frequency, FrequencyLowerLimit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) FrequencyUpperLimit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) Command0[5] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) frequency >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) Command0[4] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) frequency >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) Command0[3] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) frequency >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) Command0[2] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return card_send_command(ioaddr, name, Command0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* get SB1000 PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) PID[0] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if ((status = card_send_command(ioaddr, name, Command1, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) PID[1] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if ((status = card_send_command(ioaddr, name, Command2, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) PID[2] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if ((status = card_send_command(ioaddr, name, Command3, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) PID[3] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* set SB1000 PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) short p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) unsigned char Command0[6] = {0x80, 0x31, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) unsigned char Command1[6] = {0x80, 0x32, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) unsigned char Command2[6] = {0x80, 0x33, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) unsigned char Command3[6] = {0x80, 0x34, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) p = PID[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) Command0[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) Command0[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) p = PID[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) Command1[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) Command1[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if ((status = card_send_command(ioaddr, name, Command1, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) p = PID[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) Command2[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) Command2[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if ((status = card_send_command(ioaddr, name, Command2, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) p = PID[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) Command3[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) Command3[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if ((status = card_send_command(ioaddr, name, Command3, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if ((status = card_send_command(ioaddr, name, Command4, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) sb1000_print_status_buffer(const char* name, unsigned char st[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) unsigned char buffer[], int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) int i, j, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) printk(KERN_DEBUG "%s: status: %02x %02x\n", name, st[0], st[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (buffer[24] == 0x08 && buffer[25] == 0x00 && buffer[26] == 0x45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) printk(KERN_DEBUG "%s: length: %d protocol: %d from: %d.%d.%d.%d:%d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) "to %d.%d.%d.%d:%d\n", name, buffer[28] << 8 | buffer[29],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) buffer[35], buffer[38], buffer[39], buffer[40], buffer[41],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) buffer[46] << 8 | buffer[47],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) buffer[42], buffer[43], buffer[44], buffer[45],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) buffer[48] << 8 | buffer[49]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) for (i = 0, k = 0; i < (size + 7) / 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) printk(KERN_DEBUG "%s: %s", name, i ? " " : "buffer:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) for (j = 0; j < 8 && k < size; j++, k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) printk(" %02x", buffer[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * SB1000 commands for frame rx interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /* receive a single frame and assemble datagram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * (this is the heart of the interrupt routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) sb1000_rx(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) #define FRAMESIZE 184
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) unsigned char st[2], buffer[FRAMESIZE], session_id, frame_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) short dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int ioaddr, ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) unsigned int skbsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* SB1000 frame constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) const int FrameSize = FRAMESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) const int NewDatagramHeaderSkip = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) const int NewDatagramHeaderSize = NewDatagramHeaderSkip + 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) const int NewDatagramDataSize = FrameSize - NewDatagramHeaderSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) const int ContDatagramHeaderSkip = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) const int ContDatagramHeaderSize = ContDatagramHeaderSkip + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) const int ContDatagramDataSize = FrameSize - ContDatagramHeaderSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) const int TrailerSize = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) insw(ioaddr, (unsigned short*) st, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) #ifdef XXXDEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) printk("cm0: received: %02x %02x\n", st[0], st[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) #endif /* XXXDEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) lp->rx_frames++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /* decide if it is a good or bad frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) for (ns = 0; ns < NPIDS; ns++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) session_id = lp->rx_session_id[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) frame_id = lp->rx_frame_id[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (st[0] == session_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (st[1] == frame_id || (!frame_id && (st[1] & 0xf0) == 0x30)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) goto good_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) } else if ((st[1] & 0xf0) == 0x30 && (st[0] & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) goto skipped_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) goto bad_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) } else if (st[0] == (session_id | 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if ((st[1] & 0xf0) == 0x30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) goto skipped_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) goto bad_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) goto bad_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) skipped_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) stats->rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) skb = lp->rx_skb[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) printk(KERN_WARNING "%s: missing frame(s): got %02x %02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) "expecting %02x %02x\n", dev->name, st[0], st[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) skb ? session_id : session_id | 0x40, frame_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) good_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) lp->rx_frame_id[ns] = 0x30 | ((st[1] + 1) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* new datagram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (st[0] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* get data length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) insw(ioaddr, buffer, NewDatagramHeaderSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) #ifdef XXXDEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) printk("cm0: IP identification: %02x%02x fragment offset: %02x%02x\n", buffer[30], buffer[31], buffer[32], buffer[33]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) #endif /* XXXDEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (buffer[0] != NewDatagramHeaderSkip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) printk(KERN_WARNING "%s: new datagram header skip error: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) "got %02x expecting %02x\n", dev->name, buffer[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) NewDatagramHeaderSkip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) stats->rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) insw(ioaddr, buffer, NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) goto bad_frame_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dlen = ((buffer[NewDatagramHeaderSkip + 3] & 0x0f) << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) buffer[NewDatagramHeaderSkip + 4]) - 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (dlen > SB1000_MRU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) printk(KERN_WARNING "%s: datagram length (%d) greater "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) "than MRU (%d)\n", dev->name, dlen, SB1000_MRU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) stats->rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) insw(ioaddr, buffer, NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) goto bad_frame_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) lp->rx_dlen[ns] = dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /* compute size to allocate for datagram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) skbsize = dlen + FrameSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if ((skb = alloc_skb(skbsize, GFP_ATOMIC)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) printk(KERN_WARNING "%s: can't allocate %d bytes long "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) "skbuff\n", dev->name, skbsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) stats->rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) insw(ioaddr, buffer, NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) goto dropped_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) skb_reset_mac_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) skb->protocol = (unsigned short) buffer[NewDatagramHeaderSkip + 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) insw(ioaddr, skb_put(skb, NewDatagramDataSize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) lp->rx_skb[ns] = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /* continuation of previous datagram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) insw(ioaddr, buffer, ContDatagramHeaderSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (buffer[0] != ContDatagramHeaderSkip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) printk(KERN_WARNING "%s: cont datagram header skip error: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) "got %02x expecting %02x\n", dev->name, buffer[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) ContDatagramHeaderSkip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) stats->rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) insw(ioaddr, buffer, ContDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto bad_frame_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) skb = lp->rx_skb[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) insw(ioaddr, skb_put(skb, ContDatagramDataSize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) ContDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) dlen = lp->rx_dlen[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (skb->len < dlen + TrailerSize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) lp->rx_session_id[ns] &= ~0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* datagram completed: send to upper level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) skb_trim(skb, dlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) stats->rx_bytes+=dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) stats->rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) lp->rx_skb[ns] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) lp->rx_session_id[ns] |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) bad_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) insw(ioaddr, buffer, FrameSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) printk(KERN_WARNING "%s: frame error: got %02x %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dev->name, st[0], st[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) stats->rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) bad_frame_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (sb1000_debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) sb1000_print_status_buffer(dev->name, st, buffer, FrameSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) dropped_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) stats->rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (ns < NPIDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if ((skb = lp->rx_skb[ns])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) lp->rx_skb[ns] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) lp->rx_session_id[ns] |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) sb1000_error_dpc(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static const unsigned char Command0[6] = {0x80, 0x26, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) unsigned char st[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int ioaddr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) const int ErrorDpcCounterInitialize = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) sb1000_send_command(ioaddr, name, Command0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) sb1000_wait_for_ready(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) sb1000_read_status(ioaddr, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (st[1] & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) lp->rx_error_dpc_count = ErrorDpcCounterInitialize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * Linux interface functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) sb1000_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) int ioaddr[2], status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) const unsigned short FirmwareVersion[] = {0x01, 0x01};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* initialize sb1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if ((status = sb1000_reset(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if ((status = sb1000_check_CRC(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* initialize private data before board can catch interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) lp->rx_skb[0] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) lp->rx_skb[1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) lp->rx_skb[2] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) lp->rx_skb[3] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) lp->rx_dlen[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) lp->rx_dlen[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) lp->rx_dlen[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) lp->rx_dlen[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) lp->rx_frames = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) lp->rx_error_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) lp->rx_error_dpc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) lp->rx_session_id[0] = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) lp->rx_session_id[1] = 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) lp->rx_session_id[2] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) lp->rx_session_id[3] = 0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) lp->rx_frame_id[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) lp->rx_frame_id[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) lp->rx_frame_id[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) lp->rx_frame_id[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (request_irq(dev->irq, sb1000_interrupt, 0, "sb1000", dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (sb1000_debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) printk(KERN_DEBUG "%s: Opening, IRQ %d\n", name, dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* Activate board and check firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if ((status = sb1000_activate(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) udelay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if ((status = sb1000_get_firmware_version(ioaddr, name, version, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (version[0] != FirmwareVersion[0] || version[1] != FirmwareVersion[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) printk(KERN_WARNING "%s: found firmware version %x.%02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) "(should be %x.%02x)\n", name, version[0], version[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) FirmwareVersion[0], FirmwareVersion[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return 0; /* Always succeed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) static int sb1000_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) char* name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) unsigned char version[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) short PID[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) int ioaddr[2], status, frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) unsigned int stats[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!(dev && dev->flags & IFF_UP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) case SIOCGCMSTATS: /* get statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) stats[0] = dev->stats.rx_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) stats[1] = lp->rx_frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) stats[2] = dev->stats.rx_packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) stats[3] = dev->stats.rx_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) stats[4] = dev->stats.rx_dropped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if(copy_to_user(ifr->ifr_data, stats, sizeof(stats)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) case SIOCGCMFIRMWARE: /* get firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if ((status = sb1000_get_firmware_version(ioaddr, name, version, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if(copy_to_user(ifr->ifr_data, version, sizeof(version)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) case SIOCGCMFREQUENCY: /* get frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if ((status = sb1000_get_frequency(ioaddr, name, &frequency)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if(put_user(frequency, (int __user *) ifr->ifr_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) case SIOCSCMFREQUENCY: /* set frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if(get_user(frequency, (int __user *) ifr->ifr_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if ((status = sb1000_set_frequency(ioaddr, name, frequency)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) case SIOCGCMPIDS: /* get PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if ((status = sb1000_get_PIDs(ioaddr, name, PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if(copy_to_user(ifr->ifr_data, PID, sizeof(PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case SIOCSCMPIDS: /* set PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if(copy_from_user(PID, ifr->ifr_data, sizeof(PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if ((status = sb1000_set_PIDs(ioaddr, name, PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /* set session_id, frame_id and pkt_type too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) lp->rx_session_id[0] = 0x50 | (PID[0] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) lp->rx_session_id[1] = 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) lp->rx_session_id[2] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) lp->rx_session_id[3] = 0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) lp->rx_frame_id[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) lp->rx_frame_id[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) lp->rx_frame_id[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) lp->rx_frame_id[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* transmit function: do nothing since SB1000 can't send anything out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static netdev_tx_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) printk(KERN_WARNING "%s: trying to transmit!!!\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* sb1000 can't xmit datagrams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* SB1000 interrupt handler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) static irqreturn_t sb1000_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) static const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) unsigned char st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) int ioaddr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct net_device *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) const int MaxRxErrorCount = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) /* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /* is it a good interrupt? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) st = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!(st & 0x08 && st & 0x20)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) printk(KERN_DEBUG "%s: entering interrupt\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) st = inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (sb1000_rx(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) lp->rx_error_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) #ifdef SB1000_DELAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) udelay(SB1000_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) #endif /* SB1000_DELAY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (st & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) sb1000_error_dpc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (lp->rx_error_dpc_count && !(--lp->rx_error_dpc_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) sb1000_send_command(ioaddr, name, Command0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) sb1000_wait_for_ready(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (lp->rx_error_count >= MaxRxErrorCount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) sb1000_send_command(ioaddr, name, Command1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) sb1000_wait_for_ready(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) lp->rx_error_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static int sb1000_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) int ioaddr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (sb1000_debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) printk(KERN_DEBUG "%s: Shutting down sb1000.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* If we don't do this, we can't re-insmod it later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) release_region(ioaddr[1], SB1000_IO_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) release_region(ioaddr[0], SB1000_IO_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* free rx_skb's if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) for (i=0; i<4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (lp->rx_skb[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) dev_kfree_skb(lp->rx_skb[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) MODULE_AUTHOR("Franco Venturi <fventuri@mediaone.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) MODULE_DESCRIPTION("General Instruments SB1000 driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) module_pnp_driver(sb1000_driver);