11da177e4SLinus Torvalds /*======================================================================
21da177e4SLinus Torvalds
31da177e4SLinus Torvalds A driver for Adaptec AHA152X-compatible PCMCIA SCSI cards.
41da177e4SLinus Torvalds
51da177e4SLinus Torvalds This driver supports the Adaptec AHA-1460, the New Media Bus
61da177e4SLinus Torvalds Toaster, and the New Media Toast & Jam.
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds aha152x_cs.c 1.54 2000/06/12 21:27:25
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds The contents of this file are subject to the Mozilla Public
111da177e4SLinus Torvalds License Version 1.1 (the "License"); you may not use this file
121da177e4SLinus Torvalds except in compliance with the License. You may obtain a copy of
131da177e4SLinus Torvalds the License at http://www.mozilla.org/MPL/
141da177e4SLinus Torvalds
151da177e4SLinus Torvalds Software distributed under the License is distributed on an "AS
161da177e4SLinus Torvalds IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
171da177e4SLinus Torvalds implied. See the License for the specific language governing
181da177e4SLinus Torvalds rights and limitations under the License.
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds The initial developer of the original code is David A. Hinds
211da177e4SLinus Torvalds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
221da177e4SLinus Torvalds are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds Alternatively, the contents of this file may be used under the
251da177e4SLinus Torvalds terms of the GNU General Public License version 2 (the "GPL"), in which
261da177e4SLinus Torvalds case the provisions of the GPL are applicable instead of the
271da177e4SLinus Torvalds above. If you wish to allow the use of your version of this file
281da177e4SLinus Torvalds only under the terms of the GPL and not to allow others to use
291da177e4SLinus Torvalds your version of this file under the MPL, indicate your decision
301da177e4SLinus Torvalds by deleting the provisions above and replace them with the notice
311da177e4SLinus Torvalds and other provisions required by the GPL. If you do not delete
321da177e4SLinus Torvalds the provisions above, a recipient may use your version of this
331da177e4SLinus Torvalds file under either the MPL or the GPL.
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds ======================================================================*/
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds #include <linux/module.h>
381da177e4SLinus Torvalds #include <linux/init.h>
391da177e4SLinus Torvalds #include <linux/kernel.h>
401da177e4SLinus Torvalds #include <linux/slab.h>
411da177e4SLinus Torvalds #include <linux/string.h>
421da177e4SLinus Torvalds #include <linux/ioport.h>
431da177e4SLinus Torvalds #include <linux/major.h>
441da177e4SLinus Torvalds #include <linux/blkdev.h>
451da177e4SLinus Torvalds
46*53555fb7SBart Van Assche #include <scsi/scsi.h>
47*53555fb7SBart Van Assche #include <scsi/scsi_cmnd.h>
48*53555fb7SBart Van Assche #include <scsi/scsi_device.h>
49*53555fb7SBart Van Assche #include <scsi/scsi_eh.h>
501da177e4SLinus Torvalds #include <scsi/scsi_host.h>
51*53555fb7SBart Van Assche #include <scsi/scsi_ioctl.h>
52*53555fb7SBart Van Assche #include <scsi/scsi_tcq.h>
531da177e4SLinus Torvalds #include "aha152x.h"
541da177e4SLinus Torvalds
551da177e4SLinus Torvalds #include <pcmcia/cistpl.h>
561da177e4SLinus Torvalds #include <pcmcia/ds.h>
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds
591da177e4SLinus Torvalds /*====================================================================*/
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds /* Parameters that can be set with 'insmod' */
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds /* SCSI bus setup options */
641da177e4SLinus Torvalds static int host_id = 7;
651da177e4SLinus Torvalds static int reconnect = 1;
661da177e4SLinus Torvalds static int parity = 1;
671da177e4SLinus Torvalds static int synchronous = 1;
681da177e4SLinus Torvalds static int reset_delay = 100;
691da177e4SLinus Torvalds static int ext_trans = 0;
701da177e4SLinus Torvalds
711da177e4SLinus Torvalds module_param(host_id, int, 0);
721da177e4SLinus Torvalds module_param(reconnect, int, 0);
731da177e4SLinus Torvalds module_param(parity, int, 0);
741da177e4SLinus Torvalds module_param(synchronous, int, 0);
751da177e4SLinus Torvalds module_param(reset_delay, int, 0);
761da177e4SLinus Torvalds module_param(ext_trans, int, 0);
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds MODULE_LICENSE("Dual MPL/GPL");
791da177e4SLinus Torvalds
801da177e4SLinus Torvalds /*====================================================================*/
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds typedef struct scsi_info_t {
83fd238232SDominik Brodowski struct pcmcia_device *p_dev;
841da177e4SLinus Torvalds struct Scsi_Host *host;
851da177e4SLinus Torvalds } scsi_info_t;
861da177e4SLinus Torvalds
87fba395eeSDominik Brodowski static void aha152x_release_cs(struct pcmcia_device *link);
88cc3b4866SDominik Brodowski static void aha152x_detach(struct pcmcia_device *p_dev);
8915b99ac1SDominik Brodowski static int aha152x_config_cs(struct pcmcia_device *link);
901da177e4SLinus Torvalds
aha152x_probe(struct pcmcia_device * link)9115b99ac1SDominik Brodowski static int aha152x_probe(struct pcmcia_device *link)
921da177e4SLinus Torvalds {
931da177e4SLinus Torvalds scsi_info_t *info;
941da177e4SLinus Torvalds
953e716617SDominik Brodowski dev_dbg(&link->dev, "aha152x_attach()\n");
961da177e4SLinus Torvalds
971da177e4SLinus Torvalds /* Create new SCSI device */
98dd00cc48SYoann Padioleau info = kzalloc(sizeof(*info), GFP_KERNEL);
99f8cfa618SDominik Brodowski if (!info) return -ENOMEM;
100fba395eeSDominik Brodowski info->p_dev = link;
101fd238232SDominik Brodowski link->priv = info;
1021da177e4SLinus Torvalds
10300990e7cSDominik Brodowski link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
1047feabb64SDominik Brodowski link->config_regs = PRESENT_OPTION;
1051da177e4SLinus Torvalds
10615b99ac1SDominik Brodowski return aha152x_config_cs(link);
1071da177e4SLinus Torvalds } /* aha152x_attach */
1081da177e4SLinus Torvalds
1091da177e4SLinus Torvalds /*====================================================================*/
1101da177e4SLinus Torvalds
aha152x_detach(struct pcmcia_device * link)111fba395eeSDominik Brodowski static void aha152x_detach(struct pcmcia_device *link)
1121da177e4SLinus Torvalds {
1133e716617SDominik Brodowski dev_dbg(&link->dev, "aha152x_detach\n");
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds aha152x_release_cs(link);
1161da177e4SLinus Torvalds
1171da177e4SLinus Torvalds /* Unlink device structure, free bits */
1181da177e4SLinus Torvalds kfree(link->priv);
1191da177e4SLinus Torvalds } /* aha152x_detach */
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds /*====================================================================*/
1221da177e4SLinus Torvalds
aha152x_config_check(struct pcmcia_device * p_dev,void * priv_data)12300990e7cSDominik Brodowski static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
1240e6f9d27SDominik Brodowski {
12590abdc3bSDominik Brodowski p_dev->io_lines = 10;
12600990e7cSDominik Brodowski
1270e6f9d27SDominik Brodowski /* For New Media T&J, look for a SCSI window */
12800990e7cSDominik Brodowski if ((p_dev->resource[0]->end < 0x20) &&
12900990e7cSDominik Brodowski (p_dev->resource[1]->end >= 0x20))
13000990e7cSDominik Brodowski p_dev->resource[0]->start = p_dev->resource[1]->start;
13100990e7cSDominik Brodowski
13200990e7cSDominik Brodowski if (p_dev->resource[0]->start >= 0xffff)
1330e6f9d27SDominik Brodowski return -EINVAL;
13400990e7cSDominik Brodowski
13500990e7cSDominik Brodowski p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
13600990e7cSDominik Brodowski p_dev->resource[0]->end = 0x20;
13700990e7cSDominik Brodowski p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
13800990e7cSDominik Brodowski p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
13900990e7cSDominik Brodowski
14000990e7cSDominik Brodowski return pcmcia_request_io(p_dev);
1410e6f9d27SDominik Brodowski }
1420e6f9d27SDominik Brodowski
aha152x_config_cs(struct pcmcia_device * link)14315b99ac1SDominik Brodowski static int aha152x_config_cs(struct pcmcia_device *link)
1441da177e4SLinus Torvalds {
1451da177e4SLinus Torvalds scsi_info_t *info = link->priv;
1461da177e4SLinus Torvalds struct aha152x_setup s;
1473e716617SDominik Brodowski int ret;
1481da177e4SLinus Torvalds struct Scsi_Host *host;
1491da177e4SLinus Torvalds
1503e716617SDominik Brodowski dev_dbg(&link->dev, "aha152x_config\n");
1511da177e4SLinus Torvalds
1523e716617SDominik Brodowski ret = pcmcia_loop_config(link, aha152x_config_check, NULL);
1533e716617SDominik Brodowski if (ret)
1540e6f9d27SDominik Brodowski goto failed;
1551da177e4SLinus Torvalds
156eb14120fSDominik Brodowski if (!link->irq)
1573e716617SDominik Brodowski goto failed;
1583e716617SDominik Brodowski
1591ac71e5aSDominik Brodowski ret = pcmcia_enable_device(link);
1603e716617SDominik Brodowski if (ret)
1613e716617SDominik Brodowski goto failed;
1621da177e4SLinus Torvalds
1631da177e4SLinus Torvalds /* Set configuration options for the aha152x driver */
1641da177e4SLinus Torvalds memset(&s, 0, sizeof(s));
1651da177e4SLinus Torvalds s.conf = "PCMCIA setup";
1669a017a91SDominik Brodowski s.io_port = link->resource[0]->start;
167eb14120fSDominik Brodowski s.irq = link->irq;
1681da177e4SLinus Torvalds s.scsiid = host_id;
1691da177e4SLinus Torvalds s.reconnect = reconnect;
1701da177e4SLinus Torvalds s.parity = parity;
1711da177e4SLinus Torvalds s.synchronous = synchronous;
1721da177e4SLinus Torvalds s.delay = reset_delay;
1731da177e4SLinus Torvalds if (ext_trans)
1741da177e4SLinus Torvalds s.ext_trans = ext_trans;
1751da177e4SLinus Torvalds
1761da177e4SLinus Torvalds host = aha152x_probe_one(&s);
1771da177e4SLinus Torvalds if (host == NULL) {
1781da177e4SLinus Torvalds printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
1793e716617SDominik Brodowski goto failed;
1801da177e4SLinus Torvalds }
1811da177e4SLinus Torvalds
1821da177e4SLinus Torvalds info->host = host;
1831da177e4SLinus Torvalds
18415b99ac1SDominik Brodowski return 0;
1851da177e4SLinus Torvalds
1860e6f9d27SDominik Brodowski failed:
1871da177e4SLinus Torvalds aha152x_release_cs(link);
18815b99ac1SDominik Brodowski return -ENODEV;
1891da177e4SLinus Torvalds }
1901da177e4SLinus Torvalds
aha152x_release_cs(struct pcmcia_device * link)191fba395eeSDominik Brodowski static void aha152x_release_cs(struct pcmcia_device *link)
1921da177e4SLinus Torvalds {
1931da177e4SLinus Torvalds scsi_info_t *info = link->priv;
1941da177e4SLinus Torvalds
1951da177e4SLinus Torvalds aha152x_release(info->host);
196fba395eeSDominik Brodowski pcmcia_disable_device(link);
1971da177e4SLinus Torvalds }
1981da177e4SLinus Torvalds
aha152x_resume(struct pcmcia_device * link)199fba395eeSDominik Brodowski static int aha152x_resume(struct pcmcia_device *link)
20098e4c28bSDominik Brodowski {
20198e4c28bSDominik Brodowski scsi_info_t *info = link->priv;
20298e4c28bSDominik Brodowski
203e2482fa1SJürgen E. Fischer aha152x_host_reset_host(info->host);
20498e4c28bSDominik Brodowski
20598e4c28bSDominik Brodowski return 0;
20698e4c28bSDominik Brodowski }
20798e4c28bSDominik Brodowski
20825f8f54fSJoe Perches static const struct pcmcia_device_id aha152x_ids[] = {
2092dc27daaSDominik Brodowski PCMCIA_DEVICE_PROD_ID123("New Media", "SCSI", "Bus Toaster", 0xcdf7e4cc, 0x35f26476, 0xa8851d6e),
2102dc27daaSDominik Brodowski PCMCIA_DEVICE_PROD_ID123("NOTEWORTHY", "SCSI", "Bus Toaster", 0xad89c6e8, 0x35f26476, 0xa8851d6e),
2112dc27daaSDominik Brodowski PCMCIA_DEVICE_PROD_ID12("Adaptec, Inc.", "APA-1460 SCSI Host Adapter", 0x24ba9738, 0x3a3c3d20),
2122dc27daaSDominik Brodowski PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Multimedia Sound/SCSI", 0x085a850b, 0x80a6535c),
2132dc27daaSDominik Brodowski PCMCIA_DEVICE_PROD_ID12("NOTEWORTHY", "NWCOMB02 SCSI/AUDIO COMBO CARD", 0xad89c6e8, 0x5f9a615b),
2142dc27daaSDominik Brodowski PCMCIA_DEVICE_NULL,
2152dc27daaSDominik Brodowski };
2162dc27daaSDominik Brodowski MODULE_DEVICE_TABLE(pcmcia, aha152x_ids);
2172dc27daaSDominik Brodowski
2181da177e4SLinus Torvalds static struct pcmcia_driver aha152x_cs_driver = {
2191da177e4SLinus Torvalds .owner = THIS_MODULE,
2201da177e4SLinus Torvalds .name = "aha152x_cs",
22115b99ac1SDominik Brodowski .probe = aha152x_probe,
222cc3b4866SDominik Brodowski .remove = aha152x_detach,
2232dc27daaSDominik Brodowski .id_table = aha152x_ids,
22498e4c28bSDominik Brodowski .resume = aha152x_resume,
2251da177e4SLinus Torvalds };
226dc245cfaSVaishali Thakkar module_pcmcia_driver(aha152x_cs_driver);
227