11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds A driver for PCMCIA parallel port adapters 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (specifically, for the Quatech SPP-100 EPP card: other cards will 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds probably require driver tweaks) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parport_cs.c 1.29 2002/10/11 06:57:41 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The contents of this file are subject to the Mozilla Public 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds License Version 1.1 (the "License"); you may not use this file 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds except in compliance with the License. You may obtain a copy of 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the License at http://www.mozilla.org/MPL/ 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Software distributed under the License is distributed on an "AS 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds implied. See the License for the specific language governing 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rights and limitations under the License. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The initial developer of the original code is David A. Hinds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Alternatively, the contents of this file may be used under the 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds terms of the GNU General Public License version 2 (the "GPL"), in 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds which case the provisions of the GPL are applicable instead of the 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds above. If you wish to allow the use of your version of this file 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds only under the terms of the GPL and not to allow others to use 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds your version of this file under the MPL, indicate your decision 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds by deleting the provisions above and replace them with the notice 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and other provisions required by the GPL. If you do not delete 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the provisions above, a recipient may use your version of this 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds file under either the MPL or the GPL. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 4651dcdfec6a274afc1c6fce180d582add9ff512c0Alan Cox#include <linux/interrupt.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/parport.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/parport_pc.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cistpl.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ds.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cisreg.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ciscode.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Module parameters */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCMCIA parallel port card driver"); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("Dual MPL/GPL"); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsINT_MODULE_PARM(epp_mode, 1); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FORCE_EPP_MODE 0x08 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct parport_info_t { 74fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski struct pcmcia_device *p_dev; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ndev; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct parport *port; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} parport_info_t; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 79cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowskistatic void parport_detach(struct pcmcia_device *p_dev); 8015b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int parport_config(struct pcmcia_device *link); 81fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void parport_cs_release(struct pcmcia_device *); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8315b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int parport_probe(struct pcmcia_device *link) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parport_info_t *info; 86f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski 879b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski dev_dbg(&link->dev, "parport_attach()\n"); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create new parport device */ 90dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau info = kzalloc(sizeof(*info), GFP_KERNEL); 91f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski if (!info) return -ENOMEM; 92fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski link->priv = info; 93fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski info->p_dev = link; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9500990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; 96f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski 9715b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return parport_config(link); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* parport_attach */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void parport_detach(struct pcmcia_device *link) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1029b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski dev_dbg(&link->dev, "parport_detach\n"); 103cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski 104e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski parport_cs_release(link); 105cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(link->priv); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* parport_detach */ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10900990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowskistatic int parport_config_check(struct pcmcia_device *p_dev, void *priv_data) 11084e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski{ 11100990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; 11200990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; 11300990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; 11400990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; 11500990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski 11600990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski return pcmcia_request_io(p_dev); 11784e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski} 11884e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski 11915b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int parport_config(struct pcmcia_device *link) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parport_info_t *info = link->priv; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct parport *p; 1239b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski int ret; 12484e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski 1259b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski dev_dbg(&link->dev, "parport_config\n"); 12684e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski 12700990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski if (epp_mode) 12800990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski link->config_index |= FORCE_EPP_MODE; 12900990e7ce0b0e596fe41d9c64d6933ea70084003Dominik Brodowski 1309b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski ret = pcmcia_loop_config(link, parport_config_check, NULL); 1319b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski if (ret) 13284e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski goto failed; 13384e2d34004dcd0c90d1af43a143511b334f11a4dDominik Brodowski 134eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski if (!link->irq) 1359b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski goto failed; 1361ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski ret = pcmcia_enable_device(link); 1379b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski if (ret) 1389b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski goto failed; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1409a017a910346afd88ec2e065989903bf211a7d37Dominik Brodowski p = parport_pc_probe_port(link->resource[0]->start, 1419a017a910346afd88ec2e065989903bf211a7d37Dominik Brodowski link->resource[1]->start, 142eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski link->irq, PARPORT_DMA_NONE, 14351dcdfec6a274afc1c6fce180d582add9ff512c0Alan Cox &link->dev, IRQF_SHARED); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p == NULL) { 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " 1469a017a910346afd88ec2e065989903bf211a7d37Dominik Brodowski "0x%3x, irq %u failed\n", 1479a017a910346afd88ec2e065989903bf211a7d37Dominik Brodowski (unsigned int) link->resource[0]->start, 148eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski link->irq); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->modes |= PARPORT_MODE_PCSPP; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (epp_mode) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->ndev = 1; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->port = p; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15815b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return 0; 15915b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed: 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parport_cs_release(link); 16215b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* parport_config */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16523d5f96ce6571da51c0f6bfa7361e5f91f314b2bAdrian Bunkstatic void parport_cs_release(struct pcmcia_device *link) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1675f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski parport_info_t *info = link->priv; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1699b44de2015ff4a2ed1d56efedfcc72b917d356a6Dominik Brodowski dev_dbg(&link->dev, "parport_release\n"); 1705f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski 1715f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski if (info->ndev) { 1725f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski struct parport *p = info->port; 1735f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski parport_pc_unregister_port(p); 1745f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski } 1755f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski info->ndev = 0; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 177fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_disable_device(link); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* parport_cs_release */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 18125f8f54f6e178acfd503a95441b0ea05c525f751Joe Perchesstatic const struct pcmcia_device_id parport_ids[] = { 182476835afd7fefa353e932e160c14effc67e2ba6eDominik Brodowski PCMCIA_DEVICE_FUNC_ID(3), 18344e5e33e99e1b955ac6f0bb26abd9380629b48a9Tony Olech PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), 184476835afd7fefa353e932e160c14effc67e2ba6eDominik Brodowski PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003), 185476835afd7fefa353e932e160c14effc67e2ba6eDominik Brodowski PCMCIA_DEVICE_NULL 186476835afd7fefa353e932e160c14effc67e2ba6eDominik Brodowski}; 187476835afd7fefa353e932e160c14effc67e2ba6eDominik BrodowskiMODULE_DEVICE_TABLE(pcmcia, parport_ids); 188476835afd7fefa353e932e160c14effc67e2ba6eDominik Brodowski 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pcmcia_driver parport_cs_driver = { 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 1912e9b981a7c63ee8278df6823f8389d69dad1a499Dominik Brodowski .name = "parport_cs", 19215b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski .probe = parport_probe, 193cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski .remove = parport_detach, 194476835afd7fefa353e932e160c14effc67e2ba6eDominik Brodowski .id_table = parport_ids, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_parport_cs(void) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pcmcia_register_driver(&parport_cs_driver); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_parport_cs(void) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_unregister_driver(&parport_cs_driver); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_parport_cs); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_parport_cs); 209