Blame view

drivers/scsi/sim710.c 5.86 KB
74ba9207e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
  /*
   * sim710.c - Copyright (C) 1999 Richard Hirst <richard@sleepie.demon.co.uk>
   *
   *----------------------------------------------------------------------------
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
   *----------------------------------------------------------------------------
   *
a88dc06cd   Paul Gortmaker   scsi: delete the ...
8
   * MCA card detection code by Trent McNair. (now deleted)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
   * Fixes to not explicitly nul bss data from Xavier Bestel.
   * Some multiboard fixes from Rolf Eike Beer.
   * Auto probing of EISA config space from Trevor Hemsley.
   *
   * Rewritten to use 53c700.c by James.Bottomley@SteelEye.com
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
  
  #include <linux/blkdev.h>
  #include <linux/device.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
27
28
  #include <linux/eisa.h>
  #include <linux/interrupt.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_transport.h>
  #include <scsi/scsi_transport_spi.h>
  
  #include "53c700.h"
a88dc06cd   Paul Gortmaker   scsi: delete the ...
29
  /* Must be enough for EISA */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  #define MAX_SLOTS 8
  static __u8 __initdata id_array[MAX_SLOTS] = { [0 ... MAX_SLOTS-1] = 7 };
  
  static char *sim710;		/* command line passed by insmod */
  
  MODULE_AUTHOR("Richard Hirst");
  MODULE_DESCRIPTION("Simple NCR53C710 driver");
  MODULE_LICENSE("GPL");
  
  module_param(sim710, charp, 0);
  
  #ifdef MODULE
  #define ARG_SEP ' '
  #else
  #define ARG_SEP ','
  #endif
  
  static __init int
  param_setup(char *str)
  {
  	char *pos = str, *next;
  	int slot = -1;
  
  	while(pos != NULL && (next = strchr(pos, ':')) != NULL) {
  		int val = (int)simple_strtoul(++next, NULL, 0);
  
  		if(!strncmp(pos, "slot:", 5))
  			slot = val;
  		else if(!strncmp(pos, "id:", 3)) {
  			if(slot == -1) {
  				printk(KERN_WARNING "sim710: Must specify slot for id parameter
  ");
1a34456bb   Eric Sesterhenn   [SCSI] Overrun in...
62
  			} else if(slot >= MAX_SLOTS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  				printk(KERN_WARNING "sim710: Illegal slot %d for id %d
  ", slot, val);
  			} else {
  				id_array[slot] = val;
  			}
  		}
  		if((pos = strchr(pos, ARG_SEP)) != NULL)
  			pos++;
  	}
  	return 1;
  }
  __setup("sim710=", param_setup);
  
  static struct scsi_host_template sim710_driver_template = {
a88dc06cd   Paul Gortmaker   scsi: delete the ...
77
  	.name			= "LSI (Symbios) 710 EISA",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
  	.proc_name		= "sim710",
  	.this_id		= 7,
  	.module			= THIS_MODULE,
  };
6f0397905   Greg Kroah-Hartman   Drivers: scsi: re...
82
83
84
  static int sim710_probe_common(struct device *dev, unsigned long base_addr,
  			       int irq, int clock, int differential,
  			       int scsi_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
  {
  	struct Scsi_Host * host = NULL;
  	struct NCR_700_Host_Parameters *hostdata =
dd00cc486   Yoann Padioleau   some kmalloc/mems...
88
  		kzalloc(sizeof(struct NCR_700_Host_Parameters),	GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89

71610f55f   Kay Sievers   [SCSI] struct dev...
90
91
  	printk(KERN_NOTICE "sim710: %s
  ", dev_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
98
99
100
  	printk(KERN_NOTICE "sim710: irq = %d, clock = %d, base = 0x%lx, scsi_id = %d
  ",
  	       irq, clock, base_addr, scsi_id);
  
  	if(hostdata == NULL) {
  		printk(KERN_ERR "sim710: Failed to allocate host data
  ");
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
105
106
107
108
109
  
  	if(request_region(base_addr, 64, "sim710") == NULL) {
  		printk(KERN_ERR "sim710: Failed to reserve IO region 0x%lx
  ",
  		       base_addr);
  		goto out_free;
  	}
  
  	/* Fill in the three required pieces of hostdata */
56fece200   James Bottomley   [PATCH] finally f...
110
  	hostdata->base = ioport_map(base_addr, 64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
  	hostdata->differential = differential;
  	hostdata->clock = clock;
  	hostdata->chip710 = 1;
f67a9c159   Thomas Bogendoerfer   [SCSI] 53c700: Al...
114
  	hostdata->burst_length = 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
120
121
122
123
  
  	/* and register the chip */
  	if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev))
  	   == NULL) {
  		printk(KERN_ERR "sim710: No host detected; card configuration problem?
  ");
  		goto out_release;
  	}
  	host->this_id = scsi_id;
56fece200   James Bottomley   [PATCH] finally f...
124
  	host->base = base_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  	host->irq = irq;
1d6f359a2   Thomas Gleixner   [PATCH] irq-flags...
126
  	if (request_irq(irq, NCR_700_intr, IRQF_SHARED, "sim710", host)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
  		printk(KERN_ERR "sim710: request_irq failed
  ");
  		goto out_put_host;
  	}
3ac709c11   Matthew Wilcox   [SCSI] a4000t, zo...
131
  	dev_set_drvdata(dev, host);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
138
  	scsi_scan_host(host);
  
  	return 0;
  
   out_put_host:
  	scsi_host_put(host);
   out_release:
a1d4f73a0   Adrian Bunk   [SCSI] sim710: fi...
139
  	release_region(base_addr, 64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
   out_free:
  	kfree(hostdata);
   out:
  	return -ENODEV;
  }
6f0397905   Greg Kroah-Hartman   Drivers: scsi: re...
145
  static int sim710_device_remove(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  {
3ac709c11   Matthew Wilcox   [SCSI] a4000t, zo...
147
  	struct Scsi_Host *host = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
153
154
  	struct NCR_700_Host_Parameters *hostdata =
  		(struct NCR_700_Host_Parameters *)host->hostdata[0];
  
  	scsi_remove_host(host);
  	NCR_700_release(host);
  	kfree(hostdata);
  	free_irq(host->irq, host);
56fece200   James Bottomley   [PATCH] finally f...
155
  	release_region(host->base, 64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
163
164
  #ifdef CONFIG_EISA
  static struct eisa_device_id sim710_eisa_ids[] = {
  	{ "CPQ4410" },
  	{ "CPQ4411" },
  	{ "HWP0C80" },
  	{ "" }
  };
07563c711   Michael Tokarev   [PATCH] EISA bus ...
165
  MODULE_DEVICE_TABLE(eisa, sim710_eisa_ids);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166

648a0a7da   Sudip Mukherjee   scsi: sim710: fix...
167
  static int sim710_eisa_probe(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  {
  	struct eisa_device *edev = to_eisa_device(dev);
  	unsigned long io_addr = edev->base_addr;
  	char eisa_cpq_irqs[] = { 11, 14, 15, 10, 9, 0 };
  	char eisa_hwp_irqs[] = { 3, 4, 5, 7, 12, 10, 11, 0};
  	char *eisa_irqs;
  	unsigned char irq_index;
  	unsigned char irq, differential = 0, scsi_id = 7;
  
  	if(strcmp(edev->id.sig, "HWP0C80") == 0) {
  		__u8 val;
  		eisa_irqs =  eisa_hwp_irqs;
  		irq_index = (inb(io_addr + 0xc85) & 0x7) - 1;
  
  		val = inb(io_addr + 0x4);
  		scsi_id = ffs(val) - 1;
  
  		if(scsi_id > 7 || (val & ~(1<<scsi_id)) != 0) {
71610f55f   Kay Sievers   [SCSI] struct dev...
186
187
  			printk(KERN_ERR "sim710.c, EISA card %s has incorrect scsi_id, setting to 7
  ", dev_name(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  			scsi_id = 7;
  		}
  	} else {
  		eisa_irqs = eisa_cpq_irqs;
  		irq_index = inb(io_addr + 0xc88) & 0x07;
  	}
  
  	if(irq_index >= strlen(eisa_irqs)) {
  		printk("sim710.c: irq nasty
  ");
  		return -ENODEV;
  	}
  
  	irq = eisa_irqs[irq_index];
  		
  	return sim710_probe_common(dev, io_addr, irq, 50,
  				   differential, scsi_id);
  }
  
  static struct eisa_driver sim710_eisa_driver = {
  	.id_table		= sim710_eisa_ids,
  	.driver = {
  		.name		= "sim710",
  		.probe		= sim710_eisa_probe,
6f0397905   Greg Kroah-Hartman   Drivers: scsi: re...
212
  		.remove		= sim710_device_remove,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
217
218
219
220
221
222
223
224
  	},
  };
  #endif /* CONFIG_EISA */
  
  static int __init sim710_init(void)
  {
  	int err = -ENODEV;
  
  #ifdef MODULE
  	if (sim710)
  		param_setup(sim710);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
232
233
234
235
236
237
  #ifdef CONFIG_EISA
  	err = eisa_driver_register(&sim710_eisa_driver);
  #endif
  	/* FIXME: what we'd really like to return here is -ENODEV if
  	 * no devices have actually been found.  Instead, the err
  	 * above actually only reports problems with kobject_register,
  	 * so for the moment return success */
  
  	return 0;
  }
  
  static void __exit sim710_exit(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
244
  #ifdef CONFIG_EISA
  	eisa_driver_unregister(&sim710_eisa_driver);
  #endif
  }
  
  module_init(sim710_init);
  module_exit(sim710_exit);