]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/scsi/pcmcia/qlogic_stub.c
Merge branch 'docs-next' of git://git.lwn.net/linux-2.6
[mirror_ubuntu-hirsute-kernel.git] / drivers / scsi / pcmcia / qlogic_stub.c
CommitLineData
1da177e4
LT
1/*======================================================================
2
3 A driver for the Qlogic SCSI card
4
5 qlogic_cs.c 1.79 2000/06/12 21:27:26
6
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
11
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
31
32======================================================================*/
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/kernel.h>
1da177e4
LT
37#include <linux/slab.h>
38#include <linux/string.h>
39#include <linux/ioport.h>
40#include <asm/io.h>
41#include <scsi/scsi.h>
42#include <linux/major.h>
43#include <linux/blkdev.h>
44#include <scsi/scsi_ioctl.h>
45#include <linux/interrupt.h>
46
47#include "scsi.h"
48#include <scsi/scsi_host.h>
49#include "../qlogicfas408.h"
50
1da177e4
LT
51#include <pcmcia/cs_types.h>
52#include <pcmcia/cs.h>
53#include <pcmcia/cistpl.h>
54#include <pcmcia/ds.h>
55#include <pcmcia/ciscode.h>
56
57/* Set the following to 2 to use normal interrupt (active high/totempole-
58 * tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
59 * drain
60 */
61#define INT_TYPE 0
62
63static char qlogic_name[] = "qlogic_cs";
64
d0be4a7d 65static struct scsi_host_template qlogicfas_driver_template = {
1da177e4
LT
66 .module = THIS_MODULE,
67 .name = qlogic_name,
68 .proc_name = qlogic_name,
69 .info = qlogicfas408_info,
70 .queuecommand = qlogicfas408_queuecommand,
71 .eh_abort_handler = qlogicfas408_abort,
72 .eh_bus_reset_handler = qlogicfas408_bus_reset,
1da177e4
LT
73 .bios_param = qlogicfas408_biosparam,
74 .can_queue = 1,
75 .this_id = -1,
76 .sg_tablesize = SG_ALL,
77 .cmd_per_lun = 1,
78 .use_clustering = DISABLE_CLUSTERING,
79};
80
81/*====================================================================*/
82
83typedef struct scsi_info_t {
fd238232 84 struct pcmcia_device *p_dev;
1da177e4
LT
85 struct Scsi_Host *host;
86 unsigned short manf_id;
87} scsi_info_t;
88
fba395ee 89static void qlogic_release(struct pcmcia_device *link);
cc3b4866 90static void qlogic_detach(struct pcmcia_device *p_dev);
15b99ac1 91static int qlogic_config(struct pcmcia_device * link);
1da177e4 92
d0be4a7d 93static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
fba395ee 94 struct pcmcia_device *link, int qbase, int qlirq)
1da177e4
LT
95{
96 int qltyp; /* type of chip */
97 int qinitid;
98 struct Scsi_Host *shost; /* registered host structure */
99 struct qlogicfas408_priv *priv;
100
101 qltyp = qlogicfas408_get_chip_type(qbase, INT_TYPE);
102 qinitid = host->this_id;
103 if (qinitid < 0)
104 qinitid = 7; /* if no ID, use 7 */
105
106 qlogicfas408_setup(qbase, qinitid, INT_TYPE);
107
108 host->name = qlogic_name;
109 shost = scsi_host_alloc(host, sizeof(struct qlogicfas408_priv));
110 if (!shost)
111 goto err;
112 shost->io_port = qbase;
113 shost->n_io_port = 16;
114 shost->dma_channel = -1;
115 if (qlirq != -1)
116 shost->irq = qlirq;
117
118 priv = get_priv_by_host(shost);
119 priv->qlirq = qlirq;
120 priv->qbase = qbase;
121 priv->qinitid = qinitid;
122 priv->shost = shost;
123 priv->int_type = INT_TYPE;
124
125 if (request_irq(qlirq, qlogicfas408_ihandl, 0, qlogic_name, shost))
126 goto free_scsi_host;
127
128 sprintf(priv->qinfo,
129 "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d",
130 qltyp, qbase, qlirq, QL_TURBO_PDMA);
131
132 if (scsi_add_host(shost, NULL))
133 goto free_interrupt;
134
135 scsi_scan_host(shost);
136
137 return shost;
138
139free_interrupt:
140 free_irq(qlirq, shost);
141
142free_scsi_host:
143 scsi_host_put(shost);
144
145err:
146 return NULL;
147}
15b99ac1 148static int qlogic_probe(struct pcmcia_device *link)
1da177e4
LT
149{
150 scsi_info_t *info;
1da177e4 151
3e716617 152 dev_dbg(&link->dev, "qlogic_attach()\n");
1da177e4
LT
153
154 /* Create new SCSI device */
dd00cc48 155 info = kzalloc(sizeof(*info), GFP_KERNEL);
1da177e4 156 if (!info)
f8cfa618 157 return -ENOMEM;
fba395ee 158 info->p_dev = link;
1da177e4
LT
159 link->priv = info;
160 link->io.NumPorts1 = 16;
161 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
162 link->io.IOAddrLines = 10;
1da177e4 163 link->conf.Attributes = CONF_ENABLE_IRQ;
1da177e4
LT
164 link->conf.IntType = INT_MEMORY_AND_IO;
165 link->conf.Present = PRESENT_OPTION;
166
15b99ac1 167 return qlogic_config(link);
1da177e4
LT
168} /* qlogic_attach */
169
170/*====================================================================*/
171
fba395ee 172static void qlogic_detach(struct pcmcia_device *link)
1da177e4 173{
3e716617 174 dev_dbg(&link->dev, "qlogic_detach\n");
1da177e4 175
e2d40963 176 qlogic_release(link);
1da177e4
LT
177 kfree(link->priv);
178
179} /* qlogic_detach */
180
181/*====================================================================*/
182
0e6f9d27 183static int qlogic_config_check(struct pcmcia_device *p_dev,
8e2fc39d
DB
184 cistpl_cftable_entry_t *cfg,
185 cistpl_cftable_entry_t *dflt,
ad913c11 186 unsigned int vcc,
8e2fc39d 187 void *priv_data)
0e6f9d27 188{
0e6f9d27
DB
189 p_dev->io.BasePort1 = cfg->io.win[0].base;
190 p_dev->io.NumPorts1 = cfg->io.win[0].len;
191
192 if (p_dev->io.BasePort1 == 0)
193 return -ENODEV;
194
195 return pcmcia_request_io(p_dev, &p_dev->io);
196}
197
15b99ac1 198static int qlogic_config(struct pcmcia_device * link)
1da177e4 199{
1da177e4 200 scsi_info_t *info = link->priv;
3e716617 201 int ret;
1da177e4
LT
202 struct Scsi_Host *host;
203
3e716617 204 dev_dbg(&link->dev, "qlogic_config\n");
1da177e4 205
3e716617
DB
206 ret = pcmcia_loop_config(link, qlogic_config_check, NULL);
207 if (ret)
208 goto failed;
209
eb14120f 210 if (!link->irq)
0e6f9d27 211 goto failed;
1da177e4 212
3e716617
DB
213 ret = pcmcia_request_configuration(link, &link->conf);
214 if (ret)
215 goto failed;
1da177e4
LT
216
217 if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
218 /* set ATAcmd */
219 outb(0xb4, link->io.BasePort1 + 0xd);
220 outb(0x24, link->io.BasePort1 + 0x9);
221 outb(0x04, link->io.BasePort1 + 0xd);
222 }
223
224 /* The KXL-810AN has a bigger IO port window */
225 if (link->io.NumPorts1 == 32)
226 host = qlogic_detect(&qlogicfas_driver_template, link,
eb14120f 227 link->io.BasePort1 + 16, link->irq);
1da177e4
LT
228 else
229 host = qlogic_detect(&qlogicfas_driver_template, link,
eb14120f 230 link->io.BasePort1, link->irq);
1da177e4
LT
231
232 if (!host) {
233 printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
3e716617 234 goto failed;
1da177e4
LT
235 }
236
1da177e4
LT
237 info->host = host;
238
15b99ac1 239 return 0;
1da177e4 240
0e6f9d27 241failed:
3e716617 242 pcmcia_disable_device(link);
15b99ac1 243 return -ENODEV;
1da177e4
LT
244} /* qlogic_config */
245
246/*====================================================================*/
247
fba395ee 248static void qlogic_release(struct pcmcia_device *link)
1da177e4
LT
249{
250 scsi_info_t *info = link->priv;
251
3e716617 252 dev_dbg(&link->dev, "qlogic_release\n");
1da177e4
LT
253
254 scsi_remove_host(info->host);
1da177e4 255
eb14120f 256 free_irq(link->irq, info->host);
fba395ee 257 pcmcia_disable_device(link);
1da177e4
LT
258
259 scsi_host_put(info->host);
1da177e4
LT
260}
261
262/*====================================================================*/
263
fba395ee 264static int qlogic_resume(struct pcmcia_device *link)
98e4c28b 265{
e2d40963
DB
266 scsi_info_t *info = link->priv;
267
268 pcmcia_request_configuration(link, &link->conf);
269 if ((info->manf_id == MANFID_MACNICA) ||
270 (info->manf_id == MANFID_PIONEER) ||
271 (info->manf_id == 0x0098)) {
272 outb(0x80, link->io.BasePort1 + 0xd);
273 outb(0x24, link->io.BasePort1 + 0x9);
274 outb(0x04, link->io.BasePort1 + 0xd);
98e4c28b 275 }
e2d40963
DB
276 /* Ugggglllyyyy!!! */
277 qlogicfas408_bus_reset(NULL);
98e4c28b
DB
278
279 return 0;
280}
281
7a5a6eeb
DB
282static struct pcmcia_device_id qlogic_ids[] = {
283 PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6),
284 PCMCIA_DEVICE_PROD_ID12("EPSON", "SCSI-2 PC Card SC200", 0xd361772f, 0x299d1751),
285 PCMCIA_DEVICE_PROD_ID12("MACNICA", "MIRACLE SCSI-II mPS110", 0x20841b68, 0xab3c3b6d),
286 PCMCIA_DEVICE_PROD_ID12("MIDORI ELECTRONICS ", "CN-SC43", 0x6534382a, 0xd67eee79),
287 PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J03R", 0x18df0ba0, 0x24662e8a),
288 PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC003", 0x82375a27, 0xf68e5bf7),
289 PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC004", 0x82375a27, 0x68eace54),
290 PCMCIA_DEVICE_PROD_ID12("KME", "KXLC101", 0x3faee676, 0x194250ec),
291 PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05", 0xd77b2930, 0xa85b2735),
292 PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05 rev 1.10", 0xd77b2930, 0x70f8b5f8),
293 PCMCIA_DEVICE_PROD_ID123("KME", "KXLC002", "00", 0x3faee676, 0x81896b61, 0xf99f065f),
294 PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "SCSI2 CARD 37", 0x85c10e17, 0x1a2640c1),
295 PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200A PC CARD SCSI", 0xb4585a1a, 0xa6f06ebe),
296 PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200B PC CARD SCSI-10", 0xb4585a1a, 0x0a88dea0),
297 /* these conflict with other cards! */
298 /* PCMCIA_DEVICE_PROD_ID123("MACNICA", "MIRACLE SCSI", "mPS100", 0x20841b68, 0xf8dedaeb, 0x89f7fafb), */
299 /* PCMCIA_DEVICE_PROD_ID123("MACNICA", "MIRACLE SCSI", "mPS100", 0x20841b68, 0xf8dedaeb, 0x89f7fafb), */
300 PCMCIA_DEVICE_NULL,
301};
302MODULE_DEVICE_TABLE(pcmcia, qlogic_ids);
1da177e4
LT
303
304static struct pcmcia_driver qlogic_cs_driver = {
305 .owner = THIS_MODULE,
306 .drv = {
307 .name = "qlogic_cs",
308 },
15b99ac1 309 .probe = qlogic_probe,
cc3b4866 310 .remove = qlogic_detach,
7a5a6eeb 311 .id_table = qlogic_ids,
98e4c28b 312 .resume = qlogic_resume,
1da177e4
LT
313};
314
315static int __init init_qlogic_cs(void)
316{
317 return pcmcia_register_driver(&qlogic_cs_driver);
318}
319
320static void __exit exit_qlogic_cs(void)
321{
322 pcmcia_unregister_driver(&qlogic_cs_driver);
1da177e4
LT
323}
324
325MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
326MODULE_DESCRIPTION("Driver for the PCMCIA Qlogic FAS SCSI controllers");
327MODULE_LICENSE("GPL");
328module_init(init_qlogic_cs);
329module_exit(exit_qlogic_cs);