0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/kernel.h>
0038 #include <linux/module.h>
0039 #include <linux/init.h>
0040 #include <linux/ptrace.h>
0041 #include <linux/slab.h>
0042 #include <linux/string.h>
0043 #include <linux/timer.h>
0044 #include <linux/ioport.h>
0045 #include <linux/major.h>
0046 #include <linux/interrupt.h>
0047
0048 #include <linux/parport.h>
0049 #include <linux/parport_pc.h>
0050
0051 #include <pcmcia/cistpl.h>
0052 #include <pcmcia/ds.h>
0053 #include <pcmcia/cisreg.h>
0054 #include <pcmcia/ciscode.h>
0055
0056
0057
0058
0059
0060 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
0061 MODULE_DESCRIPTION("PCMCIA parallel port card driver");
0062 MODULE_LICENSE("Dual MPL/GPL");
0063
0064 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
0065
0066 INT_MODULE_PARM(epp_mode, 1);
0067
0068
0069
0070
0071 #define FORCE_EPP_MODE 0x08
0072
0073 typedef struct parport_info_t {
0074 struct pcmcia_device *p_dev;
0075 int ndev;
0076 struct parport *port;
0077 } parport_info_t;
0078
0079 static void parport_detach(struct pcmcia_device *p_dev);
0080 static int parport_config(struct pcmcia_device *link);
0081 static void parport_cs_release(struct pcmcia_device *);
0082
0083 static int parport_probe(struct pcmcia_device *link)
0084 {
0085 parport_info_t *info;
0086
0087 dev_dbg(&link->dev, "parport_attach()\n");
0088
0089
0090 info = kzalloc(sizeof(*info), GFP_KERNEL);
0091 if (!info) return -ENOMEM;
0092 link->priv = info;
0093 info->p_dev = link;
0094
0095 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
0096
0097 return parport_config(link);
0098 }
0099
0100 static void parport_detach(struct pcmcia_device *link)
0101 {
0102 dev_dbg(&link->dev, "parport_detach\n");
0103
0104 parport_cs_release(link);
0105
0106 kfree(link->priv);
0107 }
0108
0109 static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
0110 {
0111 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
0112 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
0113 p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
0114 p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
0115
0116 return pcmcia_request_io(p_dev);
0117 }
0118
0119 static int parport_config(struct pcmcia_device *link)
0120 {
0121 parport_info_t *info = link->priv;
0122 struct parport *p;
0123 int ret;
0124
0125 dev_dbg(&link->dev, "parport_config\n");
0126
0127 if (epp_mode)
0128 link->config_index |= FORCE_EPP_MODE;
0129
0130 ret = pcmcia_loop_config(link, parport_config_check, NULL);
0131 if (ret)
0132 goto failed;
0133
0134 if (!link->irq)
0135 goto failed;
0136 ret = pcmcia_enable_device(link);
0137 if (ret)
0138 goto failed;
0139
0140 p = parport_pc_probe_port(link->resource[0]->start,
0141 link->resource[1]->start,
0142 link->irq, PARPORT_DMA_NONE,
0143 &link->dev, IRQF_SHARED);
0144 if (p == NULL) {
0145 pr_notice("parport_cs: parport_pc_probe_port() at 0x%3x, irq %u failed\n",
0146 (unsigned int)link->resource[0]->start, link->irq);
0147 goto failed;
0148 }
0149
0150 p->modes |= PARPORT_MODE_PCSPP;
0151 if (epp_mode)
0152 p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP;
0153 info->ndev = 1;
0154 info->port = p;
0155
0156 return 0;
0157
0158 failed:
0159 parport_cs_release(link);
0160 kfree(link->priv);
0161 return -ENODEV;
0162 }
0163
0164 static void parport_cs_release(struct pcmcia_device *link)
0165 {
0166 parport_info_t *info = link->priv;
0167
0168 dev_dbg(&link->dev, "parport_release\n");
0169
0170 if (info->ndev) {
0171 struct parport *p = info->port;
0172 parport_pc_unregister_port(p);
0173 }
0174 info->ndev = 0;
0175
0176 pcmcia_disable_device(link);
0177 }
0178
0179
0180 static const struct pcmcia_device_id parport_ids[] = {
0181 PCMCIA_DEVICE_FUNC_ID(3),
0182 PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
0183 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
0184 PCMCIA_DEVICE_NULL
0185 };
0186 MODULE_DEVICE_TABLE(pcmcia, parport_ids);
0187
0188 static struct pcmcia_driver parport_cs_driver = {
0189 .owner = THIS_MODULE,
0190 .name = "parport_cs",
0191 .probe = parport_probe,
0192 .remove = parport_detach,
0193 .id_table = parport_ids,
0194 };
0195 module_pcmcia_driver(parport_cs_driver);