linux/drivers/isdn/hardware/mISDN/speedfax.c
<<
>>
Prefs
   1/*
   2 * speedfax.c   low level stuff for Sedlbauer Speedfax+ cards
   3 *              based on the ISAR DSP
   4 *              Thanks to Sedlbauer AG for informations and HW
   5 *
   6 * Author       Karsten Keil <keil@isdn4linux.de>
   7 *
   8 * Copyright 2009  by Karsten Keil <keil@isdn4linux.de>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22 *
  23 */
  24
  25#include <linux/interrupt.h>
  26#include <linux/module.h>
  27#include <linux/slab.h>
  28#include <linux/pci.h>
  29#include <linux/delay.h>
  30#include <linux/mISDNhw.h>
  31#include <linux/firmware.h>
  32#include "ipac.h"
  33#include "isar.h"
  34
  35#define SPEEDFAX_REV    "2.0"
  36
  37#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID  0x51
  38#define PCI_SUBVENDOR_SPEEDFAX_PCI      0x54
  39#define PCI_SUB_ID_SEDLBAUER            0x01
  40
  41#define SFAX_PCI_ADDR           0xc8
  42#define SFAX_PCI_ISAC           0xd0
  43#define SFAX_PCI_ISAR           0xe0
  44
  45/* TIGER 100 Registers */
  46
  47#define TIGER_RESET_ADDR        0x00
  48#define TIGER_EXTERN_RESET_ON   0x01
  49#define TIGER_EXTERN_RESET_OFF  0x00
  50#define TIGER_AUX_CTRL          0x02
  51#define TIGER_AUX_DATA          0x03
  52#define TIGER_AUX_IRQMASK       0x05
  53#define TIGER_AUX_STATUS        0x07
  54
  55/* Tiger AUX BITs */
  56#define SFAX_AUX_IOMASK         0xdd    /* 1 and 5 are inputs */
  57#define SFAX_ISAR_RESET_BIT_OFF 0x00
  58#define SFAX_ISAR_RESET_BIT_ON  0x01
  59#define SFAX_TIGER_IRQ_BIT      0x02
  60#define SFAX_LED1_BIT           0x08
  61#define SFAX_LED2_BIT           0x10
  62
  63#define SFAX_PCI_RESET_ON       (SFAX_ISAR_RESET_BIT_ON)
  64#define SFAX_PCI_RESET_OFF      (SFAX_LED1_BIT | SFAX_LED2_BIT)
  65
  66static int sfax_cnt;
  67static u32 debug;
  68static u32 irqloops = 4;
  69
  70struct sfax_hw {
  71        struct list_head        list;
  72        struct pci_dev          *pdev;
  73        char                    name[MISDN_MAX_IDLEN];
  74        u32                     irq;
  75        u32                     irqcnt;
  76        u32                     cfg;
  77        struct _ioport          p_isac;
  78        struct _ioport          p_isar;
  79        u8                      aux_data;
  80        spinlock_t              lock;   /* HW access lock */
  81        struct isac_hw          isac;
  82        struct isar_hw          isar;
  83};
  84
  85static LIST_HEAD(Cards);
  86static DEFINE_RWLOCK(card_lock); /* protect Cards */
  87
  88static void
  89_set_debug(struct sfax_hw *card)
  90{
  91        card->isac.dch.debug = debug;
  92        card->isar.ch[0].bch.debug = debug;
  93        card->isar.ch[1].bch.debug = debug;
  94}
  95
  96static int
  97set_debug(const char *val, struct kernel_param *kp)
  98{
  99        int ret;
 100        struct sfax_hw *card;
 101
 102        ret = param_set_uint(val, kp);
 103        if (!ret) {
 104                read_lock(&card_lock);
 105                list_for_each_entry(card, &Cards, list)
 106                        _set_debug(card);
 107                read_unlock(&card_lock);
 108        }
 109        return ret;
 110}
 111
 112MODULE_AUTHOR("Karsten Keil");
 113MODULE_LICENSE("GPL v2");
 114MODULE_VERSION(SPEEDFAX_REV);
 115MODULE_FIRMWARE("isdn/ISAR.BIN");
 116module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
 117MODULE_PARM_DESC(debug, "Speedfax debug mask");
 118module_param(irqloops, uint, S_IRUGO | S_IWUSR);
 119MODULE_PARM_DESC(irqloops, "Speedfax maximal irqloops (default 4)");
 120
 121IOFUNC_IND(ISAC, sfax_hw, p_isac)
 122IOFUNC_IND(ISAR, sfax_hw, p_isar)
 123
 124static irqreturn_t
 125speedfax_irq(int intno, void *dev_id)
 126{
 127        struct sfax_hw  *sf = dev_id;
 128        u8 val;
 129        int cnt = irqloops;
 130
 131        spin_lock(&sf->lock);
 132        val = inb(sf->cfg + TIGER_AUX_STATUS);
 133        if (val & SFAX_TIGER_IRQ_BIT) { /* for us or shared ? */
 134                spin_unlock(&sf->lock);
 135                return IRQ_NONE; /* shared */
 136        }
 137        sf->irqcnt++;
 138        val = ReadISAR_IND(sf, ISAR_IRQBIT);
 139Start_ISAR:
 140        if (val & ISAR_IRQSTA)
 141                mISDNisar_irq(&sf->isar);
 142        val = ReadISAC_IND(sf, ISAC_ISTA);
 143        if (val)
 144                mISDNisac_irq(&sf->isac, val);
 145        val = ReadISAR_IND(sf, ISAR_IRQBIT);
 146        if ((val & ISAR_IRQSTA) && cnt--)
 147                goto Start_ISAR;
 148        if (cnt < irqloops)
 149                pr_debug("%s: %d irqloops cpu%d\n", sf->name,
 150                         irqloops - cnt, smp_processor_id());
 151        if (irqloops && !cnt)
 152                pr_notice("%s: %d IRQ LOOP cpu%d\n", sf->name,
 153                          irqloops, smp_processor_id());
 154        spin_unlock(&sf->lock);
 155        return IRQ_HANDLED;
 156}
 157
 158static void
 159enable_hwirq(struct sfax_hw *sf)
 160{
 161        WriteISAC_IND(sf, ISAC_MASK, 0);
 162        WriteISAR_IND(sf, ISAR_IRQBIT, ISAR_IRQMSK);
 163        outb(SFAX_TIGER_IRQ_BIT, sf->cfg + TIGER_AUX_IRQMASK);
 164}
 165
 166static void
 167disable_hwirq(struct sfax_hw *sf)
 168{
 169        WriteISAC_IND(sf, ISAC_MASK, 0xFF);
 170        WriteISAR_IND(sf, ISAR_IRQBIT, 0);
 171        outb(0, sf->cfg + TIGER_AUX_IRQMASK);
 172}
 173
 174static void
 175reset_speedfax(struct sfax_hw *sf)
 176{
 177
 178        pr_debug("%s: resetting card\n", sf->name);
 179        outb(TIGER_EXTERN_RESET_ON, sf->cfg + TIGER_RESET_ADDR);
 180        outb(SFAX_PCI_RESET_ON, sf->cfg + TIGER_AUX_DATA);
 181        mdelay(1);
 182        outb(TIGER_EXTERN_RESET_OFF, sf->cfg + TIGER_RESET_ADDR);
 183        sf->aux_data = SFAX_PCI_RESET_OFF;
 184        outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
 185        mdelay(1);
 186}
 187
 188static int
 189sfax_ctrl(struct sfax_hw  *sf, u32 cmd, u_long arg)
 190{
 191        int ret = 0;
 192
 193        switch (cmd) {
 194        case HW_RESET_REQ:
 195                reset_speedfax(sf);
 196                break;
 197        case HW_ACTIVATE_IND:
 198                if (arg & 1)
 199                        sf->aux_data &= ~SFAX_LED1_BIT;
 200                if (arg & 2)
 201                        sf->aux_data &= ~SFAX_LED2_BIT;
 202                outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
 203                break;
 204        case HW_DEACT_IND:
 205                if (arg & 1)
 206                        sf->aux_data |= SFAX_LED1_BIT;
 207                if (arg & 2)
 208                        sf->aux_data |= SFAX_LED2_BIT;
 209                outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
 210                break;
 211        default:
 212                pr_info("%s: %s unknown command %x %lx\n",
 213                        sf->name, __func__, cmd, arg);
 214                ret = -EINVAL;
 215                break;
 216        }
 217        return ret;
 218}
 219
 220static int
 221channel_ctrl(struct sfax_hw  *sf, struct mISDN_ctrl_req *cq)
 222{
 223        int     ret = 0;
 224
 225        switch (cq->op) {
 226        case MISDN_CTRL_GETOP:
 227                cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
 228                break;
 229        case MISDN_CTRL_LOOP:
 230                /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
 231                if (cq->channel < 0 || cq->channel > 3) {
 232                        ret = -EINVAL;
 233                        break;
 234                }
 235                ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
 236                break;
 237        case MISDN_CTRL_L1_TIMER3:
 238                ret = sf->isac.ctrl(&sf->isac, HW_TIMER3_VALUE, cq->p1);
 239                break;
 240        default:
 241                pr_info("%s: unknown Op %x\n", sf->name, cq->op);
 242                ret = -EINVAL;
 243                break;
 244        }
 245        return ret;
 246}
 247
 248static int
 249sfax_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
 250{
 251        struct mISDNdevice      *dev = container_of(ch, struct mISDNdevice, D);
 252        struct dchannel         *dch = container_of(dev, struct dchannel, dev);
 253        struct sfax_hw          *sf = dch->hw;
 254        struct channel_req      *rq;
 255        int                     err = 0;
 256
 257        pr_debug("%s: cmd:%x %p\n", sf->name, cmd, arg);
 258        switch (cmd) {
 259        case OPEN_CHANNEL:
 260                rq = arg;
 261                if (rq->protocol == ISDN_P_TE_S0)
 262                        err = sf->isac.open(&sf->isac, rq);
 263                else
 264                        err = sf->isar.open(&sf->isar, rq);
 265                if (err)
 266                        break;
 267                if (!try_module_get(THIS_MODULE))
 268                        pr_info("%s: cannot get module\n", sf->name);
 269                break;
 270        case CLOSE_CHANNEL:
 271                pr_debug("%s: dev(%d) close from %p\n", sf->name,
 272                         dch->dev.id, __builtin_return_address(0));
 273                module_put(THIS_MODULE);
 274                break;
 275        case CONTROL_CHANNEL:
 276                err = channel_ctrl(sf, arg);
 277                break;
 278        default:
 279                pr_debug("%s: unknown command %x\n", sf->name, cmd);
 280                return -EINVAL;
 281        }
 282        return err;
 283}
 284
 285static int
 286init_card(struct sfax_hw *sf)
 287{
 288        int     ret, cnt = 3;
 289        u_long  flags;
 290
 291        ret = request_irq(sf->irq, speedfax_irq, IRQF_SHARED, sf->name, sf);
 292        if (ret) {
 293                pr_info("%s: couldn't get interrupt %d\n", sf->name, sf->irq);
 294                return ret;
 295        }
 296        while (cnt--) {
 297                spin_lock_irqsave(&sf->lock, flags);
 298                ret = sf->isac.init(&sf->isac);
 299                if (ret) {
 300                        spin_unlock_irqrestore(&sf->lock, flags);
 301                        pr_info("%s: ISAC init failed with %d\n",
 302                                sf->name, ret);
 303                        break;
 304                }
 305                enable_hwirq(sf);
 306                /* RESET Receiver and Transmitter */
 307                WriteISAC_IND(sf, ISAC_CMDR, 0x41);
 308                spin_unlock_irqrestore(&sf->lock, flags);
 309                msleep_interruptible(10);
 310                if (debug & DEBUG_HW)
 311                        pr_notice("%s: IRQ %d count %d\n", sf->name,
 312                                  sf->irq, sf->irqcnt);
 313                if (!sf->irqcnt) {
 314                        pr_info("%s: IRQ(%d) got no requests during init %d\n",
 315                                sf->name, sf->irq, 3 - cnt);
 316                } else
 317                        return 0;
 318        }
 319        free_irq(sf->irq, sf);
 320        return -EIO;
 321}
 322
 323
 324static int
 325setup_speedfax(struct sfax_hw *sf)
 326{
 327        u_long flags;
 328
 329        if (!request_region(sf->cfg, 256, sf->name)) {
 330                pr_info("mISDN: %s config port %x-%x already in use\n",
 331                        sf->name, sf->cfg, sf->cfg + 255);
 332                return -EIO;
 333        }
 334        outb(0xff, sf->cfg);
 335        outb(0, sf->cfg);
 336        outb(0xdd, sf->cfg + TIGER_AUX_CTRL);
 337        outb(0, sf->cfg + TIGER_AUX_IRQMASK);
 338
 339        sf->isac.type = IPAC_TYPE_ISAC;
 340        sf->p_isac.ale = sf->cfg + SFAX_PCI_ADDR;
 341        sf->p_isac.port = sf->cfg + SFAX_PCI_ISAC;
 342        sf->p_isar.ale = sf->cfg + SFAX_PCI_ADDR;
 343        sf->p_isar.port = sf->cfg + SFAX_PCI_ISAR;
 344        ASSIGN_FUNC(IND, ISAC, sf->isac);
 345        ASSIGN_FUNC(IND, ISAR, sf->isar);
 346        spin_lock_irqsave(&sf->lock, flags);
 347        reset_speedfax(sf);
 348        disable_hwirq(sf);
 349        spin_unlock_irqrestore(&sf->lock, flags);
 350        return 0;
 351}
 352
 353static void
 354release_card(struct sfax_hw *card) {
 355        u_long  flags;
 356
 357        spin_lock_irqsave(&card->lock, flags);
 358        disable_hwirq(card);
 359        spin_unlock_irqrestore(&card->lock, flags);
 360        card->isac.release(&card->isac);
 361        free_irq(card->irq, card);
 362        card->isar.release(&card->isar);
 363        mISDN_unregister_device(&card->isac.dch.dev);
 364        release_region(card->cfg, 256);
 365        pci_disable_device(card->pdev);
 366        pci_set_drvdata(card->pdev, NULL);
 367        write_lock_irqsave(&card_lock, flags);
 368        list_del(&card->list);
 369        write_unlock_irqrestore(&card_lock, flags);
 370        kfree(card);
 371        sfax_cnt--;
 372}
 373
 374static int
 375setup_instance(struct sfax_hw *card)
 376{
 377        const struct firmware *firmware;
 378        int i, err;
 379        u_long flags;
 380
 381        snprintf(card->name, MISDN_MAX_IDLEN - 1, "Speedfax.%d", sfax_cnt + 1);
 382        write_lock_irqsave(&card_lock, flags);
 383        list_add_tail(&card->list, &Cards);
 384        write_unlock_irqrestore(&card_lock, flags);
 385        _set_debug(card);
 386        spin_lock_init(&card->lock);
 387        card->isac.hwlock = &card->lock;
 388        card->isar.hwlock = &card->lock;
 389        card->isar.ctrl = (void *)&sfax_ctrl;
 390        card->isac.name = card->name;
 391        card->isar.name = card->name;
 392        card->isar.owner = THIS_MODULE;
 393
 394        err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev);
 395        if (err < 0) {
 396                pr_info("%s: firmware request failed %d\n",
 397                        card->name, err);
 398                goto error_fw;
 399        }
 400        if (debug & DEBUG_HW)
 401                pr_notice("%s: got firmware %zu bytes\n",
 402                          card->name, firmware->size);
 403
 404        mISDNisac_init(&card->isac, card);
 405
 406        card->isac.dch.dev.D.ctrl = sfax_dctrl;
 407        card->isac.dch.dev.Bprotocols =
 408                mISDNisar_init(&card->isar, card);
 409        for (i = 0; i < 2; i++) {
 410                set_channelmap(i + 1, card->isac.dch.dev.channelmap);
 411                list_add(&card->isar.ch[i].bch.ch.list,
 412                         &card->isac.dch.dev.bchannels);
 413        }
 414
 415        err = setup_speedfax(card);
 416        if (err)
 417                goto error_setup;
 418        err = card->isar.init(&card->isar);
 419        if (err)
 420                goto error;
 421        err = mISDN_register_device(&card->isac.dch.dev,
 422                                    &card->pdev->dev, card->name);
 423        if (err)
 424                goto error;
 425        err = init_card(card);
 426        if (err)
 427                goto error_init;
 428        err = card->isar.firmware(&card->isar, firmware->data, firmware->size);
 429        if (!err)  {
 430                release_firmware(firmware);
 431                sfax_cnt++;
 432                pr_notice("SpeedFax %d cards installed\n", sfax_cnt);
 433                return 0;
 434        }
 435        disable_hwirq(card);
 436        free_irq(card->irq, card);
 437error_init:
 438        mISDN_unregister_device(&card->isac.dch.dev);
 439error:
 440        release_region(card->cfg, 256);
 441error_setup:
 442        card->isac.release(&card->isac);
 443        card->isar.release(&card->isar);
 444        release_firmware(firmware);
 445error_fw:
 446        pci_disable_device(card->pdev);
 447        write_lock_irqsave(&card_lock, flags);
 448        list_del(&card->list);
 449        write_unlock_irqrestore(&card_lock, flags);
 450        kfree(card);
 451        return err;
 452}
 453
 454static int
 455sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 456{
 457        int err = -ENOMEM;
 458        struct sfax_hw *card = kzalloc(sizeof(struct sfax_hw), GFP_KERNEL);
 459
 460        if (!card) {
 461                pr_info("No memory for Speedfax+ PCI\n");
 462                return err;
 463        }
 464        card->pdev = pdev;
 465        err = pci_enable_device(pdev);
 466        if (err) {
 467                kfree(card);
 468                return err;
 469        }
 470
 471        pr_notice("mISDN: Speedfax found adapter %s at %s\n",
 472                  (char *)ent->driver_data, pci_name(pdev));
 473
 474        card->cfg = pci_resource_start(pdev, 0);
 475        card->irq = pdev->irq;
 476        pci_set_drvdata(pdev, card);
 477        err = setup_instance(card);
 478        if (err)
 479                pci_set_drvdata(pdev, NULL);
 480        return err;
 481}
 482
 483static void
 484sfax_remove_pci(struct pci_dev *pdev)
 485{
 486        struct sfax_hw  *card = pci_get_drvdata(pdev);
 487
 488        if (card)
 489                release_card(card);
 490        else
 491                pr_debug("%s: drvdata already removed\n", __func__);
 492}
 493
 494static struct pci_device_id sfaxpci_ids[] = {
 495        { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
 496          PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
 497          0, 0, (unsigned long) "Pyramid Speedfax + PCI"
 498        },
 499        { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
 500          PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER,
 501          0, 0, (unsigned long) "Sedlbauer Speedfax + PCI"
 502        },
 503        { }
 504};
 505MODULE_DEVICE_TABLE(pci, sfaxpci_ids);
 506
 507static struct pci_driver sfaxpci_driver = {
 508        .name = "speedfax+ pci",
 509        .probe = sfaxpci_probe,
 510        .remove = sfax_remove_pci,
 511        .id_table = sfaxpci_ids,
 512};
 513
 514static int __init
 515Speedfax_init(void)
 516{
 517        int err;
 518
 519        pr_notice("Sedlbauer Speedfax+ Driver Rev. %s\n",
 520                  SPEEDFAX_REV);
 521        err = pci_register_driver(&sfaxpci_driver);
 522        return err;
 523}
 524
 525static void __exit
 526Speedfax_cleanup(void)
 527{
 528        pci_unregister_driver(&sfaxpci_driver);
 529}
 530
 531module_init(Speedfax_init);
 532module_exit(Speedfax_cleanup);
 533