11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************************************************
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Filename:		donauboe.c
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Version: 		2.17
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description:   Driver for the Toshiba OBOE (or type-O or 701)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                FIR Chipset, also supports the DONAUOBOE (type-DO
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                or d01) FIR chipset which as far as I know is
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                register compatible.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation: http://libxg.free.fr/irda/lib-irda.html
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Status:        Experimental.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author:        James McKenzie <james@fishsoup.dhs.org>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Created at:    Sat May 8  12:35:27 1999
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified:      Paul Bristow <paul.bristow@technologist.com>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified:      Mon Nov 11 19:10:05 1999
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified:      James McKenzie <james@fishsoup.dhs.org>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified:      Thu Mar 16 12:49:00 2000 (Substantial rewrite)
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified:      Sat Apr 29 00:23:03 2000 (Added DONAUOBOE support)
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified:      Wed May 24 23:45:02 2000 (Fixed chipio_t structure)
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.13 Christian Gennerat <christian.gennerat@polytechnique.org>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.13 dim jan 07 21:57:39 2001 (tested with kernel 2.4 & irnet/ppp)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.14 Christian Gennerat <christian.gennerat@polytechnique.org>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.14 lun fev 05 17:55:59 2001 (adapted to patch-2.4.1-pre8-irda1)
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.15 Martin Lucina <mato@kotelna.sk>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.15 Fri Jun 21 20:40:59 2002 (sync with 2.4.18, substantial fixes)
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.16 Martin Lucina <mato@kotelna.sk>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.16 Sat Jun 22 18:54:29 2002 (fix freeregion, default to verbose)
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.17 Christian Gennerat <christian.gennerat@polytechnique.org>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.17 jeu sep 12 08:50:20 2002 (save_flags();cli(); replaced by spinlocks)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.18 Christian Gennerat <christian.gennerat@polytechnique.org>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified: 2.18 ven jan 10 03:14:16 2003 Change probe default options
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     This program is free software; you can redistribute it and/or
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     modify it under the terms of the GNU General Public License as
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     published by the Free Software Foundation; either version 2 of
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     the License, or (at your option) any later version.
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Neither James McKenzie nor Cambridge University admit liability nor
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     provide warranty for any of this software. This material is
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     provided "AS-IS" and at no charge.
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Applicable Models : Libretto 100/110CT and many more.
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Toshiba refers to this chip as the type-O IR port,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     or the type-DO IR port.
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************/
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Look at toshoboe.h (currently in include/net/irda) for details of */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Where to get documentation on the chip         */
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* See below for a description of the logic in this driver */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* User servicable parts */
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* USE_PROBE Create the code which probes the chip and does a few tests */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* do_probe module parameter Enable this code */
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Probe code is very useful for understanding how the hardware works */
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use it with various combinations of TT_LEN, RX_LEN */
5925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* Strongly recommended, disable if the probe fails on your machine */
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* and send me <james@fishsoup.dhs.org> the output of dmesg */
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define USE_PROBE 1
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef  USE_PROBE
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Trace Transmit ring, interrupts, Receive ring or not ? */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PROBE_VERBOSE 1
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Debug option, examine sent and received raw data */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Irdadump is better, but does not see all packets. enable it if you want. */
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DUMP_PACKETS
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MIR mode has not been tested. Some behaviour is different */
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Seems to work against an Ericsson R520 for me. -Martin */
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define USE_MIR
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Schedule back to back hardware transmits wherever possible, otherwise */
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* we need an interrupt for every frame, unset if oboe works for a bit and */
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* then hangs */
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPTIMIZE_TX
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set the number of slots in the rings */
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If you get rx/tx fifo overflows at high bitrates, you can try increasing */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* these */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RING_SIZE (OBOE_RING_SIZE_RX8 | OBOE_RING_SIZE_TX8)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_SLOTS    8
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_SLOTS    8
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Less user servicable parts below here */
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Test, Transmit and receive buffer sizes, adjust at your peril */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* remarks: nfs usually needs 1k blocks */
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* remarks: in SIR mode, CRC is received, -> RX_LEN=TX_LEN+2 */
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* remarks: test accepts large blocks. Standard is 0x80 */
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* When TT_LEN > RX_LEN (SIR mode) data is stored in successive slots. */
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* When 3 or more slots are needed for each test packet, */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* data received in the first slots is overwritten, even */
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* if OBOE_CTL_RX_HW_OWNS is not set, without any error! */
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TT_LEN      0x80
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_LEN      0xc00
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_LEN      0xc04
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Real transmitted length (SIR mode) is about 14+(2%*TX_LEN) more */
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* long than user-defined length (see async_wrap_skb) and is less then 4K */
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Real received length is (max RX_LEN) differs from user-defined */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* length only b the CRC (2 or 4 bytes) */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BUF_SAFETY  0x7a
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_BUF_SZ   (RX_LEN)
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_BUF_SZ   (TX_LEN+BUF_SAFETY)
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Logic of the netdev part of this driver                             */
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The RX ring is filled with buffers, when a packet arrives           */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* it is DMA'd into the buffer which is marked used and RxDone called  */
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* RxDone forms an skb (and checks the CRC if in SIR mode) and ships   */
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the packet off upstairs */
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The transmitter on the oboe chip can work in one of two modes       */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* for each ring->tx[] the transmitter can either                      */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* a) transmit the packet, leave the trasmitter enabled and proceed to */
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*    the next ring                                                    */
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* OR                                                                  */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* b) transmit the packet, switch off the transmitter and issue TxDone */
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All packets are entered into the ring in mode b), if the ring was   */
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* empty the transmitter is started.                                   */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If OPTIMIZE_TX is defined then in TxDone if the ring contains       */
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* more than one packet, all but the last are set to mode a) [HOWEVER  */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the hardware may not notice this, this is why we start in mode b) ] */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* then restart the transmitter                                        */
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* If OPTIMIZE_TX is not defined then we just restart the transmitter  */
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* if the ring isn't empty */
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Speed changes are delayed until the TxRing is empty                 */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* mtt is handled by generating packets with bad CRCs, before the data */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TODO: */
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* check the mtt works ok      */
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* finish the watchdog         */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* No user servicable parts below here */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
155a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h>
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h>
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/wrapper.h>
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irda.h>
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//#include <net/irda/irmod.h>
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//#include <net/irda/irlap_frame.h>
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irda_device.h>
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/crc.h>
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "donauboe.h"
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INB(port)       inb_p(port)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OUTB(val,port)  outb_p(val,port)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OUTBP(val,port) outb_p(val,port)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PROMPT  OUTB(OBOE_PROMPT_BIT,OBOE_PROMPT);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if PROBE_VERBOSE
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PROBE_DEBUG(args...) (printk (args))
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PROBE_DEBUG(args...) ;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set the DMA to be byte at a time */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONFIG0H_DMA_OFF OBOE_CONFIG0H_RCVANY
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
187a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(toshoboe_pci_tbl) = {
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, },
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ }			/* Terminating entry */
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_NAME "toshoboe"
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *driver_name = DRIVER_NAME;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int max_baud = 4000000;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_PROBE
199eb93992207dadb946a3b5cf4544957dc924a6f58Rusty Russellstatic bool do_probe = false;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************************************************/
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_checkfcs (unsigned char *buf, int len)
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  union
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  {
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    __u16 value;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    __u8 bytes[2];
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  fcs;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  fcs.value = INIT_FCS;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < len; ++i)
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    fcs.value = irda_fcs (fcs.value, *(buf++));
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
220807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet  return fcs.value == GOOD_FCS;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************************/
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Generic chip handling code */
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DUMP_PACKETS
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char dump[50];
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds_dumpbufs (unsigned char *data, int len, char tete)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint i,j;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar head=tete;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfor (i=0;i<len;i+=16) {
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    for (j=0;j<16 && i+j<len;j++) { sprintf(&dump[3*j],"%02x.",data[i+j]); }
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    dump [3*j]=0;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    IRDA_DEBUG (2, "%c%s\n",head , dump);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    head='+';
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_PROBE
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Dump the registers */
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_dumpregs (struct toshoboe_cb *self)
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u32 ringbase;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
248a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ringbase = INB (OBOE_RING_BASE0) << 10;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ringbase |= INB (OBOE_RING_BASE1) << 18;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ringbase |= INB (OBOE_RING_BASE2) << 26;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR DRIVER_NAME ": Register dump:\n");
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "Interrupts: Tx:%d Rx:%d TxUnder:%d RxOver:%d Sip:%d\n",
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->int_tx, self->int_rx, self->int_txunder, self->int_rxover,
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->int_sip);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "RX %02x TX %02x RingBase %08x\n",
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_RXSLOT), INB (OBOE_TXSLOT), ringbase);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "RING_SIZE %02x IER %02x ISR %02x\n",
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_RING_SIZE), INB (OBOE_IER), INB (OBOE_ISR));
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "CONFIG1 %02x STATUS %02x\n",
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_CONFIG1), INB (OBOE_STATUS));
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "CONFIG0 %02x%02x ENABLE %02x%02x\n",
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_CONFIG0H), INB (OBOE_CONFIG0L),
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_ENABLEH), INB (OBOE_ENABLEL));
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "NEW_PCONFIG %02x%02x CURR_PCONFIG %02x%02x\n",
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_NEW_PCONFIGH), INB (OBOE_NEW_PCONFIGL),
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_CURR_PCONFIGH), INB (OBOE_CURR_PCONFIGL));
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR "MAXLEN %02x%02x RXCOUNT %02x%02x\n",
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_MAXLENH), INB (OBOE_MAXLENL),
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          INB (OBOE_RXCOUNTL), INB (OBOE_RXCOUNTH));
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->ring)
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      int i;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ringbase = virt_to_bus (self->ring);
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR "Ring at %08x:\n", ringbase);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR "RX:");
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      for (i = 0; i < RX_SLOTS; ++i)
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        printk (" (%d,%02x)",self->ring->rx[i].len,self->ring->rx[i].control);
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk ("\n");
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR "TX:");
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      for (i = 0; i < RX_SLOTS; ++i)
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        printk (" (%d,%02x)",self->ring->tx[i].len,self->ring->tx[i].control);
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk ("\n");
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*Don't let the chip look at memory */
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_disablebm (struct toshoboe_cb *self)
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u8 command;
296a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  command &= ~PCI_COMMAND_MASTER;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  pci_write_config_byte (self->pdev, PCI_COMMAND, command);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Shutdown the chip and point the taskfile reg somewhere else */
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_stopchip (struct toshoboe_cb *self)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
308a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Disable interrupts */
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x0, OBOE_IER);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Disable DMA, Disable Rx, Disable Tx */
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (CONFIG0H_DMA_OFF, OBOE_CONFIG0H);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Disable SIR MIR FIR, Tx and Rx */
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x00, OBOE_ENABLEH);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Point the ring somewhere safe */
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x3f, OBOE_RING_BASE2);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0xff, OBOE_RING_BASE1);
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0xff, OBOE_RING_BASE0);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (RX_LEN >> 8, OBOE_MAXLENH);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Acknoledge any pending interrupts */
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0xff, OBOE_ISR);
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Why */
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*switch it off */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_CONFIG1_OFF, OBOE_CONFIG1);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_disablebm (self);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Transmitter initialization */
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_start_DMA (struct toshoboe_cb *self, int opts)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x0, OBOE_ENABLEH);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (CONFIG0H_DMA_ON | opts,  OBOE_CONFIG0H);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  PROMPT;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*Set the baud rate */
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_setbaud (struct toshoboe_cb *self)
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u16 pconfig = 0;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u8 config0l = 0;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
353a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (2, "%s(%d/%d)\n", __func__, self->speed, self->io.speed);
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  switch (self->speed)
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 2400:
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 4800:
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 9600:
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 19200:
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 38400:
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 57600:
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 115200:
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_MIR
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 1152000:
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 4000000:
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    default:
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": switch to unsupported baudrate %d\n",
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              self->speed);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      return;
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  switch (self->speed)
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* For SIR the preamble is done by adding XBOFs */
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* to the packet */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* set to filtered SIR mode, filter looks for BOF and EOF */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 2400:
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 47 << OBOE_PCONFIG_BAUDSHIFT;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 4800:
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 23 << OBOE_PCONFIG_BAUDSHIFT;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 9600:
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 11 << OBOE_PCONFIG_BAUDSHIFT;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 19200:
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 5 << OBOE_PCONFIG_BAUDSHIFT;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 38400:
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 2 << OBOE_PCONFIG_BAUDSHIFT;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 57600:
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 1 << OBOE_PCONFIG_BAUDSHIFT;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 115200:
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    default:
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /*Set to packet based reception */
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      OUTB (RX_LEN >> 8, OBOE_MAXLENH);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  switch (self->speed)
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 2400:
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 4800:
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 9600:
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 19200:
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 38400:
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 57600:
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 115200:
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      config0l = OBOE_CONFIG0L_ENSIR;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (self->async)
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /*Set to character based reception */
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /*System will lock if MAXLEN=0 */
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /*so have to be careful */
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          OUTB (0x01, OBOE_MAXLENH);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          OUTB (0x01, OBOE_MAXLENL);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          OUTB (0x00, OBOE_MAXLENH);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      else
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /*Set to packet based reception */
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          config0l |= OBOE_CONFIG0L_ENSIRF;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          OUTB (RX_LEN >> 8, OBOE_MAXLENH);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_MIR
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* MIR mode */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Set for 16 bit CRC and enable MIR */
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Preamble now handled by the chip */
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 1152000:
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 8 << OBOE_PCONFIG_WIDTHSHIFT;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 1 << OBOE_PCONFIG_PREAMBLESHIFT;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      config0l = OBOE_CONFIG0L_CRC16 | OBOE_CONFIG0L_ENMIR;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* FIR mode */
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Set for 32 bit CRC and enable FIR */
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Preamble handled by the chip */
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case 4000000:
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Documentation says 14, but toshiba use 15 in their drivers */
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      pconfig |= 15 << OBOE_PCONFIG_PREAMBLESHIFT;
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      config0l = OBOE_CONFIG0L_ENFIR;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Copy into new PHY config buffer */
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTBP (pconfig >> 8, OBOE_NEW_PCONFIGH);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (pconfig & 0xff, OBOE_NEW_PCONFIGL);
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (config0l, OBOE_CONFIG0L);
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Now make OBOE copy from new PHY to current PHY */
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x0, OBOE_ENABLEH);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  PROMPT;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* speed change executed */
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->new_speed = 0;
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->io.speed = self->speed;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*Let the chip look at memory */
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_enablebm (struct toshoboe_cb *self)
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
485a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  pci_set_master (self->pdev);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*setup the ring */
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_initring (struct toshoboe_cb *self)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
495a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < TX_SLOTS; ++i)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[i].len = 0;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[i].control = 0x00;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[i].address = virt_to_bus (self->tx_bufs[i]);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->rx[i].len = RX_LEN;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->rx[i].len = 0;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->rx[i].address = virt_to_bus (self->rx_bufs[i]);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->rx[i].control = OBOE_CTL_RX_HW_OWNS;
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_resetptrs (struct toshoboe_cb *self)
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Can reset pointers by twidling DMA */
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x0, OBOE_ENABLEH);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTBP (CONFIG0H_DMA_OFF, OBOE_CONFIG0H);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->rxs = inb_p (OBOE_RXSLOT) & OBOE_SLOT_MASK;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->txs = inb_p (OBOE_TXSLOT) & OBOE_SLOT_MASK;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Called in locked state */
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_initptrs (struct toshoboe_cb *self)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* spin_lock_irqsave(self->spinlock, flags); */
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* save_flags (flags); */
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Can reset pointers by twidling DMA */
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_resetptrs (self);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0x0, OBOE_ENABLEH);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->txpending = 0;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* spin_unlock_irqrestore(self->spinlock, flags); */
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* restore_flags (flags); */
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Wake the chip up and get it looking at the rings */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Called in locked state */
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_startchip (struct toshoboe_cb *self)
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u32 physaddr;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
553a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_initring (self);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_enablebm (self);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTBP (OBOE_CONFIG1_RESET, OBOE_CONFIG1);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTBP (OBOE_CONFIG1_ON, OBOE_CONFIG1);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Stop the clocks */
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0, OBOE_ENABLEH);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Set size of rings */
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (RING_SIZE, OBOE_RING_SIZE);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Acknoledge any pending interrupts */
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0xff, OBOE_ISR);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Enable ints */
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_INT_TXDONE  | OBOE_INT_RXDONE |
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        OBOE_INT_TXUNDER | OBOE_INT_RXOVER | OBOE_INT_SIP , OBOE_IER);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Acknoledge any pending interrupts */
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (0xff, OBOE_ISR);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Set the maximum packet length to 0xfff (4095) */
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (RX_LEN >> 8, OBOE_MAXLENH);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (RX_LEN & 0xff, OBOE_MAXLENL);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Shutdown DMA */
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (CONFIG0H_DMA_OFF, OBOE_CONFIG0H);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Find out where the rings live */
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  physaddr = virt_to_bus (self->ring);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  IRDA_ASSERT ((physaddr & 0x3ff) == 0,
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       printk (KERN_ERR DRIVER_NAME "ring not correctly aligned\n");
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       return;);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB ((physaddr >> 10) & 0xff, OBOE_RING_BASE0);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB ((physaddr >> 18) & 0xff, OBOE_RING_BASE1);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB ((physaddr >> 26) & 0x3f, OBOE_RING_BASE2);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5943a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. Day  /*Enable DMA controller in byte mode and RX */
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Start up the clocks */
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*set to sensible speed */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->speed = 9600;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_setbaud (self);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_initptrs (self);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_isntstuck (struct toshoboe_cb *self)
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_checkstuck (struct toshoboe_cb *self)
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (0)
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_lock_irqsave(&self->spinlock, flags);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* This will reset the chip completely */
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": Resetting chip\n");
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_stopchip (self);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_startchip (self);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_unlock_irqrestore(&self->spinlock, flags);
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*Generate packet of about mtt us long */
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_makemttpacket (struct toshoboe_cb *self, void *buf, int mtt)
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int xbofs;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  xbofs = ((int) (mtt/100)) * (int) (self->speed);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  xbofs=xbofs/80000; /*Eight bits per byte, and mtt is in us*/
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  xbofs++;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  IRDA_DEBUG (2, DRIVER_NAME
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ": generated mtt of %d bytes for %d us at %d baud\n"
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  , xbofs,mtt,self->speed);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (xbofs > TX_LEN)
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": wanted %d bytes MTT but TX_LEN is %d\n",
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              xbofs, TX_LEN);
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      xbofs = TX_LEN;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*xbofs will do for SIR, MIR and FIR,SIR mode doesn't generate a checksum anyway */
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memset (buf, XBOF, xbofs);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return xbofs;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_PROBE
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************************/
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Probe code */
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_dumptx (struct toshoboe_cb *self)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  PROBE_DEBUG(KERN_WARNING "TX:");
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    PROBE_DEBUG(" (%d,%02x)",self->ring->tx[i].len,self->ring->tx[i].control);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  PROBE_DEBUG(" [%d]\n",self->speed);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_dumprx (struct toshoboe_cb *self, int score)
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  PROBE_DEBUG(" %d\nRX:",score);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    PROBE_DEBUG(" (%d,%02x)",self->ring->rx[i].len,self->ring->rx[i].control);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  PROBE_DEBUG("\n");
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstuff_byte (__u8 byte, __u8 * buf)
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  switch (byte)
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case BOF:                  /* FALLTHROUGH */
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case EOF:                  /* FALLTHROUGH */
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case CE:
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Insert transparently coded */
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      buf[0] = CE;              /* Send link escape */
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      buf[1] = byte ^ IRDA_TRANS; /* Complement bit 5 */
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      return 2;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* break; */
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    default:
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Non-special value, no transparency required */
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      buf[0] = byte;
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      return 1;
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* break; */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
7027d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellstoshoboe_probeinterrupt (int irq, void *dev_id)
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
704c31f28e778ab299a5035ea2bda64f245b8915d7cJeff Garzik  struct toshoboe_cb *self = dev_id;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u8 irqstat;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  irqstat = INB (OBOE_ISR);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* was it us */
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!(irqstat & OBOE_INT_MASK))
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return IRQ_NONE;
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Ack all the interrupts */
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (irqstat, OBOE_ISR);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_TXDONE)
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      int txp;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->int_tx++;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      PROBE_DEBUG("T");
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS)
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->int_tx+=100;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          PROBE_DEBUG("S");
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_RXDONE) {
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->int_rx++;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    PROBE_DEBUG("R"); }
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_TXUNDER) {
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->int_txunder++;
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    PROBE_DEBUG("U"); }
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_RXOVER) {
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->int_rxover++;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    PROBE_DEBUG("O"); }
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_SIP) {
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->int_sip++;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    PROBE_DEBUG("I"); }
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return IRQ_HANDLED;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_maketestpacket (unsigned char *buf, int badcrc, int fir)
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int len = 0;
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  union
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  {
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    __u16 value;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    __u8 bytes[2];
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  fcs;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (fir)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      memset (buf, 0, TT_LEN);
762807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet      return TT_LEN;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  fcs.value = INIT_FCS;
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memset (buf, XBOF, 10);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  len += 10;
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  buf[len++] = BOF;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < TT_LEN; ++i)
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      len += stuff_byte (i, buf + len);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      fcs.value = irda_fcs (fcs.value, i);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  len += stuff_byte (fcs.bytes[0] ^ badcrc, buf + len);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  len += stuff_byte (fcs.bytes[1] ^ badcrc, buf + len);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  buf[len++] = EOF;
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  len++;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return len;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_probefail (struct toshoboe_cb *self, char *msg)
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_ERR DRIVER_NAME "probe(%d) failed %s\n",self-> speed, msg);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_dumpregs (self);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_stopchip (self);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  free_irq (self->io.irq, (void *) self);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_numvalidrcvs (struct toshoboe_cb *self)
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i, ret = 0;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if ((self->ring->rx[i].control & 0xe0) == 0)
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ret++;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return ret;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_numrcvs (struct toshoboe_cb *self)
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i, ret = 0;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (!(self->ring->rx[i].control & OBOE_CTL_RX_HW_OWNS))
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ret++;
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return ret;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_probe (struct toshoboe_cb *self)
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i, j, n;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_MIR
821215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches  static const int bauds[] = { 9600, 115200, 4000000, 1152000 };
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
823215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches  static const int bauds[] = { 9600, 115200, 4000000 };
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
827a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (request_irq (self->io.irq, toshoboe_probeinterrupt,
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                   self->io.irqflags, "toshoboe", (void *) self))
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": probe failed to allocate irq %d\n",
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              self->io.irq);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      return 0;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* test 1: SIR filter and back to back */
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
839e9edda697ed7697f1288d0656570e49c47e204aeAlejandro Martinez Ruiz  for (j = 0; j < ARRAY_SIZE(bauds); ++j)
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      int fir = (j > 1);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_stopchip (self);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_lock_irqsave(&self->spinlock, flags);
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /*Address is already setup */
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_startchip (self);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->int_rx = self->int_tx = 0;
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->speed = bauds[j];
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_setbaud (self);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_initptrs (self);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_unlock_irqrestore(&self->spinlock, flags);
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].control =
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*   (FIR only) OBOE_CTL_TX_SIP needed for switching to next slot */
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*    MIR: all received data is stored in one slot */
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              : OBOE_CTL_TX_HW_OWNS ;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].len =
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs++;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs %= TX_SLOTS;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].control =
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_SIP
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              : OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX ;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].len =
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs++;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs %= TX_SLOTS;
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].control =
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              : OBOE_CTL_TX_HW_OWNS ;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].len =
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs++;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs %= TX_SLOTS;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].control =
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              | OBOE_CTL_TX_SIP     | OBOE_CTL_TX_BAD_CRC
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              : OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX ;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->ring->tx[self->txs].len =
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs++;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txs %= TX_SLOTS;
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_dumptx (self);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Turn on TX and RX and loopback */
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      i = 0;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      n = fir ? 1 : 4;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      while (toshoboe_numvalidrcvs (self) != n)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (i > 4800)
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              return toshoboe_probefail (self, "filter test");
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          udelay ((9600*(TT_LEN+16))/self->speed);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          i++;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      n = fir ? 203 : 102;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      while ((toshoboe_numrcvs(self) != self->int_rx) || (self->int_tx != n))
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (i > 4800)
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              return toshoboe_probefail (self, "interrupt test");
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          udelay ((9600*(TT_LEN+16))/self->speed);
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          i++;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     toshoboe_dumprx (self,i);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     }
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* test 2: SIR in char at a time */
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_stopchip (self);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->int_rx = self->int_tx = 0;
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_irqsave(&self->spinlock, flags);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_startchip (self);
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_unlock_irqrestore(&self->spinlock, flags);
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->async = 1;
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->speed = 115200;
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_setbaud (self);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->ring->tx[self->txs].control =
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    OBOE_CTL_TX_RTCENTX | OBOE_CTL_TX_HW_OWNS;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->ring->tx[self->txs].len = 4;
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ((unsigned char *) self->tx_bufs[self->txs])[0] = 'f';
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ((unsigned char *) self->tx_bufs[self->txs])[1] = 'i';
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ((unsigned char *) self->tx_bufs[self->txs])[2] = 's';
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ((unsigned char *) self->tx_bufs[self->txs])[3] = 'h';
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_dumptx (self);
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  i = 0;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  while (toshoboe_numvalidrcvs (self) != 4)
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (i > 100)
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          return toshoboe_probefail (self, "Async test");
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      udelay (100);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      i++;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  while ((toshoboe_numrcvs (self) != self->int_rx) || (self->int_tx != 1))
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (i > 100)
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          return toshoboe_probefail (self, "Async interrupt test");
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      udelay (100);
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      i++;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_dumprx (self,i);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->async = 0;
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->speed = 9600;
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_setbaud (self);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_stopchip (self);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  free_irq (self->io.irq, (void *) self);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_WARNING DRIVER_NAME ": Self test passed ok\n");
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 1;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Netdev style code */
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Transmit something */
9736518bbb803fe02b15a3211c8db2afdff0ac4f808Stephen Hemmingerstatic netdev_tx_t
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __s32 speed;
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int mtt, len, ctl;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9824cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen  self = netdev_priv(dev);
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
984ec634fe328182a1a098585bfc7b69e5042bdb08dPatrick McHardy  IRDA_ASSERT (self != NULL, return NETDEV_TX_OK; );
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
986a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __func__
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ,skb->len,self->txpending,INB (OBOE_ENABLEH));
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!cb->magic) {
989a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (2, "%s.Not IrLAP:%x\n", __func__, cb->magic);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DUMP_PACKETS
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      _dumpbufs(skb->data,skb->len,'>');
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* change speed pending, wait for its execution */
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->new_speed)
9974bd73ae2682d9069746bb049a416d9ab90c6684bPatrick McHardy      return NETDEV_TX_BUSY;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* device stopped (apm) wait for restart */
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->stopped)
10014bd73ae2682d9069746bb049a416d9ab90c6684bPatrick McHardy      return NETDEV_TX_BUSY;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_checkstuck (self);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check if we need to change the speed */
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* But not now. Wait after transmission if mtt not required */
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  speed=irda_get_next_speed(skb);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if ((speed != self->io.speed) && (speed != -1))
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_lock_irqsave(&self->spinlock, flags);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (self->txpending || skb->len)
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->new_speed = speed;
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          IRDA_DEBUG (1, "%s: Queued TxDone scheduled speed change %d\n" ,
1016a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison		      __func__, speed);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* if no data, that's all! */
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (!skb->len)
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            {
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      spin_unlock_irqrestore(&self->spinlock, flags);
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              dev_kfree_skb (skb);
10226ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy              return NETDEV_TX_OK;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            }
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* True packet, go on, but */
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* do not accept anything before change speed execution */
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          netif_stop_queue(dev);
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* ready to process TxDone interrupt */
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  spin_unlock_irqrestore(&self->spinlock, flags);
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      else
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* idle and no data, change speed now */
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->speed = speed;
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          toshoboe_setbaud (self);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  spin_unlock_irqrestore(&self->spinlock, flags);
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          dev_kfree_skb (skb);
10376ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy          return NETDEV_TX_OK;
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if ((mtt = irda_get_mtt(skb)))
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* This is fair since the queue should be empty anyway */
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_lock_irqsave(&self->spinlock, flags);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (self->txpending)
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  spin_unlock_irqrestore(&self->spinlock, flags);
10504bd73ae2682d9069746bb049a416d9ab90c6684bPatrick McHardy          return NETDEV_TX_BUSY;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* If in SIR mode we need to generate a string of XBOFs */
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* In MIR and FIR we need to generate a string of data */
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* which we will add a wrong checksum to */
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      mtt = toshoboe_makemttpacket (self, self->tx_bufs[self->txs], mtt);
1058a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (1, "%s.mtt:%x(%x)%d\n", __func__
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ,skb->len,mtt,self->txpending);
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (mtt)
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->ring->tx[self->txs].len = mtt & 0xfff;
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX;
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON)
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            {
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              ctl |= OBOE_CTL_TX_BAD_CRC | OBOE_CTL_TX_SIP ;
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            }
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_MIR
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          else if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_MIRON)
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            {
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              ctl |= OBOE_CTL_TX_BAD_CRC;
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            }
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->ring->tx[self->txs].control = ctl;
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          OUTB (0x0, OBOE_ENABLEH);
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          /* It is only a timer. Do not send mtt packet outside! */
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP);
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->txpending++;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->txs++;
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->txs %= TX_SLOTS;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      else
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          printk(KERN_ERR DRIVER_NAME ": problem with mtt packet - ignored\n");
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_unlock_irqrestore(&self->spinlock, flags);
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DUMP_PACKETS
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdumpbufs(skb->data,skb->len,'>');
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_irqsave(&self->spinlock, flags);
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->ring->tx[self->txs].control & OBOE_CTL_TX_HW_OWNS)
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
1102a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (0, "%s.ful:%x(%x)%x\n", __func__
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ,skb->len, self->ring->tx[self->txs].control, self->txpending);
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      spin_unlock_irqrestore(&self->spinlock, flags);
11064bd73ae2682d9069746bb049a416d9ab90c6684bPatrick McHardy      return NETDEV_TX_BUSY;
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON)
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      len = async_wrap_skb (skb, self->tx_bufs[self->txs], TX_BUF_SZ);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  else
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      len = skb->len;
1116d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo      skb_copy_from_linear_data(skb, self->tx_bufs[self->txs], len);
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->ring->tx[self->txs].len = len & 0x0fff;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*Sometimes the HW doesn't see us assert RTCENTX in the interrupt code */
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*later this plays safe, we garuntee the last packet to be transmitted */
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*has RTCENTX set */
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX;
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON)
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ctl |= OBOE_CTL_TX_SIP ;
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->ring->tx[self->txs].control = ctl;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* If transmitter is idle start in one-shot mode */
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!self->txpending)
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->txpending++;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->txs++;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->txs %= TX_SLOTS;
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_unlock_irqrestore(&self->spinlock, flags);
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  dev_kfree_skb (skb);
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11446ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy  return NETDEV_TX_OK;
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*interrupt handler */
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
11497d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellstoshoboe_interrupt (int irq, void *dev_id)
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
115115e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik  struct toshoboe_cb *self = dev_id;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  __u8 irqstat;
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct sk_buff *skb = NULL;
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  irqstat = INB (OBOE_ISR);
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* was it us */
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!(irqstat & OBOE_INT_MASK))
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      return IRQ_NONE;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Ack all the interrupts */
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  OUTB (irqstat, OBOE_ISR);
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_isntstuck (self);
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Txdone */
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_TXDONE)
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      int txp, txpc;
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      int i;
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      txp = self->txpending;
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->txpending = 0;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      for (i = 0; i < TX_SLOTS; ++i)
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (self->ring->tx[i].control & OBOE_CTL_TX_HW_OWNS)
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              self->txpending++;
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
1180a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (1, "%s.txd(%x)%x/%x\n", __func__
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ,irqstat,txp,self->txpending);
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK;
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Got anything queued ? start it together */
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS)
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          txpc = txp;
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef OPTIMIZE_TX
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          while (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            {
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              txp = txpc;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              txpc++;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              txpc %= TX_SLOTS;
1195216c32d4407ea6951d6832773fdb3de058e12c62Alexander Beregalov              self->netdev->stats.tx_packets++;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX;
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            }
1199216c32d4407ea6951d6832773fdb3de058e12c62Alexander Beregalov          self->netdev->stats.tx_packets--;
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
1201216c32d4407ea6951d6832773fdb3de058e12c62Alexander Beregalov          self->netdev->stats.tx_packets++;
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if ((!self->txpending) && (self->new_speed))
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->speed = self->new_speed;
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          IRDA_DEBUG (1, "%s: Executed TxDone scheduled speed change %d\n",
1210a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison		      __func__, self->speed);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          toshoboe_setbaud (self);
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Tell network layer that we want more frames */
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (!self->new_speed)
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          netif_wake_queue(self->netdev);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_RXDONE)
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      while (!(self->ring->rx[self->rxs].control & OBOE_CTL_RX_HW_OWNS))
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          int len = self->ring->rx[self->rxs].len;
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          skb = NULL;
1225a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison          IRDA_DEBUG (3, "%s.rcv:%x(%x)\n", __func__
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      ,len,self->ring->rx[self->rxs].control);
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DUMP_PACKETS
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdumpbufs(self->rx_bufs[self->rxs],len,'<');
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (self->ring->rx[self->rxs].control == 0)
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            {
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              __u8 enable = INB (OBOE_ENABLEH);
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              /* In SIR mode we need to check the CRC as this */
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              /* hasn't been done by the hardware */
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              if (enable & OBOE_ENABLEH_SIRON)
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  if (!toshoboe_checkfcs (self->rx_bufs[self->rxs], len))
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len = 0;
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  /*Trim off the CRC */
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  if (len > 1)
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len -= 2;
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  else
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len = 0;
1247a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison                  IRDA_DEBUG (1, "%s.SIR:%x(%x)\n", __func__, len,enable);
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_MIR
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              else if (enable & OBOE_ENABLEH_MIRON)
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  if (len > 1)
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len -= 2;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  else
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len = 0;
1257a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison                  IRDA_DEBUG (2, "%s.MIR:%x(%x)\n", __func__, len,enable);
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              else if (enable & OBOE_ENABLEH_FIRON)
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  if (len > 3)
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len -= 4;   /*FIXME: check this */
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  else
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      len = 0;
1266a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison                  IRDA_DEBUG (1, "%s.FIR:%x(%x)\n", __func__, len,enable);
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              else
1269a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison                  IRDA_DEBUG (0, "%s.?IR:%x(%x)\n", __func__, len,enable);
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              if (len)
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  skb = dev_alloc_skb (len + 1);
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  if (skb)
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                    {
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      skb_reserve (skb, 1);
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      skb_put (skb, len);
127927d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo                      skb_copy_to_linear_data(skb, self->rx_bufs[self->rxs],
128027d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo					      len);
1281216c32d4407ea6951d6832773fdb3de058e12c62Alexander Beregalov                      self->netdev->stats.rx_packets++;
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      skb->dev = self->netdev;
1283459a98ed881802dee55897441bc7f77af614368eArnaldo Carvalho de Melo                      skb_reset_mac_header(skb);
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      skb->protocol = htons (ETH_P_IRDA);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                    }
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                  else
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                    {
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                      printk (KERN_INFO
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                              "%s(), memory squeeze, dropping frame.\n",
1290a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison			      __func__);
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                    }
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            }
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          else
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            {
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            /* TODO: =========================================== */
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            /*  if OBOE_CTL_RX_LENGTH, our buffers are too small */
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            /* (MIR or FIR) data is lost. */
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            /* (SIR) data is splitted in several slots. */
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            /* we have to join all the received buffers received */
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            /*in a large buffer before checking CRC. */
1302a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison            IRDA_DEBUG (0, "%s.err:%x(%x)\n", __func__
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                ,len,self->ring->rx[self->rxs].control);
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            }
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->ring->rx[self->rxs].len = 0x0;
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->ring->rx[self->rxs].control = OBOE_CTL_RX_HW_OWNS;
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->rxs++;
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          self->rxs %= RX_SLOTS;
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          if (skb)
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              netif_rx (skb);
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_TXUNDER)
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_WARNING DRIVER_NAME ": tx fifo underflow\n");
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_RXOVER)
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_WARNING DRIVER_NAME ": rx fifo overflow\n");
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This must be useful for something... */
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (irqstat & OBOE_INT_SIP)
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->int_sip++;
1330a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (1, "%s.sip:%x(%x)%x\n", __func__
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      ,self->int_sip,irqstat,self->txpending);
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return IRQ_HANDLED;
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_net_open (struct net_device *dev)
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self;
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
134215e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik  int rc;
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1344a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
134615e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik  self = netdev_priv(dev);
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->async)
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -EBUSY;
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->stopped)
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
135415e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik  rc = request_irq (self->io.irq, toshoboe_interrupt,
135515e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik                    IRQF_SHARED | IRQF_DISABLED, dev->name, self);
135615e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik  if (rc)
135715e541feb340bc2a4caaf707ee5ad71a47fdd068Jeff Garzik  	return rc;
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_irqsave(&self->spinlock, flags);
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_startchip (self);
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_unlock_irqrestore(&self->spinlock, flags);
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Ready to play! */
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  netif_start_queue(dev);
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   * Open new IrLAP layer instance, now that everything should be
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   * initialized properly
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   */
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->irlap = irlap_open (dev, &self->qos, driver_name);
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->irdad = 1;
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_net_close (struct net_device *dev)
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self;
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1382a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  IRDA_ASSERT (dev != NULL, return -1; );
13854cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen  self = netdev_priv(dev);
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Stop device */
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  netif_stop_queue(dev);
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Stop and remove instance of IrLAP */
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (self->irlap)
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    irlap_close (self->irlap);
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->irlap = NULL;
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->irdad = 0;
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  free_irq (self->io.irq, (void *) self);
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!self->stopped)
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_stopchip (self);
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function toshoboe_net_ioctl (dev, rq, cmd)
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Process IOCTL commands for this device
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct if_irda_req *irq = (struct if_irda_req *) rq;
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self;
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int ret = 0;
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  IRDA_ASSERT (dev != NULL, return -1; );
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14234cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen  self = netdev_priv(dev);
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  IRDA_ASSERT (self != NULL, return -1; );
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1427a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (5, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd);
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Disable interrupts & save flags */
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_irqsave(&self->spinlock, flags);
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  switch (cmd)
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case SIOCSBANDWIDTH:       /* Set bandwidth */
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* This function will also be used by IrLAP to change the
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       * speed, so we still must allow for speed change within
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       * interrupt context.
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       */
1439a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (1, "%s(BANDWIDTH), %s, (%X/%ld\n", __func__
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ,dev->name, INB (OBOE_STATUS), irq->ifr_baudrate );
1441ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton      if (!in_interrupt () && !capable (CAP_NET_ADMIN)) {
1442ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton	ret = -EPERM;
1443ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton	goto out;
1444ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton      }
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* self->speed=irq->ifr_baudrate; */
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* toshoboe_setbaud(self); */
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      /* Just change speed once - inserted by Paul Bristow */
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->new_speed = irq->ifr_baudrate;
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case SIOCSMEDIABUSY:       /* Set media busy */
1452a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (1, "%s(MEDIABUSY), %s, (%X/%x)\n", __func__
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ,dev->name, INB (OBOE_STATUS), capable (CAP_NET_ADMIN) );
1454ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton      if (!capable (CAP_NET_ADMIN)) {
1455ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton	ret = -EPERM;
1456ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton	goto out;
1457ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Morton      }
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      irda_device_set_media_busy (self->netdev, TRUE);
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case SIOCGRECEIVING:       /* Check if we are receiving right now */
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      irq->ifr_receiving = (INB (OBOE_STATUS) & OBOE_STATUS_RXBUSY) ? 1 : 0;
1462a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (3, "%s(RECEIVING), %s, (%X/%x)\n", __func__
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          ,dev->name, INB (OBOE_STATUS), irq->ifr_receiving );
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      break;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    default:
1466a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison      IRDA_DEBUG (1, "%s(?), %s, (cmd=0x%X)\n", __func__, dev->name, cmd);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      ret = -EOPNOTSUPP;
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
1469ac7c98eca88a854755475fcfe1b2bf5f97f90d99Andrew Mortonout:
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_unlock_irqrestore(&self->spinlock, flags);
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return ret;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param (max_baud, int, 0);
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_baud, "Maximum baud rate");
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_PROBE
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param (do_probe, bool, 0);
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(do_probe, "Enable/disable chip probing and self-test");
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_close (struct pci_dev *pci_dev)
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i;
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1493a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  IRDA_ASSERT (self != NULL, return; );
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!self->stopped)
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      toshoboe_stopchip (self);
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  release_region (self->io.fir_base, self->io.fir_ext);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < TX_SLOTS; ++i)
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      kfree (self->tx_bufs[i]);
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->tx_bufs[i] = NULL;
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      kfree (self->rx_bufs[i]);
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->rx_bufs[i] = NULL;
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unregister_netdev(self->netdev);
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  kfree (self->ringbuf);
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->ringbuf = NULL;
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->ring = NULL;
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  free_netdev(self->netdev);
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1525ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemmingerstatic const struct net_device_ops toshoboe_netdev_ops = {
1526ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger	.ndo_open	= toshoboe_net_open,
1527ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger	.ndo_stop	= toshoboe_net_close,
1528ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger	.ndo_start_xmit	= toshoboe_hard_xmit,
1529ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger	.ndo_do_ioctl	= toshoboe_net_ioctl,
1530ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger};
1531ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct net_device *dev;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i = 0;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int ok = 0;
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int err;
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if ((err=pci_enable_device(pci_dev)))
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return err;
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  dev = alloc_irdadev(sizeof (struct toshoboe_cb));
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (dev == NULL)
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": can't allocate memory for "
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              "IrDA control block\n");
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      return -ENOMEM;
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15544cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen  self = netdev_priv(dev);
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->netdev = dev;
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->pdev = pci_dev;
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->base = pci_resource_start(pci_dev,0);
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->io.fir_base = self->base;
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->io.fir_ext = OBOE_IO_EXTENT;
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->io.irq = pci_dev->irq;
15621fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner  self->io.irqflags = IRQF_SHARED | IRQF_DISABLED;
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->speed = self->io.speed = 9600;
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->async = 0;
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Lock the port that we need */
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (NULL==request_region (self->io.fir_base, self->io.fir_ext, driver_name))
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": can't get iobase of 0x%03x\n"
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      ,self->io.fir_base);
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      err = -EBUSY;
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      goto freeself;
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_init(&self->spinlock);
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  irda_init_max_qos_capabilies (&self->qos);
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->qos.baud_rate.bits = 0;
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (max_baud >= 2400)
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->qos.baud_rate.bits |= IR_2400;
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (max_baud >= 9600)
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->qos.baud_rate.bits |= IR_9600;
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (max_baud >= 19200)
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->qos.baud_rate.bits |= IR_19200;
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (max_baud >= 115200)
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->qos.baud_rate.bits |= IR_115200;
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_MIR
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (max_baud >= 1152000)
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->qos.baud_rate.bits |= IR_1152000;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (max_baud >= 4000000)
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->qos.baud_rate.bits |= (IR_4000000 << 8);
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*FIXME: work this out... */
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->qos.min_turn_time.bits = 0xff;
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  irda_qos_bits_to_value (&self->qos);
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Allocate twice the size to guarantee alignment */
16075cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day  self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL);
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!self->ringbuf)
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      err = -ENOMEM;
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      goto freeregion;
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if (BITS_PER_LONG == 64)
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#error broken on 64-bit:  casts pointer to 32-bit, and then back to pointer.
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /*We need to align the taskfile on a taskfile size boundary */
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  {
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    unsigned long addr;
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    addr = (__u32) self->ringbuf;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    addr &= ~(OBOE_RING_LEN - 1);
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    addr += OBOE_RING_LEN;
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    self->ring = (struct OboeRing *) addr;
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memset (self->ring, 0, OBOE_RING_LEN);
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->io.mem_base = (__u32) self->ring;
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  ok = 1;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < TX_SLOTS; ++i)
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->tx_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL);
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (!self->tx_bufs[i])
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ok = 0;
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      self->rx_bufs[i] = kmalloc (RX_BUF_SZ, GFP_KERNEL);
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      if (!self->rx_bufs[i])
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ok = 0;
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!ok)
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      err = -ENOMEM;
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      goto freebufs;
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef USE_PROBE
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (do_probe)
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (!toshoboe_probe (self))
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      {
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = -ENODEV;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        goto freebufs;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      }
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  SET_NETDEV_DEV(dev, &pci_dev->dev);
1663ddec2c89f89b9f2d15ddff07f01570123e95f544Stephen Hemminger  dev->netdev_ops = &toshoboe_netdev_ops;
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  err = register_netdev(dev);
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (err)
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    {
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      printk (KERN_ERR DRIVER_NAME ": register_netdev() failed\n");
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      err = -ENOMEM;
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      goto freebufs;
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  printk (KERN_INFO "IrDA: Registered device %s\n", dev->name);
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  pci_set_drvdata(pci_dev,self);
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1676d4c3c0753594adaafbcb77a086f013f1d847b3f0Adrian Bunk  printk (KERN_INFO DRIVER_NAME ": Using multiple tasks\n");
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreebufs:
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < TX_SLOTS; ++i)
1682b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl    kfree (self->tx_bufs[i]);
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  for (i = 0; i < RX_SLOTS; ++i)
1684b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl    kfree (self->rx_bufs[i]);
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  kfree(self->ringbuf);
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreeregion:
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  release_region (self->io.fir_base, self->io.fir_ext);
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreeself:
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  free_netdev(dev);
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return err;
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_gotosleep (struct pci_dev *pci_dev, pm_message_t crap)
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int i = 10;
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1703a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!self || self->stopped)
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if ((!self->irdad) && (!self->async))
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Flush all packets */
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  while ((i--) && (self->txpending))
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    udelay (10000);
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_irqsave(&self->spinlock, flags);
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_stopchip (self);
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->stopped = 1;
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->txpending = 0;
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_unlock_irqrestore(&self->spinlock, flags);
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstoshoboe_wakeup (struct pci_dev *pci_dev)
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  unsigned long flags;
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731a97a6f10771b90235b33c13a6db9279237a08422Harvey Harrison  IRDA_DEBUG (4, "%s()\n", __func__);
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!self || !self->stopped)
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if ((!self->irdad) && (!self->async))
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_lock_irqsave(&self->spinlock, flags);
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  toshoboe_startchip (self);
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  self->stopped = 0;
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  netif_wake_queue(self->netdev);
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  spin_unlock_irqrestore(&self->spinlock, flags);
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver donauboe_pci_driver = {
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "donauboe",
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= toshoboe_pci_tbl,
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= toshoboe_open,
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= toshoboe_close,
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= toshoboe_gotosleep,
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= toshoboe_wakeup
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdonauboe_init (void)
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1761a85d771e32f9724b61a68748cc667d1e11fe3478Christophe Lucas  return pci_register_driver(&donauboe_pci_driver);
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdonauboe_cleanup (void)
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  pci_unregister_driver(&donauboe_pci_driver);
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(donauboe_init);
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(donauboe_cleanup);
1772