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