nsc-ircc.c revision 3b99b93baba4cbf4fd3d206e65e81a070b21b560
195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/********************************************************************* 295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Filename: nsc-ircc.c 495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Version: 1.0 595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Description: Driver for the NSC PC'108 and PC'338 IrDA chipsets 6e47dfcd81edb7c6065fd2219c818b3b526bd624dGuo-Fu Tseng * Status: Stable. 795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Author: Dag Brattli <dagb@cs.uit.no> 895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Created at: Sat Nov 7 21:43:15 1998 995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Modified at: Wed Mar 1 11:29:34 2000 1095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Modified by: Dag Brattli <dagb@cs.uit.no> 1195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 1295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> 1395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> 1495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Copyright (c) 1998 Actisys Corp., www.actisys.com 1595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Copyright (c) 2000-2004 Jean Tourrilhes <jt@hpl.hp.com> 1695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * All Rights Reserved 1795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 1895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This program is free software; you can redistribute it and/or 1995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * modify it under the terms of the GNU General Public License as 2095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * published by the Free Software Foundation; either version 2 of 2195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the License, or (at your option) any later version. 2295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 2395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Neither Dag Brattli nor University of Troms� admit liability nor 2495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * provide warranty for any of this software. This material is 2549d70c4856acfce943fab35fc199b3074961313fJoe Perches * provided "AS-IS" and at no charge. 2649d70c4856acfce943fab35fc199b3074961313fJoe Perches * 2795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Notice that all functions that needs to access the chip in _any_ 2895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * way, must save BSR register on entry, and restore it on exit. 2995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * It is _very_ important to follow this policy! 3095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 3195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * __u8 bank; 3295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 3395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * bank = inb(iobase+BSR); 3495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 3595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * do_your_stuff_here(); 3695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 3795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * outb(bank, iobase+BSR); 3895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 3995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * If you find bugs in this file, its very likely that the same bug 4095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * will also be in w83977af_ir.c since the implementations are quite 4195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * similar. 4295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 435a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo ********************************************************************/ 44b7c6bfb710cfd6552c3186cb8ce1ac9eef7a0e3dKamalesh Babulal 4595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/module.h> 4695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 4795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/kernel.h> 4895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/types.h> 4995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/skbuff.h> 5095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/netdevice.h> 5195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/ioport.h> 5295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/delay.h> 5395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/slab.h> 5495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/init.h> 5595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/rtnetlink.h> 5695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/dma-mapping.h> 5795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/pnp.h> 5895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <linux/platform_device.h> 5995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 6095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <asm/io.h> 6195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <asm/dma.h> 6295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <asm/byteorder.h> 6395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 6495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <net/irda/wrapper.h> 6595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <net/irda/irda.h> 6695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include <net/irda/irda_device.h> 6795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 6895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#include "nsc-ircc.h" 6995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 7095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#define CHIP_IO_EXTENT 8 7195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#define BROKEN_DONGLE_ID 7295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 7395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic char *driver_name = "nsc-ircc"; 7495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 7595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* Power Management */ 7695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#define NSC_IRCC_DRIVER_NAME "nsc-ircc" 7795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state); 7895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_resume(struct platform_device *dev); 7949d70c4856acfce943fab35fc199b3074961313fJoe Perches 8095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic struct platform_driver nsc_ircc_driver = { 8195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .suspend = nsc_ircc_suspend, 8295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .resume = nsc_ircc_resume, 8395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .driver = { 8495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .name = NSC_IRCC_DRIVER_NAME, 8595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng }, 8695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 8795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 8895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* Module parameters */ 8995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int qos_mtt_bits = 0x07; /* 1 ms or more */ 9095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int dongle_id; 9195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 9295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* Use BIOS settions by default, but user may supply module parameters */ 9395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic unsigned int io[] = { ~0, ~0, ~0, ~0 }; 9495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic unsigned int irq[] = { 0, 0, 0, 0 }; 9595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic unsigned int dma[] = { 0, 0, 0, 0 }; 9695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 9795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); 9895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); 9995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info); 10095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); 10195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); 10295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); 10395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id); 10495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 10595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* These are the known NSC chips */ 10695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic nsc_chip_t chips[] = { 10795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* Name, {cfg registers}, chip id index reg, chip id expected value, revision mask */ 10849d70c4856acfce943fab35fc199b3074961313fJoe Perches { "PC87108", { 0x150, 0x398, 0xea }, 0x05, 0x10, 0xf0, 10995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_probe_108, nsc_ircc_init_108 }, 11095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, 11195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_probe_338, nsc_ircc_init_338 }, 11295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Contributed by Steffen Pingel - IBM X40 */ 11395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { "PC8738x", { 0x164e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, 11495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_probe_39x, nsc_ircc_init_39x }, 11595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Contributed by Jan Frey - IBM A30/A31 */ 11695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 11795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_probe_39x, nsc_ircc_init_39x }, 11895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { NULL } 11995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 12095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 12195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; 12295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 12395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic char *dongle_types[] = { 12495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Differential serial interface", 12595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Differential serial interface", 12695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Reserved", 12795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Reserved", 12895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Sharp RY5HD01", 12995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Reserved", 13095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Single-ended serial interface", 13195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Consumer-IR only", 13295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "HP HSDL-2300, HP HSDL-3600/HSDL-3610", 13395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "IBM31T1100 or Temic TFDS6000/TFDS6500", 13495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Reserved", 13595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Reserved", 13695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "HP HSDL-1100/HSDL-2100", 13795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "HP HSDL-1100/HSDL-2100", 138b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches "Supports SIR Mode only", 13995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "No dongle connected", 14095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 14195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 14295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* PNP probing */ 14395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic chipio_t pnp_info; 14495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic const struct pnp_device_id nsc_ircc_pnp_table[] = { 14595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { .id = "NSC6001", .driver_data = 0 }, 14695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { .id = "IBM0071", .driver_data = 0 }, 14795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng { } 14895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 14995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 15095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table); 15195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 15295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic struct pnp_driver nsc_ircc_pnp_driver = { 15395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .name = "nsc-ircc", 15495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .id_table = nsc_ircc_pnp_table, 15595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng .probe = nsc_ircc_pnp_probe, 15695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng}; 15795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 15895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* Some prototypes */ 15995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_open(chipio_t *info); 16095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_close(struct nsc_ircc_cb *self); 16195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_setup(chipio_t *info); 16295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); 16395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_dma_receive(struct nsc_ircc_cb *self); 164854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase); 165854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev); 166854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev); 167854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size); 168854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase); 169854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud); 170854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_is_receiving(struct nsc_ircc_cb *self); 171854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_read_dongle_id (int iobase); 172854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic void nsc_ircc_init_dongle_interface (int iobase, int dongle_id); 173854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 174854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_net_open(struct net_device *dev); 175854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_net_close(struct net_device *dev); 176854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 177854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); 178854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 179854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng/* Globals */ 180854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int pnp_registered; 181854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int pnp_succeeded; 182854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 183854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng/* 184854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Function nsc_ircc_init () 185854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * 186854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Initialize chip. Just try to find out how many chips we are dealing with 187854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * and where they are 188854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 189854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tsengstatic int __init nsc_ircc_init(void) 190854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng{ 191854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng chipio_t info; 192854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng nsc_chip_t *chip; 193854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int ret; 194854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int cfg_base; 195854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int cfg, id; 196854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int reg; 197854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int i = 0; 198854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 199854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng ret = platform_driver_register(&nsc_ircc_driver); 200854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (ret) { 201854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng IRDA_ERROR("%s, Can't register driver!\n", driver_name); 202854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng return ret; 203854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng } 204854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 205854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* Register with PnP subsystem to detect disable ports */ 206854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng ret = pnp_register_driver(&nsc_ircc_pnp_driver); 207854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 208854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (ret >= 0) 209854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng pnp_registered = 1; 210854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 211854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng ret = -ENODEV; 212854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 213854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* Probe for all the NSC chipsets we know about */ 214854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng for (chip = chips; chip->name ; chip++) { 215854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, 216854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng chip->name); 217854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 218854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* Try all config registers for this chip */ 219854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { 220854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng cfg_base = chip->cfg[cfg]; 221854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (!cfg_base) 222854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng continue; 223854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 224854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* Read index register */ 22595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base); 22695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (reg == 0xff) { 227b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches IRDA_DEBUG(2, "%s() no chip at 0x%03x\n", __FUNCTION__, cfg_base); 22895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng continue; 22995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 23095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 23195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read chip identification register */ 232854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng outb(chip->cid_index, cfg_base); 233854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng id = inb(cfg_base+1); 234854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if ((id & chip->cid_mask) == chip->cid_value) { 235854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", 236854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng __FUNCTION__, chip->name, id & ~chip->cid_mask); 237854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 238854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* 239854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * If we found a correct PnP setting, 240854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * we first try it. 241854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 242854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (pnp_succeeded) { 243854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng memset(&info, 0, sizeof(chipio_t)); 244854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng info.cfg_base = cfg_base; 245854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng info.fir_base = pnp_info.fir_base; 246854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng info.dma = pnp_info.dma; 247854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng info.irq = pnp_info.irq; 248854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 249854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (info.fir_base < 0x2000) { 25095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_MESSAGE("%s, chip->init\n", driver_name); 25195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng chip->init(chip, &info); 25295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 25395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng chip->probe(chip, &info); 25495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 25595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (nsc_ircc_open(&info) >= 0) 25695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ret = 0; 25795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 25895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 25995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 26095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Opening based on PnP values failed. 26195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Let's fallback to user values, or probe 26295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the chip. 26395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 26495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ret) { 26595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name); 26695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(&info, 0, sizeof(chipio_t)); 26795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info.cfg_base = cfg_base; 26895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info.fir_base = io[i]; 26995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info.dma = dma[i]; 27095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info.irq = irq[i]; 27195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 27295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 27395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * If the user supplies the base address, then 274bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng * we init the chip, if not we probe the values 27595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * set by the BIOS 27695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 27795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (io[i] < 0x2000) { 27895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng chip->init(chip, &info); 27995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 28095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng chip->probe(chip, &info); 28195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 28295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (nsc_ircc_open(&info) >= 0) 28395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ret = 0; 28495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 28595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng i++; 28695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 28795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); 28895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 28995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 29095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 29195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 29295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (ret) { 29395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng platform_driver_unregister(&nsc_ircc_driver); 29495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_unregister_driver(&nsc_ircc_pnp_driver); 29595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_registered = 0; 29695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 29795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 29895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return ret; 29949d70c4856acfce943fab35fc199b3074961313fJoe Perches} 30095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 30195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 30295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_cleanup () 30395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 30495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Close all configured chips 30595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 30695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 30795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void __exit nsc_ircc_cleanup(void) 30895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 30995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int i; 31095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 31195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (i = 0; i < ARRAY_SIZE(dev_self); i++) { 31295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (dev_self[i]) 31395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_close(dev_self[i]); 31495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 31595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 31695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng platform_driver_unregister(&nsc_ircc_driver); 31795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 31895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pnp_registered) 31995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_unregister_driver(&nsc_ircc_pnp_driver); 32095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 32195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_registered = 0; 32295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 32395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 32495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 32595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_open (iobase, irq) 32695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 32795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Open driver instance 32895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 32995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 33095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int __init nsc_ircc_open(chipio_t *info) 33195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 33295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *dev; 33395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self; 33495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng void *ret; 33595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int err, chip_index; 33695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 33795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 33895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 33995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 34095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { 34195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!dev_self[chip_index]) 34295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 34395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 34495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 34595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (chip_index == ARRAY_SIZE(dev_self)) { 34695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__); 34795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -ENOMEM; 34895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 34995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 35095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, 35195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->cfg_base); 35295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 35395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((nsc_ircc_setup(info)) == -1) 35495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -1; 35595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 35695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name); 357f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches 35895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev = alloc_irdadev(sizeof(struct nsc_ircc_cb)); 35995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (dev == NULL) { 36095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ERROR("%s(), can't allocate memory for " 36195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "control block!\n", __FUNCTION__); 36295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -ENOMEM; 36395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 36495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 36595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self = dev->priv; 36695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->netdev = dev; 36795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_init(&self->lock); 36895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 36995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Need to store self somewhere */ 37095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_self[chip_index] = self; 37195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->index = chip_index; 37295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 37395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Initialize IO */ 37495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.cfg_base = info->cfg_base; 37595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.fir_base = info->fir_base; 37695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.irq = info->irq; 37795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.fir_ext = CHIP_IO_EXTENT; 37895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.dma = info->dma; 37995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.fifo_size = 32; 38095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 38195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Reserve the ioports that we need */ 38295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name); 38395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!ret) { 38495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", 38595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, self->io.fir_base); 38695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng err = -ENODEV; 38795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out1; 38895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 38995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 39095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Initialize QoS for this device */ 39195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irda_init_max_qos_capabilies(&self->qos); 39295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 39395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* The only value we must override it the baudrate */ 39495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| 39595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8); 39695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 39795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->qos.min_turn_time.bits = qos_mtt_bits; 39895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irda_qos_bits_to_value(&self->qos); 39995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 40095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ 40195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.truesize = 14384; 40295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.truesize = 14384; 40395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 40495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Allocate memory if needed */ 40551754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng self->rx_buff.head = 40695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_alloc_coherent(NULL, self->rx_buff.truesize, 40795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng &self->rx_buff_dma, GFP_KERNEL); 40895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->rx_buff.head == NULL) { 40995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng err = -ENOMEM; 41095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out2; 41151754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng 41295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 41395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(self->rx_buff.head, 0, self->rx_buff.truesize); 41495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 41595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.head = 41695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_alloc_coherent(NULL, self->tx_buff.truesize, 41795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng &self->tx_buff_dma, GFP_KERNEL); 41895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->tx_buff.head == NULL) { 41995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng err = -ENOMEM; 420854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng goto out3; 42195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 42295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(self->tx_buff.head, 0, self->tx_buff.truesize); 42395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 42495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.in_frame = FALSE; 42595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.state = OUTSIDE_FRAME; 42695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.data = self->tx_buff.head; 42795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.data = self->rx_buff.head; 42895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 42995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Reset Tx queue info */ 43095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; 43195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.tail = self->tx_buff.head; 43295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 43395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Override the network functions we need to use */ 43495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng SET_MODULE_OWNER(dev); 43595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->hard_start_xmit = nsc_ircc_hard_xmit_sir; 43695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->open = nsc_ircc_net_open; 43795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->stop = nsc_ircc_net_close; 43895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->do_ioctl = nsc_ircc_net_ioctl; 43995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->get_stats = nsc_ircc_net_get_stats; 44095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 44195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng err = register_netdev(dev); 44295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (err) { 44395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ERROR("%s(), register_netdev() failed!\n", __FUNCTION__); 44495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out4; 44595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 44695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); 44795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 44895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if user has supplied a valid dongle id or not */ 44995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((dongle_id <= 0) || 45095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (dongle_id >= ARRAY_SIZE(dongle_types))) { 45195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); 45295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 45395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, 45495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dongle_types[dongle_id]); 45595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 45695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_MESSAGE("%s, Using dongle: %s\n", driver_name, 45795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dongle_types[dongle_id]); 45895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 45995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 46095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.dongle_id = dongle_id; 46195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); 46295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 46395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, 46495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->index, NULL, 0); 46595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (IS_ERR(self->pldev)) { 46695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng err = PTR_ERR(self->pldev); 46795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out5; 46895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 46949d70c4856acfce943fab35fc199b3074961313fJoe Perches platform_set_drvdata(self->pldev, self); 47095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 47195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return chip_index; 47295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 47395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng out5: 47495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unregister_netdev(dev); 47595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng out4: 47695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_free_coherent(NULL, self->tx_buff.truesize, 47795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.head, self->tx_buff_dma); 47895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng out3: 47995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma_free_coherent(NULL, self->rx_buff.truesize, 48095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.head, self->rx_buff_dma); 48195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng out2: 48295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng release_region(self->io.fir_base, self->io.fir_ext); 483854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng out1: 484854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng free_netdev(dev); 485854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng dev_self[chip_index] = NULL; 486854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng return err; 48795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 48895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 489854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng/* 49095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_close (self) 49195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 49295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Close driver instance 493854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * 49495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 49595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int __exit nsc_ircc_close(struct nsc_ircc_cb *self) 49695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 497854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int iobase; 49895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 49995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(4, "%s()\n", __FUNCTION__); 50095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 50195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ASSERT(self != NULL, return -1;); 50295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 50395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 50495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 50595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng platform_device_unregister(self->pldev); 5063903c023570446303a10f152cfc120dcbf9a4ccfGuo-Fu Tseng 507854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* Remove netdevice */ 50895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unregister_netdev(self->netdev); 50995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 51095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Release the PORT that this driver is using */ 51195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", 51295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, self->io.fir_base); 5133903c023570446303a10f152cfc120dcbf9a4ccfGuo-Fu Tseng release_region(self->io.fir_base, self->io.fir_ext); 51495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 515a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng if (self->tx_buff.head) 516854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng dma_free_coherent(NULL, self->tx_buff.truesize, 517854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng self->tx_buff.head, self->tx_buff_dma); 518a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng 519854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng if (self->rx_buff.head) 520854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng dma_free_coherent(NULL, self->rx_buff.truesize, 521a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng self->rx_buff.head, self->rx_buff_dma); 522854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 523a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng dev_self[self->index] = NULL; 524a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng free_netdev(self->netdev); 52551754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng 526854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng return 0; 527a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng} 528a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng 52951754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng/* 530854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng * Function nsc_ircc_init_108 (iobase, cfg_base, irq, dma) 531a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng * 532a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng * Initialize the NSC '108 chip 53351754572371491b63f70aae41dab70dfcaf771b2Guo-Fu Tseng * 534a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng */ 535a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tsengstatic int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) 536a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng{ 537a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng int cfg_base = info->cfg_base; 538a821ebe580c535e3e8e354c6ab10516a0e95e202Guo-Fu Tseng __u8 temp=0; 539854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 54095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(2, cfg_base); /* Mode Control Register (MCTL) */ 5414f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting outb(0x00, cfg_base+1); /* Disable device */ 5424f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting 5434f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting /* Base Address and Interrupt Control Register (BAIC) */ 5444f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting outb(CFG_108_BAIC, cfg_base); 5454f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting switch (info->fir_base) { 5464f40bf46897ddb57f149c0758f0cef0cc7782f7fakeemting case 0x3e8: outb(0x14, cfg_base+1); break; 54749d70c4856acfce943fab35fc199b3074961313fJoe Perches case 0x2e8: outb(0x15, cfg_base+1); break; 54895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x3f8: outb(0x16, cfg_base+1); break; 54995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x2f8: outb(0x17, cfg_base+1); break; 55095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: IRDA_ERROR("%s(), invalid base_address", __FUNCTION__); 55195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 55295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 55349d70c4856acfce943fab35fc199b3074961313fJoe Perches /* Control Signal Routing Register (CSRT) */ 55495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (info->irq) { 55595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 3: temp = 0x01; break; 55695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 4: temp = 0x02; break; 55795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 5: temp = 0x03; break; 55895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 7: temp = 0x04; break; 55995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 9: temp = 0x05; break; 56095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 11: temp = 0x06; break; 56195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 15: temp = 0x07; break; 56295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: IRDA_ERROR("%s(), invalid irq", __FUNCTION__); 56395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 56495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_108_CSRT, cfg_base); 56595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 56695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (info->dma) { 56795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0: outb(0x08+temp, cfg_base+1); break; 56895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 1: outb(0x10+temp, cfg_base+1); break; 56995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 3: outb(0x18+temp, cfg_base+1); break; 57095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: IRDA_ERROR("%s(), invalid dma", __FUNCTION__); 57195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 57247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 57347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_108_MCTL, cfg_base); /* Mode Control Register (MCTL) */ 57495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x03, cfg_base+1); /* Enable device */ 57595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 57695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 57795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 57895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 57995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 58095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_probe_108 (chip, info) 58195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 58295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 58395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 58495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 58547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengstatic int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) 58647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng{ 58747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng int cfg_base = info->cfg_base; 58847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng int reg; 58947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 59095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read address and interrupt control register (BAIC) */ 59195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_108_BAIC, cfg_base); 59295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 59395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 59495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (reg & 0x03) { 59595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0: 59695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x3e8; 59795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 59847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 1: 59947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->fir_base = 0x2e8; 60047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 60147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 2: 60247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->fir_base = 0x3f8; 60347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 60447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 3: 60547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->fir_base = 0x2f8; 60647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 60747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng } 60847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->sir_base = info->fir_base; 60947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __FUNCTION__, 61047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->fir_base); 61147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 61295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read control signals routing register (CSRT) */ 61395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_108_CSRT, cfg_base); 61495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 61595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 61695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (reg & 0x07) { 61795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0: 61895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->irq = -1; 619eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng break; 62095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 1: 62195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->irq = 3; 62247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 62347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 2: 62447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->irq = 4; 62547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 62647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 3: 62747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->irq = 5; 62847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 62947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 4: 63047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->irq = 7; 63147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 63247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 5: 63395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->irq = 9; 63447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng break; 63595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 6: 63695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->irq = 11; 63795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 63895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 7: 63995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->irq = 15; 64095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 64195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 64295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(), probing irq=%d\n", __FUNCTION__, info->irq); 64395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 64495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Currently we only read Rx DMA but it will also be used for Tx */ 64595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch ((reg >> 3) & 0x03) { 64647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng case 0: 64795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->dma = -1; 64895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 64995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 1: 65095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->dma = 0; 65195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 65295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 2: 65395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->dma = 1; 65495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 65595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 3: 65695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->dma = 3; 65795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 65895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 65995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma); 66095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 66195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read mode control register (MCTL) */ 66295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_108_MCTL, cfg_base); 66395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 66495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 66595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->enabled = reg & 0x01; 66695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->suspended = !((reg >> 1) & 0x01); 66795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 66895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 66995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 67095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 67195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 67295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_init_338 (chip, info) 67395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 67495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Initialize the NSC '338 chip. Remember that the 87338 needs two 67595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * consecutive writes to the data registers while CPU interrupts are 67695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * disabled. The 97338 does not require this, but shouldn't be any 67795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * harm if we do it anyway. 678854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng */ 67995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info) 68095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 68195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* No init yet */ 682854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 683854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng return 0; 684854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng} 685854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 68695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 68795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_probe_338 (chip, info) 68895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 68995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 69095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 69195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 69295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info) 69395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 69495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int cfg_base = info->cfg_base; 69595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int reg, com = 0; 69695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int pnp; 69795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 69895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read funtion enable register (FER) */ 69995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_338_FER, cfg_base); 70095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 70195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 70295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->enabled = (reg >> 2) & 0x01; 70395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 70495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if we are in Legacy or PnP mode */ 70595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_338_PNP0, cfg_base); 70695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 70795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 70895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp = (reg >> 3) & 0x01; 70995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pnp) { 71095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "(), Chip is in PnP mode\n"); 71195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x46, cfg_base); 71295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = (inb(cfg_base+1) & 0xfe) << 2; 71395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 71495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x47, cfg_base); 71595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg |= ((inb(cfg_base+1) & 0xfc) << 8); 71695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 71795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = reg; 71895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 71949d70c4856acfce943fab35fc199b3074961313fJoe Perches /* Read function address register (FAR) */ 720854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng outb(CFG_338_FAR, cfg_base); 721854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng reg = inb(cfg_base+1); 722854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 723854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng switch ((reg >> 4) & 0x03) { 724854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng case 0: 72595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x3f8; 72695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 72795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 1: 72895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x2f8; 72995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 730eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng case 2: 73195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng com = 3; 73295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 73395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 3: 73495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng com = 4; 73595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 73695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 73795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 73895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (com) { 73995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch ((reg >> 6) & 0x03) { 74095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0: 74195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (com == 3) 74295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x3e8; 74395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 74495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x2e8; 74595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 74695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 1: 74795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (com == 3) 74895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x338; 74995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 75095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x238; 75195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 75295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 2: 75395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (com == 3) 75494c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng info->fir_base = 0x2e8; 75595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 75695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x2e0; 75795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 75895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 3: 75995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (com == 3) 76095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->fir_base = 0x220; 76194c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng else 76294c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng info->fir_base = 0x228; 76394c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng break; 76494c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng } 76594c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng } 76694c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng } 76794c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng info->sir_base = info->fir_base; 76894c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng 76994c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng /* Read PnP register 1 (PNP1) */ 77094c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng outb(CFG_338_PNP1, cfg_base); 77194c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng reg = inb(cfg_base+1); 77294c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng 77395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->irq = reg >> 4; 77495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 77594c5b41b327e08de0ddf563237855f55080652a1Guo-Fu Tseng /* Read PnP register 3 (PNP3) */ 77695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_338_PNP3, cfg_base); 77795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 77895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 77995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->dma = (reg & 0x07) - 1; 78095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 78195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read power and test register (PTR) */ 78295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_338_PTR, cfg_base); 78395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng reg = inb(cfg_base+1); 78495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 78595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->suspended = reg & 0x01; 78695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 78795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 78895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 78995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 79095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 79195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 79295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_init_39x (chip, info) 79395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 79495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Now that we know it's a '39x (see probe below), we need to 79595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * configure it so we can use it. 79695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 79795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * The NSC '338 chip is a Super I/O chip with a "bank" architecture, 79895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the configuration of the different functionality (serial, parallel, 79995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * floppy...) are each in a different bank (Logical Device Number). 80095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * The base address, irq and dma configuration registers are common 80195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * to all functionalities (index 0x30 to 0x7F). 80295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * There is only one configuration register specific to the 80395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * serial port, CFG_39X_SPC. 80495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * JeanII 80547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng * 80647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng * Note : this code was written by Jan Frey <janfrey@web.de> 80747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng */ 80847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengstatic int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) 80947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng{ 81095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int cfg_base = info->cfg_base; 81195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int enabled; 81295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 81395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* User is shure about his config... accept it. */ 81495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): " 81595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "io=0x%04x, irq=%d, dma=%d\n", 81695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, info->fir_base, info->irq, info->dma); 81795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 81895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Access bank for SP2 */ 81947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_39X_LDN, cfg_base); 82095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x02, cfg_base+1); 82195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 82295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Configure SP2 */ 82395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 82495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* We want to enable the device if not enabled */ 82595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_ACT, cfg_base); 82695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng enabled = inb(cfg_base+1) & 0x01; 82795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 82895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!enabled) { 82995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable the device */ 83095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_SIOCF1, cfg_base); 83195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x01, cfg_base+1); 83295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* May want to update info->enabled. Jean II */ 83395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 83495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 83547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng /* Enable UART bank switching (bit 7) ; Sets the chip to normal 83647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng * power mode (wake up from sleep mode) (bit 1) */ 83795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_SPC, cfg_base); 83895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x82, cfg_base+1); 83995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 84095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 84195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 84295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 84395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 84495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_probe_39x (chip, info) 84595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 84695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Test if we really have a '39x chip at the given address 84747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng * 84847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng * Note : this code was written by Jan Frey <janfrey@web.de> 84947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng */ 85047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tsengstatic int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) 85147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng{ 85295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int cfg_base = info->cfg_base; 85395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int reg1, reg2, irq, irqt, dma1, dma2; 85495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int enabled, susp; 85547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 85647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng IRDA_DEBUG(2, "%s(), nsc_ircc_probe_39x, base=%d\n", 85795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, cfg_base); 85895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 85995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* This function should be executed with irq off to avoid 86095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * another driver messing with the Super I/O bank - Jean II */ 86195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 86295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Access bank for SP2 */ 86395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_LDN, cfg_base); 86495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x02, cfg_base+1); 86595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 86695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read infos about SP2 ; store in info struct */ 86747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_39X_BASEH, cfg_base); 86847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng reg1 = inb(cfg_base+1); 86947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_39X_BASEL, cfg_base); 87047bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng reg2 = inb(cfg_base+1); 87147bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->fir_base = (reg1 << 8) | reg2; 87247bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 87347bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_39X_IRQNUM, cfg_base); 87447bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng irq = inb(cfg_base+1); 87547bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_39X_IRQSEL, cfg_base); 87647bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng irqt = inb(cfg_base+1); 87747bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng info->irq = irq; 87847bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng 87947bd10d14b3341004266395014007c120a359c9dGuo-Fu Tseng outb(CFG_39X_DMA0, cfg_base); 88095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma1 = inb(cfg_base+1); 88195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_DMA1, cfg_base); 88295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dma2 = inb(cfg_base+1); 88395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->dma = dma1 -1; 88495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 88595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_ACT, cfg_base); 88695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng info->enabled = enabled = inb(cfg_base+1) & 0x01; 88795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 88895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_SPC, cfg_base); 88995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng susp = 1 - ((inb(cfg_base+1) & 0x02) >> 1); 89095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 89195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(): io=0x%02x%02x, irq=%d (type %d), rxdma=%d, txdma=%d, enabled=%d (suspended=%d)\n", __FUNCTION__, reg1,reg2,irq,irqt,dma1,dma2,enabled,susp); 89295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 89395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Configure SP2 */ 89495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 895eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng /* We want to enable the device if not enabled */ 89695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_ACT, cfg_base); 897eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng enabled = inb(cfg_base+1) & 0x01; 89895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 89995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!enabled) { 90095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable the device */ 90195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_SIOCF1, cfg_base); 90295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x01, cfg_base+1); 90395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* May want to update info->enabled. Jean II */ 90495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 90595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 90695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable UART bank switching (bit 7) ; Sets the chip to normal 9078b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng * power mode (wake up from sleep mode) (bit 1) */ 90895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(CFG_39X_SPC, cfg_base); 90995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x82, cfg_base+1); 91095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 91195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 91295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 91395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 914854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng/* PNP probing */ 91595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) 91695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 91795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memset(&pnp_info, 0, sizeof(chipio_t)); 918854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng pnp_info.irq = -1; 919854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng pnp_info.dma = -1; 920854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng pnp_succeeded = 1; 921854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 922854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* There don't seem to be any way to get the cfg_base. 92395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * On my box, cfg_base is in the PnP descriptor of the 92495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * motherboard. Oh well... Jean II */ 92595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 92695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pnp_port_valid(dev, 0) && 92795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) 92895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_info.fir_base = pnp_port_start(dev, 0); 92995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 93095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pnp_irq_valid(dev, 0) && 93195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) 93295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_info.irq = pnp_irq(dev, 0); 93395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 93495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (pnp_dma_valid(dev, 0) && 93595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) 93695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_info.dma = pnp_dma(dev, 0); 93795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 93895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", 93995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); 94095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 94195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if((pnp_info.fir_base == 0) || 94295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng (pnp_info.irq == -1) || (pnp_info.dma == -1)) { 94395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Returning an error will disable the device. Yuck ! */ 94495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng //return -EINVAL; 94595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng pnp_succeeded = 0; 94695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 94795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 94895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 94995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 95095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 95195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 95295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_setup (info) 95395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 95495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Returns non-negative on success. 95595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 95695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 95749d70c4856acfce943fab35fc199b3074961313fJoe Perchesstatic int nsc_ircc_setup(chipio_t *info) 95895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 959854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int version; 960854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng int iobase = info->fir_base; 961854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng 962854a2e7c331a36244169626ba8e11e15d134cb5fGuo-Fu Tseng /* Read the Module ID */ 96395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK3); 96495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng version = inb(iobase+MID); 965c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 966c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng IRDA_DEBUG(2, "%s() Driver %s Found chip version %02x\n", 967c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng __FUNCTION__, driver_name, version); 968c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 969c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng /* Should be 0x2? */ 970c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng if (0x20 != (version & 0xf0)) { 971c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng IRDA_ERROR("%s, Wrong chip version %02x\n", 972c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng driver_name, version); 973c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng return -1; 974c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng } 975c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 976c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng /* Switch to advanced mode */ 977c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng switch_bank(iobase, BANK2); 978c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng outb(ECR1_EXT_SL, iobase+ECR1); 979c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng switch_bank(iobase, BANK0); 980c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 981c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ 982c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng switch_bank(iobase, BANK0); 983c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); 984c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 985c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng outb(0x03, iobase+LCR); /* 8 bit word length */ 986c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng outb(MCR_SIR, iobase+MCR); /* Start at SIR-mode, also clears LSR*/ 987c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng 988c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng /* Set FIFO size to 32 */ 989c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng switch_bank(iobase, BANK2); 990c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); 99195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 992c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng /* IRCR2: FEND_MD is not set */ 99395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK5); 99495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x02, iobase+4); 99595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 99695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Make sure that some defaults are OK */ 997ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng switch_bank(iobase, BANK6); 998ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng outb(0x20, iobase+0); /* Set 32 bits FIR CRC */ 999ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng outb(0x0a, iobase+1); /* Set MIR pulse width */ 1000f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches outb(0x0d, iobase+2); /* Set SIR pulse width to 1.6us */ 1001ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */ 100295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 100395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable receive interrupts */ 1004ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng switch_bank(iobase, BANK0); 1005c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng outb(IER_RXHDL_IE, iobase+IER); 1006ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng 100749d70c4856acfce943fab35fc199b3074961313fJoe Perches return 0; 1008ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng} 100995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 101095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 1011ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng * Function nsc_ircc_read_dongle_id (void) 1012ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng * 101349d70c4856acfce943fab35fc199b3074961313fJoe Perches * Try to read dongle indentification. This procedure needs to be executed 1014ce7d70af2c8b9c74e8afb2c0d69e304d141ce4aaGuo-Fu Tseng * once after power-on/reset. It also needs to be used whenever you suspect 101595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * that the user may have plugged/unplugged the IrDA Dongle. 101695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 101795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_read_dongle_id (int iobase) 101895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 101995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int dongle_id; 102095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 102195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 102295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 102395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 102495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Select Bank 7 */ 102595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK7); 102695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 102795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */ 102895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x00, iobase+7); 102995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 103095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* ID0, 1, and 2 are pulled up/down very slowly */ 103195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng udelay(50); 103295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 103395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* IRCFG1: read the ID bits */ 103495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dongle_id = inb(iobase+4) & 0x0f; 103595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 103695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#ifdef BROKEN_DONGLE_ID 103795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (dongle_id == 0x0a) 103895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dongle_id = 0x09; 103995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng#endif 104095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Go back to bank 0 before returning */ 104195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 104295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 104395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 104495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 104595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return dongle_id; 104695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 104795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 104895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 104995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_init_dongle_interface (iobase, dongle_id) 105095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 105195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This function initializes the dongle for the transceiver that is 105295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * used. This procedure needs to be executed once after 1053c00cd82641023ade3c44b4f11140a8afad460415Guo-Fu Tseng * power-on/reset. It also needs to be used whenever you suspect that 105495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the dongle is changed. 105595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 1056bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazetstatic void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) 105795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 105831c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison int bank; 10595043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko 10605043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko /* Save current bank */ 10615043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko bank = inb(iobase+BSR); 10625043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko 106395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Select Bank 7 */ 10645043f5057773ba8b539eb51b9a4007e99599824fJiri Pirko switch_bank(iobase, BANK7); 106595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 106631c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison /* IRCFG4: set according to dongle_id */ 106731c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison switch (dongle_id) { 106895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x00: /* same as */ 106995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x01: /* Differential serial interface */ 107095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 107195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 107295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 107395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x02: /* same as */ 107495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x03: /* Reserved */ 107595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 107695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 107795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 107895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x04: /* Sharp RY5HD01 */ 107995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 108095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x05: /* Reserved, but this is what the Thinkpad reports */ 108195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 108295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 108395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 108495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x06: /* Single-ended serial interface */ 108595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 108695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 108795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 108895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x07: /* Consumer-IR only */ 108995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", 109095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 109195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 109295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ 109395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s\n", 109495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 1095858b9ced6e73a0f087294c398a1ae70a7eeed94fRoel Kluin break; 109695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ 109795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x28, iobase+7); /* Set irsl[0-2] as output */ 109895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 109931c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison case 0x0A: /* same as */ 110095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0B: /* Reserved */ 110195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 1102858b9ced6e73a0f087294c398a1ae70a7eeed94fRoel Kluin __FUNCTION__, dongle_types[dongle_id]); 110395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 1104ea192aa89c3b26d56113e70c72238f6951d4097fGuo-Fu Tseng case 0x0C: /* same as */ 110595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0D: /* HP HSDL-1100/HSDL-2100 */ 110695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 110795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Set irsl0 as input, irsl[1-2] as output, and separate 110895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * inputs are used for SIR and MIR/FIR 110995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 111095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x48, iobase+7); 111195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 111295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0E: /* Supports SIR Mode only */ 111395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x28, iobase+7); /* Set irsl[0-2] as output */ 111495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 111595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0F: /* No dongle connected */ 111695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s\n", 111795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 111895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 111995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 112095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x62, iobase+MCR); 112195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 112295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 112395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), invalid dongle_id %#x", 112495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_id); 112595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 112695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 112795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* IRCFG1: IRSL1 and 2 are set to IrDA mode */ 112895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x00, iobase+4); 112995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 113095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 113195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 113295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 113395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} /* set_up_dongle_interface */ 113495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 113595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 113695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_change_dongle_speed (iobase, speed, dongle_id) 113795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 113895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Change speed of the attach dongle 113995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 114095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 114195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) 114295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 114395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 114495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 114595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 114695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 114795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 114895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Select Bank 7 */ 114995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK7); 115095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 115195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* IRCFG1: set according to dongle_id */ 115295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (dongle_id) { 115395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x00: /* same as */ 115495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x01: /* Differential serial interface */ 115595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 115695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 115795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 115895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x02: /* same as */ 115995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x03: /* Reserved */ 116095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 116195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 116295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 116395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x04: /* Sharp RY5HD01 */ 116495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 116595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x05: /* Reserved */ 11668e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 11678e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches __FUNCTION__, dongle_types[dongle_id]); 116895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 116995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x06: /* Single-ended serial interface */ 117095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 117195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 117295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 117395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x07: /* Consumer-IR only */ 117495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", 117595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 117695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 117795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ 117895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s\n", 117995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 118095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x00, iobase+4); 118195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (speed > 115200) 118295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x01, iobase+4); 118395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 118495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ 118595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x01, iobase+4); 118695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 118795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (speed == 4000000) { 118895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* There was a cli() there, but we now are already 118995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * under spin_lock_irqsave() - JeanII */ 119095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x81, iobase+4); 119195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x80, iobase+4); 119295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 119395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x00, iobase+4); 119495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 119595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0A: /* same as */ 119695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0B: /* Reserved */ 119795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", 119895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 119995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 120095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0C: /* same as */ 120195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0D: /* HP HSDL-1100/HSDL-2100 */ 120295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 120395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0E: /* Supports SIR Mode only */ 120495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 120595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 0x0F: /* No dongle connected */ 120695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", 120795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, dongle_types[dongle_id]); 120895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 120995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 121095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x62, iobase+MCR); 121195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 121295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 121395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), invalid data_rate\n", __FUNCTION__); 121495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 121595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 121695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 121795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 121895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 121995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 122095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_change_speed (self, baud) 122195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 122295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Change the speed of the device 122395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 122495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * This function *must* be called with irq off and spin-lock. 122595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 122695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) 122795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 122895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *dev = self->netdev; 122995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 mcr = MCR_SIR; 123095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 123195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 123295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 ier; /* Interrupt enable register */ 123395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 123495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(), speed=%d\n", __FUNCTION__, speed); 123595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 123695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ASSERT(self != NULL, return 0;); 123795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 123895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 123995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 124095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Update accounting for new speed */ 124195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.speed = speed; 124295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 124395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 124495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 124595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 124695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Disable interrupts */ 124795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 124895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0, iobase+IER); 124995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 125095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Select Bank 2 */ 125195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK2); 125295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 125395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x00, iobase+BGDH); 125495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch (speed) { 125595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 9600: outb(0x0c, iobase+BGDL); break; 125695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 19200: outb(0x06, iobase+BGDL); break; 125795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 38400: outb(0x03, iobase+BGDL); break; 125895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 57600: outb(0x02, iobase+BGDL); break; 125995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 115200: outb(0x01, iobase+BGDL); break; 126095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 576000: 126195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK5); 126295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 126395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* IRCR2: MDRS is set */ 126495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(inb(iobase+4) | 0x04, iobase+4); 126595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 126695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mcr = MCR_MIR; 126795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __FUNCTION__); 126895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 126995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 1152000: 127095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mcr = MCR_MIR; 127195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", __FUNCTION__); 127295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 127395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case 4000000: 127495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mcr = MCR_FIR; 127595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", __FUNCTION__); 127695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 127795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 127895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mcr = MCR_FIR; 127995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), unknown baud rate of %d\n", 128095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, speed); 128195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 128295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 128395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 128495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Set appropriate speed mode */ 128595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 128695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(mcr | MCR_TX_DFR, iobase+MCR); 128795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 128895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Give some hits to the transceiver */ 128995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id); 129095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 129195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Set FIFO threshold to TX17, RX16 */ 129295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 129395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0x00, iobase+FCR); 129495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(FCR_FIFO_EN, iobase+FCR); 129595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(FCR_RXTH| /* Set Rx FIFO threshold */ 129695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng FCR_TXTH| /* Set Tx FIFO threshold */ 129795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng FCR_TXSR| /* Reset Tx FIFO */ 129895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng FCR_RXSR| /* Reset Rx FIFO */ 129995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng FCR_FIFO_EN, /* Enable FIFOs */ 130095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase+FCR); 130195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 130249d70c4856acfce943fab35fc199b3074961313fJoe Perches /* Set FIFO size to 32 */ 130395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK2); 130449d70c4856acfce943fab35fc199b3074961313fJoe Perches outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); 130595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 130695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable some interrupts so we can receive frames */ 130795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 130895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (speed > 115200) { 130995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Install FIR xmit handler */ 131095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->hard_start_xmit = nsc_ircc_hard_xmit_fir; 131195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ier = IER_SFIF_IE; 131295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_dma_receive(self); 131395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 131495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Install SIR xmit handler */ 131595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->hard_start_xmit = nsc_ircc_hard_xmit_sir; 131695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ier = IER_RXHDL_IE; 131795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 131895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Set our current interrupt mask */ 131995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(ier, iobase+IER); 132095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 132195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore BSR */ 132295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 132395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 132495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Make sure interrupt handlers keep the proper interrupt mask */ 132595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return(ier); 132695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 132795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 132895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 132995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_hard_xmit (skb, dev) 133095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 133195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Transmit the frame! 133295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 133395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 133495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev) 133595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 133695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self; 133749d70c4856acfce943fab35fc199b3074961313fJoe Perches unsigned long flags; 133895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 133995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __s32 speed; 134095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 134195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 134295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self = (struct nsc_ircc_cb *) dev->priv; 134349d70c4856acfce943fab35fc199b3074961313fJoe Perches 134495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ASSERT(self != NULL, return 0;); 134595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 134695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 134795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 134895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(dev); 134995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 135095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Make sure tests *& speed change are atomic */ 135195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 135295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 135395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if we need to change the speed */ 135495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng speed = irda_get_next_speed(skb); 135595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((speed != self->io.speed) && (speed != -1)) { 135695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check for empty frame. */ 135795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!skb->len) { 135895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* If we just sent a frame, we get called before 135995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the last bytes get out (because of the SIR FIFO). 136095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * If this is the case, let interrupt handler change 136195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the speed itself... Jean II */ 136295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->io.direction == IO_RECV) { 136395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_change_speed(self, speed); 136495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* TODO : For SIR->SIR, the next packet 136595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * may get corrupted - Jean II */ 136695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(dev); 136795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 136895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed = speed; 136995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Queue will be restarted after speed change 137095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * to make sure packets gets through the 137195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * proper xmit handler - Jean II */ 137295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 137395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->trans_start = jiffies; 137495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 137595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(skb); 137695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 137795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 137895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed = speed; 137995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 138095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 138295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 138395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.data = self->tx_buff.head; 138595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 138795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.truesize); 138895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 138995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.tx_bytes += self->tx_buff.len; 139095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 139195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Add interrupt on tx low level (will fire immediately) */ 139295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 139395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(IER_TXLDL_IE, iobase+IER); 139495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 139595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 139695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 139795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 139895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->trans_start = jiffies; 139995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 140095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 140195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(skb); 140295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 140395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 140495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 140595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 140695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev) 140795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 140895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self; 140995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unsigned long flags; 141095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 141195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __s32 speed; 141295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 141395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int mtt, diff; 141495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 141595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self = (struct nsc_ircc_cb *) dev->priv; 141695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 141795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1418f8502ce4f986a8fd486302980285b5e786b8dabeJoe Perches netif_stop_queue(dev); 141995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 142095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Make sure tests *& speed change are atomic */ 142195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 142295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 142395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if we need to change the speed */ 142495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng speed = irda_get_next_speed(skb); 142595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((speed != self->io.speed) && (speed != -1)) { 142695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check for empty frame. */ 142795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!skb->len) { 142895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* If we are currently transmitting, defer to 142995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * interrupt handler. - Jean II */ 143095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if(self->tx_fifo.len == 0) { 143195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_change_speed(self, speed); 143295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(dev); 1433eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng } else { 143495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed = speed; 143595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Keep queue stopped : 143695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the speed change operation may change the 143795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * xmit handler, and we want to make sure 143849d70c4856acfce943fab35fc199b3074961313fJoe Perches * the next packet get through the proper 143995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Tx path, so block the Tx queue until 144095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the speed change has been done. 144195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Jean II */ 144295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 144395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->trans_start = jiffies; 144495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 144595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(skb); 144695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 144795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 144895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Change speed after current frame */ 144995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed = speed; 145095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 145195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 145295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 145349d70c4856acfce943fab35fc199b3074961313fJoe Perches /* Save current bank */ 145495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 145595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 145695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Register and copy this frame to DMA memory */ 145795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail; 145895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.queue[self->tx_fifo.free].len = skb->len; 145995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.tail += skb->len; 146095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.tx_bytes += skb->len; 146295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data, 146495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb->len); 146595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.len++; 146795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.free++; 146895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 146995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Start transmit only if there is currently no transmit going on */ 147095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->tx_fifo.len == 1) { 147195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if we must wait the min turn time or not */ 147295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mtt = irda_get_mtt(skb); 147395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (mtt) { 147495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check how much time we have used already */ 147549d70c4856acfce943fab35fc199b3074961313fJoe Perches do_gettimeofday(&self->now); 147695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng diff = self->now.tv_usec - self->stamp.tv_usec; 147795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (diff < 0) 147895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng diff += 1000000; 147995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 148095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if the mtt is larger than the time we have 148195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * already used by all the protocol processing 148295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 148395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (mtt > diff) { 148495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mtt -= diff; 148595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 148695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 148795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Use timer if delay larger than 125 us, and 148895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * use udelay for smaller values which should 148995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * be acceptable 149095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 149195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (mtt > 125) { 149295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Adjust for timer resolution */ 149395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng mtt = mtt / 125; 149495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 149595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Setup timer */ 149695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK4); 149795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(mtt & 0xff, iobase+TMRL); 149895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb((mtt >> 8) & 0x0f, iobase+TMRH); 149995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 150095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Start timer */ 150195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(IRCR1_TMR_EN, iobase+IRCR1); 150295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.direction = IO_XMIT; 150395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 150495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable timer interrupt */ 150595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 150695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(IER_TMR_IE, iobase+IER); 150795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 150895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Timer will take care of the rest */ 150995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng goto out; 151095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 151195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng udelay(mtt); 151295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 151395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 151495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable DMA interrupt */ 151595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 151649d70c4856acfce943fab35fc199b3074961313fJoe Perches outb(IER_DMA_IE, iobase+IER); 151795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 151895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Transmit frame */ 151995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_dma_xmit(self, iobase); 152095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 152195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng out: 152295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Not busy transmitting anymore if window is not full, 152395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * and if we don't need to change speed */ 152495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) 152595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(self->netdev); 152695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 152795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 152895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 152995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 153095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev->trans_start = jiffies; 153195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 153295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng dev_kfree_skb(skb); 153395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 153495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 153595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 153695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 153795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 153895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_dma_xmit (self, iobase) 153995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 154095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Transmit data using DMA 154195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 154295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 154395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase) 154495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 154595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int bsr; 154695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 154795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 154895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bsr = inb(iobase+BSR); 154995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 155095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Disable DMA */ 155195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 155295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); 155395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 155495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.direction = IO_XMIT; 155595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 155695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Choose transmit DMA channel */ 155795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK2); 155895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); 155995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 156095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irda_setup_dma(self->io.dma, 156195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - 156295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.head) + self->tx_buff_dma, 156395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.queue[self->tx_fifo.ptr].len, 156495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng DMA_TX_MODE); 156595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 156695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Enable DMA and SIR interaction pulse */ 156795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 156895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(inb(iobase+MCR)|MCR_TX_DFR|MCR_DMA_EN|MCR_IR_PLS, iobase+MCR); 156995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 157095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 157195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bsr, iobase+BSR); 157295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 157395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 157495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 157595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_pio_xmit (self, iobase) 157695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 157795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Transmit data using PIO. Returns the number of bytes that actually 157895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * got transferred 157995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 158095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 158195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size) 158295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 158395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int actual = 0; 158495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 158595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 158695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(4, "%s()\n", __FUNCTION__); 158795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 158895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 158995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 159095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 159195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 159295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!(inb_p(iobase+LSR) & LSR_TXEMP)) { 159395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(4, "%s(), warning, FIFO not empty yet!\n", 159495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__); 159595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 159695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* FIFO may still be filled to the Tx interrupt threshold */ 159795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng fifo_size -= 17; 159895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 1599576b5223e2caa0f19afb8ac17455759c214370ceakeemting 160095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Fill FIFO with current frame */ 160195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((fifo_size-- > 0) && (actual < len)) { 160295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Transmit next byte */ 160395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(buf[actual++], iobase+TXD); 160495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 160595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 160695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(4, "%s(), fifo_size %d ; %d sent of %d\n", 160795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__, fifo_size, actual, len); 160895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 160995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank */ 161095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 161195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 161295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return actual; 161395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 161495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 161595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 161695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_dma_xmit_complete (self) 161795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 161895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * The transfer of a frame in finished. This function will only be called 161995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * by the interrupt handler 1620d1dfa1d1de855e8db58ec4e403af5939d273f8feGuo-Fu Tseng * 162195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 162295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self) 162395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 162495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 162595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 162695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int ret = TRUE; 162795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 162895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s()\n", __FUNCTION__); 162995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 163095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 163195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 163295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 163395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 163495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 163595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Disable DMA */ 163695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 163795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); 163895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 163995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check for underrrun! */ 164095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (inb(iobase+ASCR) & ASCR_TXUR) { 164195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.tx_errors++; 164295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.tx_fifo_errors++; 164395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 164495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Clear bit, by writing 1 into it */ 164595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(ASCR_TXUR, iobase+ASCR); 164695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 164795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.tx_packets++; 164895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 164995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 165095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Finished with this frame, so prepare for next */ 165195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.ptr++; 165295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_fifo.len--; 165395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 165495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Any frames to be sent back-to-back? */ 165595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->tx_fifo.len) { 165695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_dma_xmit(self, iobase); 165795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 165895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Not finished yet! */ 165995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ret = FALSE; 166095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 166195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Reset Tx FIFO info */ 166249d70c4856acfce943fab35fc199b3074961313fJoe Perches self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; 166349d70c4856acfce943fab35fc199b3074961313fJoe Perches self->tx_fifo.tail = self->tx_buff.head; 166449d70c4856acfce943fab35fc199b3074961313fJoe Perches } 166549d70c4856acfce943fab35fc199b3074961313fJoe Perches 166695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Make sure we have room for more frames and 166795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * that we don't need to change speed */ 166895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) { 166995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Not busy transmitting anymore */ 167095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Tell the network layer, that we can accept more frames */ 167195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(self->netdev); 167295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 167395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 167495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank */ 167595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 167695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 167795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return ret; 167895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 167995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 168095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 168195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_dma_receive (self) 168295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 168395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Get ready for receiving a frame. The device will initiate a DMA 168495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * if it starts to receive a frame. 168595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 168695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 168795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_dma_receive(struct nsc_ircc_cb *self) 168895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 1689c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng int iobase; 16904872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng __u8 bsr; 16914872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 16924872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng iobase = self->io.fir_base; 16934872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 16944872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng /* Reset Tx FIFO info */ 16954872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; 16964872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng self->tx_fifo.tail = self->tx_buff.head; 16974872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 16984872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng /* Save current bank */ 16994872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng bsr = inb(iobase+BSR); 17004872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17014872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng /* Disable DMA */ 17024872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng switch_bank(iobase, BANK0); 17034872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); 17044872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17054872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng /* Choose DMA Rx, DMA Fairness, and Advanced mode */ 17064872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng switch_bank(iobase, BANK2); 17074872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng outb(ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); 17084872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17094872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng self->io.direction = IO_RECV; 17104872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng self->rx_buff.data = self->rx_buff.head; 17114872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17124872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng /* Reset Rx FIFO. This will also flush the ST_FIFO */ 17134872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng switch_bank(iobase, BANK0); 17144872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR); 17154872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17164872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng self->st_fifo.len = self->st_fifo.pending_bytes = 0; 17174872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng self->st_fifo.tail = self->st_fifo.head = 0; 17184872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17194872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, 17204872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng DMA_RX_MODE); 17214872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 1722c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng /* Enable DMA */ 1723c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng switch_bank(iobase, BANK0); 1724c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR); 1725c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng 1726c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng /* Restore bank register */ 1727c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng outb(bsr, iobase+BSR); 1728c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng 17294872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng return 0; 17304872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng} 17314872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng 17324872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng/* 17334872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng * Function nsc_ircc_dma_receive_complete (self) 17344872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng * 17354872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng * Finished with receiving frames 17364872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng * 17374872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng * 17384872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng */ 17394872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tsengstatic int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase) 17404872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng{ 17414872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng struct st_fifo *st_fifo; 17424872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng struct sk_buff *skb; 17434872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng __u8 status; 17444872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng __u8 bank; 1745c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng int len; 1746c8a8684d5cfb0f110a962c93586630c0bf91ebc1Guo-Fu Tseng 174795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo = &self->st_fifo; 174895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 174995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 175095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 175195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 175295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Read all entries in status FIFO */ 175395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK5); 175495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) { 175595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* We must empty the status FIFO no matter what */ 175638ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8); 175795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 175895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (st_fifo->tail >= MAX_RX_WINDOW) { 175995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(0, "%s(), window is full!\n", __FUNCTION__); 176095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng continue; 176195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 176295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 176395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->entries[st_fifo->tail].status = status; 176495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->entries[st_fifo->tail].len = len; 176595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->pending_bytes += len; 176695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->tail++; 17674872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng st_fifo->len++; 17684872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng } 176995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Try to process all entries in status FIFO */ 17704872b11fdbbf78665230b2bb5864b1611dcb4a25Guo-Fu Tseng while (st_fifo->len > 0) { 177195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Get first entry */ 177295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng status = st_fifo->entries[st_fifo->head].status; 177395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng len = st_fifo->entries[st_fifo->head].len; 177495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->pending_bytes -= len; 177595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->head++; 177695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->len--; 177795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 177895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check for errors */ 177995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_ERR_MSK) { 178095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_LOST_FR) { 178195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Add number of lost frames to stats */ 178295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_errors += len; 178395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 178495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Skip frame */ 178595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_errors++; 178695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 178795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.data += len; 17881c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 178995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_MAX_LEN) 179095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_length_errors++; 179195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 179295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_PHY_ERR) 179395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_frame_errors++; 179495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 179595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_BAD_CRC) 179695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_crc_errors++; 179795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 179895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* The errors below can be reported in both cases */ 179995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_OVR1) 180095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_fifo_errors++; 180195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 180295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (status & FRM_ST_OVR2) 180395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_fifo_errors++; 180495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 180595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 180695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * First we must make sure that the frame we 180795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * want to deliver is all in main memory. If we 180895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * cannot tell, then we check if the Rx FIFO is 180995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * empty. If not then we will have to take a nap 181095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * and try again later. 181195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 181295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (st_fifo->pending_bytes < self->io.fifo_size) { 181395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 181495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (inb(iobase+LSR) & LSR_RXDA) { 181595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Put this entry back in fifo */ 181695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng st_fifo->head--; 18171c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng st_fifo->len++; 18181c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng st_fifo->pending_bytes += len; 18191c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng st_fifo->entries[st_fifo->head].status = status; 18201c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng st_fifo->entries[st_fifo->head].len = len; 18211c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng /* 18221c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng * DMA not finished yet, so try again 18231c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng * later, set timer value, resolution 1824bc057e0366cad58e55038a2cb69572d51c40cdf3Guo-Fu Tseng * 125 us 18251c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng */ 18261c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng switch_bank(iobase, BANK4); 18271c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng outb(0x02, iobase+TMRL); /* x 125 us */ 18281c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng outb(0x00, iobase+TMRH); 18291c5578194abde100c089855cce72e87c047d8530Guo-Fu Tseng 183095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Start timer */ 183195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(IRCR1_TMR_EN, iobase+IRCR1); 183295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 183395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 183495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 183595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 183695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return FALSE; /* I'll be back! */ 183795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 183895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 183995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 184095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 184195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Remember the time we received this frame, so we can 184295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * reduce the min turn time a bit since we will know 184338ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng * how much time we have used for protocol processing 184438ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng */ 184538ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng do_gettimeofday(&self->stamp); 184638ed0c2107dea55347504042ed4e1d0cbc3e9100Guo-Fu Tseng 184795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb = dev_alloc_skb(len+1); 184895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (skb == NULL) { 184995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s(), memory squeeze, " 185095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "dropping frame.\n", 185195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__); 185295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_dropped++; 185395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 185495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 185595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 185695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 185795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return FALSE; 185895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 185995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 186095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Make sure IP header gets aligned */ 186195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_reserve(skb, 1); 186295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1863eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng /* Copy frame without CRC */ 186495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->io.speed < 4000000) { 186595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_put(skb, len-2); 186695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memcpy(skb->data, self->rx_buff.data, len-2); 186795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 186895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb_put(skb, len-4); 186995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng memcpy(skb->data, self->rx_buff.data, len-4); 187095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 187195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Move to next frame */ 187395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->rx_buff.data += len; 187495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_bytes += len; 187595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.rx_packets++; 187695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 187795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb->dev = self->netdev; 187895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb->mac.raw = skb->data; 187995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng skb->protocol = htons(ETH_P_IRDA); 188095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_rx(skb); 188195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->netdev->last_rx = jiffies; 188295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 188395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 188495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 188595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 188695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 188795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return TRUE; 188895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 188995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 189095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 189195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_pio_receive (self) 189295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 189395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Receive all data in receiver FIFO 189495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 189595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 189695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void nsc_ircc_pio_receive(struct nsc_ircc_cb *self) 189795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 189895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 byte; 189995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 190095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 190195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 190295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 190395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Receive all characters in Rx FIFO */ 190495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng do { 190595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng byte = inb(iobase+RXD); 190695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 190795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng byte); 190895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } while (inb(iobase+LSR) & LSR_RXDA); /* Data available */ 190995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 191095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 191195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 191295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_sir_interrupt (self, eir) 191395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 191495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Handle SIR interrupt 191595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 191695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 1917eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tsengstatic void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir) 191895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 191995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int actual; 1920c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław 192195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if transmit FIFO is low on data */ 192295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eir & EIR_TXLDL_EV) { 19239e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet /* Write data left in transmit buffer */ 192495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng actual = nsc_ircc_pio_write(self->io.fir_base, 192595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.data, 192695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.len, 192795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.fifo_size); 192895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.data += actual; 192995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->tx_buff.len -= actual; 193095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 1931f327358ab2cdfa534b2dc89e9dd2266c0f61f587Ian Campbell self->io.direction = IO_XMIT; 1932f327358ab2cdfa534b2dc89e9dd2266c0f61f587Ian Campbell 19339e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet /* Check if finished */ 193495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->tx_buff.len > 0) 193595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_TXLDL_IE; 193695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else { 193795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 193895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->stats.tx_packets++; 193995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(self->netdev); 194095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_TXEMP_IE; 194195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 194295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 194395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 194495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if transmission has completed */ 194595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eir & EIR_TXEMP_EV) { 194695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Turn around and get ready to receive some data */ 194795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.direction = IO_RECV; 194895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_RXHDL_IE; 194995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if we need to change the speed? 195095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Need to be after self->io.direction to avoid race with 195195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * nsc_ircc_hard_xmit_sir() - Jean II */ 195295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->new_speed) { 195395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(2, "%s(), Changing speed!\n", __FUNCTION__); 195495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = nsc_ircc_change_speed(self, 195595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed); 195695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed = 0; 195795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(self->netdev); 195831c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison 195995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if we are going to FIR */ 196031c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison if (self->io.speed > 115200) { 196195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* No need to do anymore SIR stuff */ 196295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return; 196395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 196495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 196595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 196695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 196795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Rx FIFO threshold or timeout */ 196895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eir & EIR_RXHDL_EV) { 196995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_pio_receive(self); 197095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 197195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Keep receiving */ 197295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_RXHDL_IE; 197395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 197495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 197595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 197695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 197795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_fir_interrupt (self, eir) 197895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 197995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Handle MIR/FIR interrupt 198095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 198195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 198295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase, 198395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int eir) 198495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 198595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 198695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 198895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 198995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Status FIFO event*/ 199095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eir & EIR_SFIF_EV) { 199195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if DMA has finished */ 199295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (nsc_ircc_dma_receive_complete(self, iobase)) { 199395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Wait for next status FIFO interrupt */ 199495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_SFIF_IE; 199595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 199695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_SFIF_IE | IER_TMR_IE; 199795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 199895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (eir & EIR_TMR_EV) { /* Timer finished */ 199995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Disable timer */ 200095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK4); 200195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0, iobase+IRCR1); 200295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 200395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Clear timer event */ 200495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 200595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(ASCR_CTE, iobase+ASCR); 200695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 200795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if this is a Tx timer interrupt */ 200895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->io.direction == IO_XMIT) { 200995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_dma_xmit(self, iobase); 201095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 201195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Interrupt on DMA */ 201295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_DMA_IE; 201349d70c4856acfce943fab35fc199b3074961313fJoe Perches } else { 201495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check (again) if DMA has finished */ 201595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (nsc_ircc_dma_receive_complete(self, iobase)) { 201695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_SFIF_IE; 201795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 201895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_SFIF_IE | IER_TMR_IE; 201995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 202031c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison } 202195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (eir & EIR_DMA_EV) { 202295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Finished with all transmissions? */ 202395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (nsc_ircc_dma_xmit_complete(self)) { 202431c221c49f92d17632e0d662eb62a27e8b425805Harvey Harrison if(self->new_speed != 0) { 202595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* As we stop the Tx queue, the speed change 202695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * need to be done when the Tx fifo is 202795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * empty. Ask for a Tx done interrupt */ 202895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_TXEMP_IE; 20297f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng } else { 203095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Check if there are more frames to be 2031eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng * transmitted */ 203295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (irda_device_txqueue_empty(self->netdev)) { 203395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Prepare for receive */ 203495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_dma_receive(self); 203595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_SFIF_IE; 203695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 203795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s(), potential " 203895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng "Tx queue lockup !\n", 203995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __FUNCTION__); 204095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 204195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 204295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Not finished yet, so interrupt on DMA again */ 204395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = IER_DMA_IE; 204495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 204595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else if (eir & EIR_TXEMP_EV) { 204695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* The Tx FIFO has totally drained out, so now we can change 204795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * the speed... - Jean II */ 204895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = nsc_ircc_change_speed(self, self->new_speed); 204995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->new_speed = 0; 205095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_wake_queue(self->netdev); 205195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Note : nsc_ircc_change_speed() restarted Rx fifo */ 205295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 205395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 205495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 205595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 205695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 205795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 205895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_interrupt (irq, dev_id, regs) 20597f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng * 206095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * An interrupt from the chip has arrived. Time to do some work 206195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 206295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 206395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic irqreturn_t nsc_ircc_interrupt(int irq, void *dev_id, 206495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct pt_regs *regs) 206595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 206695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct net_device *dev = (struct net_device *) dev_id; 206795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self; 206895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bsr, eir; 206995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 207095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 207195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!dev) { 207295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s: irq %d for unknown device.\n", 207395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng driver_name, irq); 207495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return IRQ_NONE; 207595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 207695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self = (struct nsc_ircc_cb *) dev->priv; 207795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 207895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock(&self->lock); 2079eacf69a156dd068b3dfaa0aeb4874cda8633de87Guo-Fu Tseng 208095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 208195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bsr = inb(iobase+BSR); /* Save current bank */ 208395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 208595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->ier = inb(iobase+IER); 208695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng eir = inb(iobase+EIR) & self->ier; /* Mask out the interesting ones */ 208795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 208849d70c4856acfce943fab35fc199b3074961313fJoe Perches outb(0, iobase+IER); /* Disable interrupts */ 208995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 209095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (eir) { 209195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Dispatch interrupt handler for the current speed */ 209295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->io.speed > 115200) 209349d70c4856acfce943fab35fc199b3074961313fJoe Perches nsc_ircc_fir_interrupt(self, iobase, eir); 209495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng else 209595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_sir_interrupt(self, eir); 209695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 209795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 209895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(self->ier, iobase+IER); /* Restore interrupts */ 209995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bsr, iobase+BSR); /* Restore bank register */ 210095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 210149d70c4856acfce943fab35fc199b3074961313fJoe Perches spin_unlock(&self->lock); 210249d70c4856acfce943fab35fc199b3074961313fJoe Perches return IRQ_RETVAL(eir); 210395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 210495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 210595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 210695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_is_receiving (self) 210795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 210895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Return TRUE is we are currently receiving a frame 210995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 211061357325f377889a1daffa14962d705dc814dd0eStephen Hemminger */ 211195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_is_receiving(struct nsc_ircc_cb *self) 211295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 211395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unsigned long flags; 211495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int status = FALSE; 211595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 211695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 211795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 211895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ASSERT(self != NULL, return FALSE;); 211995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 212195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->io.speed > 115200) { 212395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 212495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 212549d70c4856acfce943fab35fc199b3074961313fJoe Perches /* Check if rx FIFO is not empty */ 212649d70c4856acfce943fab35fc199b3074961313fJoe Perches bank = inb(iobase+BSR); 212795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK2); 212895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if ((inb(iobase+RXFLV) & 0x3f) != 0) { 212995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* We are receiving something */ 213095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng status = TRUE; 21317f7fd2da92b4ce20f55d3b7615089cf8e04cfffcGuo-Fu Tseng } 213295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 213395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else 213495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng status = (self->rx_buff.state != OUTSIDE_FRAME); 213595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 213695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 213795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 213849d70c4856acfce943fab35fc199b3074961313fJoe Perches return status; 213949d70c4856acfce943fab35fc199b3074961313fJoe Perches} 214095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 214195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 214295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_net_open (dev) 214395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 214495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Start the device 21458b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng * 21468b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng */ 21478b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tsengstatic int nsc_ircc_net_open(struct net_device *dev) 21488b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng{ 21498b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng struct nsc_ircc_cb *self; 21508b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng int iobase; 21518b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng char hwname[32]; 21528b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng __u8 bank; 21538b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 21548b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng IRDA_DEBUG(4, "%s()\n", __FUNCTION__); 21558b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 21568b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng IRDA_ASSERT(dev != NULL, return -1;); 21578b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng self = (struct nsc_ircc_cb *) dev->priv; 21588b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 21598b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng IRDA_ASSERT(self != NULL, return 0;); 21608b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng 216195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 216295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 216395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) { 216495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s, unable to allocate irq=%d\n", 216595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng driver_name, self->io.irq); 216695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EAGAIN; 216795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 216895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 216995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Always allocate the DMA channel after the IRQ, and clean up on 217095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * failure. 217195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 21728b53abae582cee9a17320460e0f05474097192b6Guo-Fu Tseng if (request_dma(self->io.dma, dev->name)) { 217395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s, unable to allocate dma=%d\n", 217495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng driver_name, self->io.dma); 217595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_irq(self->io.irq, dev); 217695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return -EAGAIN; 217795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 217895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 217995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 218095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 218195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* turn on interrupts */ 218395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 218495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER); 218595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 218795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 218895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 218995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Ready to play! */ 219095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_start_queue(dev); 219195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 219295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Give self a hardware name */ 219322bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko sprintf(hwname, "NSC-FIR @ 0x%03x", self->io.fir_base); 219495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 219595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 219695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Open new IrLAP layer instance, now that everything should be 219722bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko * initialized properly 219822bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko */ 219995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->irlap = irlap_open(dev, &self->qos, hwname); 220095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 220195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 220295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 220395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 220495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 220595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_net_close (dev) 220695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 220795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Stop the device 220895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 220995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 221095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_net_close(struct net_device *dev) 221195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 221295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self; 221395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase; 221495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng __u8 bank; 221595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 221695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(4, "%s()\n", __FUNCTION__); 221795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 221895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ASSERT(dev != NULL, return -1;); 221995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self = (struct nsc_ircc_cb *) dev->priv; 222195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_ASSERT(self != NULL, return 0;); 222295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Stop device */ 222495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_stop_queue(dev); 222595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 222695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Stop and remove instance of IrLAP */ 222795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->irlap) 222895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irlap_close(self->irlap); 222995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->irlap = NULL; 223095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng iobase = self->io.fir_base; 223295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng disable_dma(self->io.dma); 223495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 2235d7b576545648e487b2958c220542e111f5ac46f0Michał Mirosław /* Save current bank */ 2236d7b576545648e487b2958c220542e111f5ac46f0Michał Mirosław bank = inb(iobase+BSR); 223795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 223895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Disable interrupts */ 223995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 224095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0, iobase+IER); 224195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_irq(self->io.irq, dev); 224395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_dma(self->io.dma); 224495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 224695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 224795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 224895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 224995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 225095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 225195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng/* 225295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Function nsc_ircc_net_ioctl (dev, rq, cmd) 225395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 225495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Process IOCTL commands for this device 225595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * 225695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 225795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 2258bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng{ 2259bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng struct if_irda_req *irq = (struct if_irda_req *) rq; 2260bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng struct nsc_ircc_cb *self; 2261bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng unsigned long flags; 2262bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng int ret = 0; 2263bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2264bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng IRDA_ASSERT(dev != NULL, return -1;); 2265bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2266bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng self = dev->priv; 2267bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2268bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng IRDA_ASSERT(self != NULL, return -1;); 2269bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2270bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); 2271bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng 2272bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng switch (cmd) { 2273bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng case SIOCSBANDWIDTH: /* Set bandwidth */ 2274bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng if (!capable(CAP_NET_ADMIN)) { 2275bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng ret = -EPERM; 2276bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng break; 2277bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } 2278bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 2279bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng nsc_ircc_change_speed(self, irq->ifr_baudrate); 2280bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 2281bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng break; 2282bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng case SIOCSMEDIABUSY: /* Set media busy */ 2283bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng if (!capable(CAP_NET_ADMIN)) { 2284bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng ret = -EPERM; 2285bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng break; 2286bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng } 2287bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng irda_device_set_media_busy(self->netdev, TRUE); 2288bf5e5360fd1df1ae429ebbd81838d7d0879797d1Guo-Fu Tseng break; 228995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng case SIOCGRECEIVING: /* Check if we are receiving right now */ 229095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* This is already protected */ 229195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng irq->ifr_receiving = nsc_ircc_is_receiving(self); 229295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng break; 229395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng default: 229495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng ret = -EOPNOTSUPP; 229523020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones } 229623020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones return ret; 229723020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones} 229895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 229995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev) 230095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 230195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self = (struct nsc_ircc_cb *) dev->priv; 230295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 230395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return &self->stats; 230495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 230595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 230695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) 230795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 230895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self = platform_get_drvdata(dev); 230995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int bank; 231095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unsigned long flags; 231195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng int iobase = self->io.fir_base; 231295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (self->io.suspended) 231495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 231595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(1, "%s, Suspending\n", driver_name); 231795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 231895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rtnl_lock(); 231995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_running(self->netdev)) { 232095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_device_detach(self->netdev); 232195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 232295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Save current bank */ 232395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng bank = inb(iobase+BSR); 232495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Disable interrupts */ 232695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng switch_bank(iobase, BANK0); 232795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(0, iobase+IER); 232895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 232995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* Restore bank register */ 233095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng outb(bank, iobase+BSR); 233195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 233395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng free_irq(self->io.irq, self->netdev); 233495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng disable_dma(self->io.dma); 233595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 233695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.suspended = 1; 233795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rtnl_unlock(); 233895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 233995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 234095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 234195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengstatic int nsc_ircc_resume(struct platform_device *dev) 234395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng{ 234495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng struct nsc_ircc_cb *self = platform_get_drvdata(dev); 234595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unsigned long flags; 234695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 234795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (!self->io.suspended) 234895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 234995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 235095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_DEBUG(1, "%s, Waking up\n", driver_name); 235195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 235295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rtnl_lock(); 235395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_setup(&self->io); 235495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id); 235595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 235695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (netif_running(self->netdev)) { 235795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, 235895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->netdev->name, self->netdev)) { 235995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng IRDA_WARNING("%s, unable to allocate irq=%d\n", 236095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng driver_name, self->io.irq); 236195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 236295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng /* 236395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * Don't fail resume process, just kill this 236495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng * network interface 236595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng */ 236695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng unregister_netdevice(self->netdev); 236795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 236895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 236995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_change_speed(self, self->io.speed); 237095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 237195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng netif_device_attach(self->netdev); 237295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 237395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 237495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } else { 237595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_lock_irqsave(&self->lock, flags); 237695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng nsc_ircc_change_speed(self, 9600); 237795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng spin_unlock_irqrestore(&self->lock, flags); 237895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng } 237995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng self->io.suspended = 0; 238095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng rtnl_unlock(); 238195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 238295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng return 0; 238395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng} 238495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 238595252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); 238695252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_DESCRIPTION("NSC IrDA Device Driver"); 238795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_LICENSE("GPL"); 238895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 238995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 239095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param(qos_mtt_bits, int, 0); 239195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); 239295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param_array(io, int, NULL, 0); 239395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(io, "Base I/O addresses"); 239495252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param_array(irq, int, NULL, 0); 23958e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe PerchesMODULE_PARM_DESC(irq, "IRQ lines"); 23968e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perchesmodule_param_array(dma, int, NULL, 0); 239795252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(dma, "DMA channels"); 239895252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_param(dongle_id, int, 0); 239995252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu TsengMODULE_PARM_DESC(dongle_id, "Type-id of used dongle"); 240095252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 240195252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_init(nsc_ircc_init); 240295252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tsengmodule_exit(nsc_ircc_cleanup); 240395252236e73e789dd186ce796a2abc60b3a61ebeGuo-Fu Tseng 24048e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches