1 | // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) |
2 | /* |
3 | * Driver for Future Domain-compatible PCMCIA SCSI cards |
4 | * Copyright 2019 Ondrej Zary |
5 | * |
6 | * The initial developer of the original code is David A. Hinds |
7 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds |
8 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
9 | */ |
10 | |
11 | #include <linux/module.h> |
12 | #include <linux/init.h> |
13 | #include <scsi/scsi_host.h> |
14 | #include <pcmcia/cistpl.h> |
15 | #include <pcmcia/ds.h> |
16 | #include "fdomain.h" |
17 | |
18 | MODULE_AUTHOR("Ondrej Zary, David Hinds" ); |
19 | MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver" ); |
20 | MODULE_LICENSE("Dual MPL/GPL" ); |
21 | |
22 | static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data) |
23 | { |
24 | p_dev->io_lines = 10; |
25 | p_dev->resource[0]->end = FDOMAIN_REGION_SIZE; |
26 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
27 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
28 | return pcmcia_request_io(p_dev); |
29 | } |
30 | |
31 | static int fdomain_probe(struct pcmcia_device *link) |
32 | { |
33 | int ret; |
34 | struct Scsi_Host *sh; |
35 | |
36 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
37 | link->config_regs = PRESENT_OPTION; |
38 | |
39 | ret = pcmcia_loop_config(p_dev: link, conf_check: fdomain_config_check, NULL); |
40 | if (ret) |
41 | return ret; |
42 | |
43 | ret = pcmcia_enable_device(p_dev: link); |
44 | if (ret) |
45 | goto fail_disable; |
46 | |
47 | if (!request_region(link->resource[0]->start, FDOMAIN_REGION_SIZE, |
48 | "fdomain_cs" )) { |
49 | ret = -EBUSY; |
50 | goto fail_disable; |
51 | } |
52 | |
53 | sh = fdomain_create(link->resource[0]->start, link->irq, 7, &link->dev); |
54 | if (!sh) { |
55 | dev_err(&link->dev, "Controller initialization failed" ); |
56 | ret = -ENODEV; |
57 | goto fail_release; |
58 | } |
59 | |
60 | link->priv = sh; |
61 | |
62 | return 0; |
63 | |
64 | fail_release: |
65 | release_region(link->resource[0]->start, FDOMAIN_REGION_SIZE); |
66 | fail_disable: |
67 | pcmcia_disable_device(p_dev: link); |
68 | return ret; |
69 | } |
70 | |
71 | static void fdomain_remove(struct pcmcia_device *link) |
72 | { |
73 | fdomain_destroy(link->priv); |
74 | release_region(link->resource[0]->start, FDOMAIN_REGION_SIZE); |
75 | pcmcia_disable_device(p_dev: link); |
76 | } |
77 | |
78 | static const struct pcmcia_device_id fdomain_ids[] = { |
79 | PCMCIA_DEVICE_PROD_ID12("IBM Corp." , "SCSI PCMCIA Card" , 0xe3736c88, |
80 | 0x859cad20), |
81 | PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card" , 0x8dacb57e), |
82 | PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation" , |
83 | "SCSI PCMCIA Credit Card Controller" , |
84 | 0x182bdafe, 0xc80d106f), |
85 | PCMCIA_DEVICE_NULL, |
86 | }; |
87 | MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); |
88 | |
89 | static struct pcmcia_driver fdomain_cs_driver = { |
90 | .owner = THIS_MODULE, |
91 | .name = "fdomain_cs" , |
92 | .probe = fdomain_probe, |
93 | .remove = fdomain_remove, |
94 | .id_table = fdomain_ids, |
95 | }; |
96 | |
97 | module_pcmcia_driver(fdomain_cs_driver); |
98 | |