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 #include <linux/module.h>
0035 #include <linux/init.h>
0036 #include <linux/kernel.h>
0037 #include <linux/slab.h>
0038 #include <linux/string.h>
0039 #include <linux/ioport.h>
0040 #include <asm/io.h>
0041 #include <linux/major.h>
0042 #include <linux/blkdev.h>
0043 #include <linux/interrupt.h>
0044
0045 #include <scsi/scsi.h>
0046 #include <scsi/scsi_cmnd.h>
0047 #include <scsi/scsi_device.h>
0048 #include <scsi/scsi_eh.h>
0049 #include <scsi/scsi_host.h>
0050 #include <scsi/scsi_ioctl.h>
0051 #include <scsi/scsi_tcq.h>
0052 #include "../qlogicfas408.h"
0053
0054 #include <pcmcia/cistpl.h>
0055 #include <pcmcia/ds.h>
0056 #include <pcmcia/ciscode.h>
0057
0058
0059
0060
0061
0062 #define INT_TYPE 0
0063
0064 static char qlogic_name[] = "qlogic_cs";
0065
0066 static struct scsi_host_template qlogicfas_driver_template = {
0067 .module = THIS_MODULE,
0068 .name = qlogic_name,
0069 .proc_name = qlogic_name,
0070 .info = qlogicfas408_info,
0071 .queuecommand = qlogicfas408_queuecommand,
0072 .eh_abort_handler = qlogicfas408_abort,
0073 .eh_host_reset_handler = qlogicfas408_host_reset,
0074 .bios_param = qlogicfas408_biosparam,
0075 .can_queue = 1,
0076 .this_id = -1,
0077 .sg_tablesize = SG_ALL,
0078 .dma_boundary = PAGE_SIZE - 1,
0079 };
0080
0081
0082
0083 typedef struct scsi_info_t {
0084 struct pcmcia_device *p_dev;
0085 struct Scsi_Host *host;
0086 unsigned short manf_id;
0087 } scsi_info_t;
0088
0089 static void qlogic_release(struct pcmcia_device *link);
0090 static void qlogic_detach(struct pcmcia_device *p_dev);
0091 static int qlogic_config(struct pcmcia_device * link);
0092
0093 static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
0094 struct pcmcia_device *link, int qbase, int qlirq)
0095 {
0096 int qltyp;
0097 int qinitid;
0098 struct Scsi_Host *shost;
0099 struct qlogicfas408_priv *priv;
0100
0101 qltyp = qlogicfas408_get_chip_type(qbase, INT_TYPE);
0102 qinitid = host->this_id;
0103 if (qinitid < 0)
0104 qinitid = 7;
0105
0106 qlogicfas408_setup(qbase, qinitid, INT_TYPE);
0107
0108 host->name = qlogic_name;
0109 shost = scsi_host_alloc(host, sizeof(struct qlogicfas408_priv));
0110 if (!shost)
0111 goto err;
0112 shost->io_port = qbase;
0113 shost->n_io_port = 16;
0114 shost->dma_channel = -1;
0115 if (qlirq != -1)
0116 shost->irq = qlirq;
0117
0118 priv = get_priv_by_host(shost);
0119 priv->qlirq = qlirq;
0120 priv->qbase = qbase;
0121 priv->qinitid = qinitid;
0122 priv->shost = shost;
0123 priv->int_type = INT_TYPE;
0124
0125 if (request_irq(qlirq, qlogicfas408_ihandl, 0, qlogic_name, shost))
0126 goto free_scsi_host;
0127
0128 sprintf(priv->qinfo,
0129 "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d",
0130 qltyp, qbase, qlirq, QL_TURBO_PDMA);
0131
0132 if (scsi_add_host(shost, NULL))
0133 goto free_interrupt;
0134
0135 scsi_scan_host(shost);
0136
0137 return shost;
0138
0139 free_interrupt:
0140 free_irq(qlirq, shost);
0141
0142 free_scsi_host:
0143 scsi_host_put(shost);
0144
0145 err:
0146 return NULL;
0147 }
0148 static int qlogic_probe(struct pcmcia_device *link)
0149 {
0150 scsi_info_t *info;
0151
0152 dev_dbg(&link->dev, "qlogic_attach()\n");
0153
0154
0155 info = kzalloc(sizeof(*info), GFP_KERNEL);
0156 if (!info)
0157 return -ENOMEM;
0158 info->p_dev = link;
0159 link->priv = info;
0160 link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
0161 link->config_regs = PRESENT_OPTION;
0162
0163 return qlogic_config(link);
0164 }
0165
0166
0167
0168 static void qlogic_detach(struct pcmcia_device *link)
0169 {
0170 dev_dbg(&link->dev, "qlogic_detach\n");
0171
0172 qlogic_release(link);
0173 kfree(link->priv);
0174
0175 }
0176
0177
0178
0179 static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data)
0180 {
0181 p_dev->io_lines = 10;
0182 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
0183 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
0184
0185 if (p_dev->resource[0]->start == 0)
0186 return -ENODEV;
0187
0188 return pcmcia_request_io(p_dev);
0189 }
0190
0191 static int qlogic_config(struct pcmcia_device * link)
0192 {
0193 scsi_info_t *info = link->priv;
0194 int ret;
0195 struct Scsi_Host *host;
0196
0197 dev_dbg(&link->dev, "qlogic_config\n");
0198
0199 ret = pcmcia_loop_config(link, qlogic_config_check, NULL);
0200 if (ret)
0201 goto failed;
0202
0203 if (!link->irq)
0204 goto failed;
0205
0206 ret = pcmcia_enable_device(link);
0207 if (ret)
0208 goto failed;
0209
0210 if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
0211
0212 outb(0xb4, link->resource[0]->start + 0xd);
0213 outb(0x24, link->resource[0]->start + 0x9);
0214 outb(0x04, link->resource[0]->start + 0xd);
0215 }
0216
0217
0218 if (resource_size(link->resource[0]) == 32)
0219 host = qlogic_detect(&qlogicfas_driver_template, link,
0220 link->resource[0]->start + 16, link->irq);
0221 else
0222 host = qlogic_detect(&qlogicfas_driver_template, link,
0223 link->resource[0]->start, link->irq);
0224
0225 if (!host) {
0226 printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
0227 goto failed;
0228 }
0229
0230 info->host = host;
0231
0232 return 0;
0233
0234 failed:
0235 pcmcia_disable_device(link);
0236 return -ENODEV;
0237 }
0238
0239
0240
0241 static void qlogic_release(struct pcmcia_device *link)
0242 {
0243 scsi_info_t *info = link->priv;
0244
0245 dev_dbg(&link->dev, "qlogic_release\n");
0246
0247 scsi_remove_host(info->host);
0248
0249 free_irq(link->irq, info->host);
0250 pcmcia_disable_device(link);
0251
0252 scsi_host_put(info->host);
0253 }
0254
0255
0256
0257 static int qlogic_resume(struct pcmcia_device *link)
0258 {
0259 scsi_info_t *info = link->priv;
0260 int ret;
0261
0262 ret = pcmcia_enable_device(link);
0263 if (ret)
0264 return ret;
0265
0266 if ((info->manf_id == MANFID_MACNICA) ||
0267 (info->manf_id == MANFID_PIONEER) ||
0268 (info->manf_id == 0x0098)) {
0269 outb(0x80, link->resource[0]->start + 0xd);
0270 outb(0x24, link->resource[0]->start + 0x9);
0271 outb(0x04, link->resource[0]->start + 0xd);
0272 }
0273
0274 qlogicfas408_host_reset(NULL);
0275
0276 return 0;
0277 }
0278
0279 static const struct pcmcia_device_id qlogic_ids[] = {
0280 PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6),
0281 PCMCIA_DEVICE_PROD_ID12("EPSON", "SCSI-2 PC Card SC200", 0xd361772f, 0x299d1751),
0282 PCMCIA_DEVICE_PROD_ID12("MACNICA", "MIRACLE SCSI-II mPS110", 0x20841b68, 0xab3c3b6d),
0283 PCMCIA_DEVICE_PROD_ID12("MIDORI ELECTRONICS ", "CN-SC43", 0x6534382a, 0xd67eee79),
0284 PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J03R", 0x18df0ba0, 0x24662e8a),
0285 PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC003", 0x82375a27, 0xf68e5bf7),
0286 PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC004", 0x82375a27, 0x68eace54),
0287 PCMCIA_DEVICE_PROD_ID12("KME", "KXLC101", 0x3faee676, 0x194250ec),
0288 PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05", 0xd77b2930, 0xa85b2735),
0289 PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05 rev 1.10", 0xd77b2930, 0x70f8b5f8),
0290 PCMCIA_DEVICE_PROD_ID123("KME", "KXLC002", "00", 0x3faee676, 0x81896b61, 0xf99f065f),
0291 PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "SCSI2 CARD 37", 0x85c10e17, 0x1a2640c1),
0292 PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200A PC CARD SCSI", 0xb4585a1a, 0xa6f06ebe),
0293 PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200B PC CARD SCSI-10", 0xb4585a1a, 0x0a88dea0),
0294
0295
0296
0297 PCMCIA_DEVICE_NULL,
0298 };
0299 MODULE_DEVICE_TABLE(pcmcia, qlogic_ids);
0300
0301 static struct pcmcia_driver qlogic_cs_driver = {
0302 .owner = THIS_MODULE,
0303 .name = "qlogic_cs",
0304 .probe = qlogic_probe,
0305 .remove = qlogic_detach,
0306 .id_table = qlogic_ids,
0307 .resume = qlogic_resume,
0308 };
0309
0310 MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
0311 MODULE_DESCRIPTION("Driver for the PCMCIA Qlogic FAS SCSI controllers");
0312 MODULE_LICENSE("GPL");
0313 module_pcmcia_driver(qlogic_cs_driver);