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