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