Blame view

drivers/scsi/g_NCR5380.c 21.2 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  /*
   * Generic Generic NCR5380 driver
24c43341a   Finn Thain   scsi: g_NCR5380: ...
4
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   * Copyright 1993, Drew Eckhardt
24c43341a   Finn Thain   scsi: g_NCR5380: ...
6
7
8
9
   * Visionary Computing
   * (Unix and Linux consulting and custom programming)
   * drew@colorado.edu
   * +1 (303) 440-4894
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
   *
   * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
24c43341a   Finn Thain   scsi: g_NCR5380: ...
12
   * K.Lentin@cs.monash.edu.au
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
   *
   * NCR53C400A extensions (c) 1996, Ingmar Baumgart
24c43341a   Finn Thain   scsi: g_NCR5380: ...
15
   * ingmar@gonzo.schwaben.de
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
   *
   * DTC3181E extensions (c) 1997, Ronald van Cuijlenborg
   * ronald.van.cuijlenborg@tip.nl or nutty@dds.nl
   *
   * Added ISAPNP support for DTC436 adapters,
   * Thomas Sailer, sailer@ife.ee.ethz.ch
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
   *
9c41ab27e   Finn Thain   ncr5380: Update u...
23
   * See Documentation/scsi/g_NCR5380.txt for more info.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <linux/blkdev.h>
161c0059a   Finn Thain   ncr5380: Cleanup ...
27
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <scsi/scsi_host.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
  #include <linux/init.h>
  #include <linux/ioport.h>
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
31
32
  #include <linux/isa.h>
  #include <linux/pnp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include <linux/interrupt.h>
14d739f64   Finn Thain   scsi: ncr5380: Re...
34
35
36
37
38
39
40
41
42
43
44
45
  /* Definitions for the core NCR5380 driver. */
  
  #define NCR5380_read(reg) \
  	ioread8(hostdata->io + hostdata->offset + (reg))
  #define NCR5380_write(reg, value) \
  	iowrite8(value, hostdata->io + hostdata->offset + (reg))
  
  #define NCR5380_implementation_fields \
  	int offset; \
  	int c400_ctl_status; \
  	int c400_blk_cnt; \
  	int c400_host_buf; \
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
46
  	int io_width; \
facfc963a   Ondrej Zary   scsi: g_NCR5380: ...
47
48
  	int pdma_residual; \
  	int board
14d739f64   Finn Thain   scsi: ncr5380: Re...
49
50
  
  #define NCR5380_dma_xfer_len            generic_NCR5380_dma_xfer_len
ab2ace2df   Finn Thain   scsi: g_NCR5380: ...
51
52
  #define NCR5380_dma_recv_setup          generic_NCR5380_precv
  #define NCR5380_dma_send_setup          generic_NCR5380_psend
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
53
  #define NCR5380_dma_residual            generic_NCR5380_dma_residual
14d739f64   Finn Thain   scsi: ncr5380: Re...
54
55
56
57
  
  #define NCR5380_intr                    generic_NCR5380_intr
  #define NCR5380_queue_command           generic_NCR5380_queue_command
  #define NCR5380_abort                   generic_NCR5380_abort
12e5fc665   Hannes Reinecke   scsi: NCR5380: Mo...
58
  #define NCR5380_host_reset              generic_NCR5380_host_reset
14d739f64   Finn Thain   scsi: ncr5380: Re...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  #define NCR5380_info                    generic_NCR5380_info
  
  #define NCR5380_io_delay(x)             udelay(x)
  
  #include "NCR5380.h"
  
  #define DRV_MODULE_NAME "g_NCR5380"
  
  #define NCR53C400_mem_base 0x3880
  #define NCR53C400_host_buffer 0x3900
  #define NCR53C400_region_size 0x3a00
  
  #define BOARD_NCR5380 0
  #define BOARD_NCR53C400 1
  #define BOARD_NCR53C400A 2
  #define BOARD_DTC3181E 3
  #define BOARD_HP_C2502 4
  
  #define IRQ_AUTO 254
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
78
  #define MAX_CARDS 8
12b859b70   Ondrej Zary   scsi: g_NCR5380: ...
79
  #define DMA_MAX_SIZE 32768
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
80
81
  
  /* old-style parameters for compatibility */
70439e933   Finn Thain   scsi: g_NCR5380: ...
82
  static int ncr_irq = -1;
c0965e637   Finn Thain   ncr5380: Remove m...
83
84
85
86
87
  static int ncr_addr;
  static int ncr_5380;
  static int ncr_53c400;
  static int ncr_53c400a;
  static int dtc_3181e;
c6084cbce   Ondrej Zary   ncr5380: Add supp...
88
  static int hp_c2502;
88f06b76e   David Howells   Annotate hardware...
89
90
  module_param_hw(ncr_irq, int, irq, 0);
  module_param_hw(ncr_addr, int, ioport, 0);
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
91
92
93
94
95
  module_param(ncr_5380, int, 0);
  module_param(ncr_53c400, int, 0);
  module_param(ncr_53c400a, int, 0);
  module_param(dtc_3181e, int, 0);
  module_param(hp_c2502, int, 0);
70439e933   Finn Thain   scsi: g_NCR5380: ...
96
  static int irq[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
88f06b76e   David Howells   Annotate hardware...
97
  module_param_hw_array(irq, int, irq, NULL, 0);
70439e933   Finn Thain   scsi: g_NCR5380: ...
98
  MODULE_PARM_DESC(irq, "IRQ number(s) (0=none, 254=auto [default])");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
100
  static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
88f06b76e   David Howells   Annotate hardware...
101
  module_param_hw_array(base, int, ioport, NULL, 0);
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
102
103
104
105
106
  MODULE_PARM_DESC(base, "base address(es)");
  
  static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  module_param_array(card, int, NULL, 0);
  MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)");
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
107
  MODULE_ALIAS("g_NCR5380_mmio");
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
108
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109

906e4a3c7   Ondrej Zary   scsi: g_NCR5380: ...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  static void g_NCR5380_trigger_irq(struct Scsi_Host *instance)
  {
  	struct NCR5380_hostdata *hostdata = shost_priv(instance);
  
  	/*
  	 * An interrupt is triggered whenever BSY = false, SEL = true
  	 * and a bit set in the SELECT_ENABLE_REG is asserted on the
  	 * SCSI bus.
  	 *
  	 * Note that the bus is only driven when the phase control signals
  	 * (I/O, C/D, and MSG) match those in the TCR.
  	 */
  	NCR5380_write(TARGET_COMMAND_REG,
  	              PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
  	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
  	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
  	NCR5380_write(INITIATOR_COMMAND_REG,
  	              ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
  
  	msleep(1);
  
  	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
  	NCR5380_write(SELECT_ENABLE_REG, 0);
  	NCR5380_write(TARGET_COMMAND_REG, 0);
  }
  
  /**
   * g_NCR5380_probe_irq - find the IRQ of a NCR5380 or equivalent
   * @instance: SCSI host instance
   *
   * Autoprobe for the IRQ line used by the card by triggering an IRQ
   * and then looking to see what interrupt actually turned up.
   */
  
  static int g_NCR5380_probe_irq(struct Scsi_Host *instance)
  {
  	struct NCR5380_hostdata *hostdata = shost_priv(instance);
  	int irq_mask, irq;
  
  	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
  	irq_mask = probe_irq_on();
  	g_NCR5380_trigger_irq(instance);
  	irq = probe_irq_off(irq_mask);
  	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
  
  	if (irq <= 0)
  		return NO_IRQ;
  	return irq;
  }
c6084cbce   Ondrej Zary   ncr5380: Add supp...
159
160
161
162
163
164
165
166
167
168
169
170
171
  /*
   * Configure I/O address of 53C400A or DTC436 by writing magic numbers
   * to ports 0x779 and 0x379.
   */
  static void magic_configure(int idx, u8 irq, u8 magic[])
  {
  	u8 cfg = 0;
  
  	outb(magic[0], 0x779);
  	outb(magic[1], 0x379);
  	outb(magic[2], 0x379);
  	outb(magic[3], 0x379);
  	outb(magic[4], 0x379);
145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
172
173
  	if (irq == 9)
  		irq = 2;
c6084cbce   Ondrej Zary   ncr5380: Add supp...
174
175
176
177
  	if (idx >= 0 && idx <= 7)
  		cfg = 0x80 | idx | (irq << 4);
  	outb(cfg, 0x379);
  }
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
178

145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  static irqreturn_t legacy_empty_irq_handler(int irq, void *dev_id)
  {
  	return IRQ_HANDLED;
  }
  
  static int legacy_find_free_irq(int *irq_table)
  {
  	while (*irq_table != -1) {
  		if (!request_irq(*irq_table, legacy_empty_irq_handler,
  		                 IRQF_PROBE_SHARED, "Test IRQ",
  		                 (void *)irq_table)) {
  			free_irq(*irq_table, (void *) irq_table);
  			return *irq_table;
  		}
  		irq_table++;
  	}
  	return -1;
  }
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
197
198
199
200
201
202
203
204
205
206
207
208
  static unsigned int ncr_53c400a_ports[] = {
  	0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
  };
  static unsigned int dtc_3181e_ports[] = {
  	0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
  };
  static u8 ncr_53c400a_magic[] = {	/* 53C400A & DTC436 */
  	0x59, 0xb9, 0xc5, 0xae, 0xa6
  };
  static u8 hp_c2502_magic[] = {	/* HP C2502 */
  	0x0f, 0x22, 0xf0, 0x20, 0x80
  };
145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
209
210
211
  static int hp_c2502_irqs[] = {
  	9, 5, 7, 3, 4, -1
  };
c6084cbce   Ondrej Zary   ncr5380: Add supp...
212

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
213
214
  static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
  			struct device *pdev, int base, int irq, int board)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  {
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
216
217
218
219
  	bool is_pmio = base <= 0xffff;
  	int ret;
  	int flags = 0;
  	unsigned int *ports = NULL;
c6084cbce   Ondrej Zary   ncr5380: Add supp...
220
  	u8 *magic = NULL;
702a98c63   Ondrej Zary   g_NCR5380: fix br...
221
  	int i;
c6084cbce   Ondrej Zary   ncr5380: Add supp...
222
  	int port_idx = -1;
9d376402c   Finn Thain   g_ncr5380: Remove...
223
  	unsigned long region_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  	struct Scsi_Host *instance;
12150797d   Ondrej Zary   ncr5380: Use runt...
225
  	struct NCR5380_hostdata *hostdata;
820682b1b   Finn Thain   scsi: ncr5380: St...
226
  	u8 __iomem *iomem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
228
  	switch (board) {
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  	case BOARD_NCR5380:
  		flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP;
  		break;
  	case BOARD_NCR53C400A:
  		ports = ncr_53c400a_ports;
  		magic = ncr_53c400a_magic;
  		break;
  	case BOARD_HP_C2502:
  		ports = ncr_53c400a_ports;
  		magic = hp_c2502_magic;
  		break;
  	case BOARD_DTC3181E:
  		ports = dtc_3181e_ports;
  		magic = ncr_53c400a_magic;
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245

b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
246
  	if (is_pmio && ports && magic) {
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
247
  		/* wakeup sequence for the NCR53C400A and DTC3181E */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248

d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
249
250
  		/* Disable the adapter and look for a free io port */
  		magic_configure(-1, 0, magic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251

d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
252
  		region_size = 16;
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
253
  		if (base)
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
254
  			for (i = 0; ports[i]; i++) {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
255
256
257
258
259
  				if (base == ports[i]) {	/* index found */
  					if (!request_region(ports[i],
  							    region_size,
  							    "ncr53c80"))
  						return -EBUSY;
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
260
  					break;
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
261
262
263
  				}
  			}
  		else
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
264
  			for (i = 0; ports[i]; i++) {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
265
266
  				if (!request_region(ports[i], region_size,
  						    "ncr53c80"))
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
267
268
269
270
271
272
273
274
  					continue;
  				if (inb(ports[i]) == 0xff)
  					break;
  				release_region(ports[i], region_size);
  			}
  		if (ports[i]) {
  			/* At this point we have our region reserved */
  			magic_configure(i, 0, magic); /* no IRQ yet */
7b93ca43b   Ondrej Zary   scsi: g_NCR5380: ...
275
276
277
  			base = ports[i];
  			outb(0xc0, base + 9);
  			if (inb(base + 9) != 0x80) {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
278
279
280
  				ret = -ENODEV;
  				goto out_release;
  			}
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
281
282
  			port_idx = i;
  		} else
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
283
  			return -EINVAL;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
284
  	} else if (is_pmio) {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
285
  		/* NCR5380 - no configuration, just grab */
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
286
  		region_size = 8;
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
287
288
  		if (!base || !request_region(base, region_size, "ncr5380"))
  			return -EBUSY;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
289
290
291
292
  	} else {	/* MMIO */
  		region_size = NCR53C400_region_size;
  		if (!request_mem_region(base, region_size, "ncr5380"))
  			return -EBUSY;
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
293
  	}
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
294
295
296
297
298
  
  	if (is_pmio)
  		iomem = ioport_map(base, region_size);
  	else
  		iomem = ioremap(base, region_size);
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
299
  	if (!iomem) {
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
300
301
  		ret = -ENOMEM;
  		goto out_release;
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
302
  	}
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
303

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
304
305
306
  	instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
  	if (instance == NULL) {
  		ret = -ENOMEM;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
307
  		goto out_unmap;
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
308
  	}
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
309
  	hostdata = shost_priv(instance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310

facfc963a   Ondrej Zary   scsi: g_NCR5380: ...
311
  	hostdata->board = board;
820682b1b   Finn Thain   scsi: ncr5380: St...
312
313
  	hostdata->io = iomem;
  	hostdata->region_size = region_size;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
314
315
  
  	if (is_pmio) {
820682b1b   Finn Thain   scsi: ncr5380: St...
316
  		hostdata->io_port = base;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
317
318
319
320
321
322
323
324
325
  		hostdata->io_width = 1; /* 8-bit PDMA by default */
  		hostdata->offset = 0;
  
  		/*
  		 * On NCR53C400 boards, NCR5380 registers are mapped 8 past
  		 * the base address.
  		 */
  		switch (board) {
  		case BOARD_NCR53C400:
820682b1b   Finn Thain   scsi: ncr5380: St...
326
  			hostdata->io_port += 8;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  			hostdata->c400_ctl_status = 0;
  			hostdata->c400_blk_cnt = 1;
  			hostdata->c400_host_buf = 4;
  			break;
  		case BOARD_DTC3181E:
  			hostdata->io_width = 2;	/* 16-bit PDMA */
  			/* fall through */
  		case BOARD_NCR53C400A:
  		case BOARD_HP_C2502:
  			hostdata->c400_ctl_status = 9;
  			hostdata->c400_blk_cnt = 10;
  			hostdata->c400_host_buf = 8;
  			break;
  		}
  	} else {
820682b1b   Finn Thain   scsi: ncr5380: St...
342
  		hostdata->base = base;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  		hostdata->offset = NCR53C400_mem_base;
  		switch (board) {
  		case BOARD_NCR53C400:
  			hostdata->c400_ctl_status = 0x100;
  			hostdata->c400_blk_cnt = 0x101;
  			hostdata->c400_host_buf = 0x104;
  			break;
  		case BOARD_DTC3181E:
  		case BOARD_NCR53C400A:
  		case BOARD_HP_C2502:
  			pr_err(DRV_MODULE_NAME ": unknown register offsets
  ");
  			ret = -EINVAL;
  			goto out_unregister;
  		}
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
358
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359

89fa9b5cb   Ondrej Zary   scsi: g_NCR5380: ...
360
361
362
363
364
365
  	/* Check for vacant slot */
  	NCR5380_write(MODE_REG, 0);
  	if (NCR5380_read(MODE_REG) != 0) {
  		ret = -ENODEV;
  		goto out_unregister;
  	}
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
366
367
  	ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP);
  	if (ret)
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
368
  		goto out_unregister;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
370
  	switch (board) {
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
371
372
373
374
375
376
  	case BOARD_NCR53C400:
  	case BOARD_DTC3181E:
  	case BOARD_NCR53C400A:
  	case BOARD_HP_C2502:
  		NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
  	}
4d8c08c71   Finn Thain   ncr5380: Move NCR...
377

d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
378
  	NCR5380_maybe_reset_bus(instance);
b6488f97d   Finn Thain   ncr5380: Split NC...
379

d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
380
  	/* Compatibility with documented NCR5380 kernel parameters */
145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
381
382
  	if (irq == 255 || irq == 0)
  		irq = NO_IRQ;
70439e933   Finn Thain   scsi: g_NCR5380: ...
383
384
  	else if (irq == -1)
  		irq = IRQ_AUTO;
145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  
  	if (board == BOARD_HP_C2502) {
  		int *irq_table = hp_c2502_irqs;
  		int board_irq = -1;
  
  		switch (irq) {
  		case NO_IRQ:
  			board_irq = 0;
  			break;
  		case IRQ_AUTO:
  			board_irq = legacy_find_free_irq(irq_table);
  			break;
  		default:
  			while (*irq_table != -1)
  				if (*irq_table++ == irq)
  					board_irq = irq;
  		}
  
  		if (board_irq <= 0) {
  			board_irq = 0;
  			irq = NO_IRQ;
  		}
  
  		magic_configure(port_idx, board_irq, magic);
  	}
70439e933   Finn Thain   scsi: g_NCR5380: ...
410
  	if (irq == IRQ_AUTO) {
145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
411
  		instance->irq = g_NCR5380_probe_irq(instance);
70439e933   Finn Thain   scsi: g_NCR5380: ...
412
413
414
415
  		if (instance->irq == NO_IRQ)
  			shost_printk(KERN_INFO, instance, "no irq detected
  ");
  	} else {
145c3ae4c   Finn Thain   scsi: g_NCR5380: ...
416
  		instance->irq = irq;
70439e933   Finn Thain   scsi: g_NCR5380: ...
417
418
419
420
  		if (instance->irq == NO_IRQ)
  			shost_printk(KERN_INFO, instance, "no irq provided
  ");
  	}
22f5f10d2   Finn Thain   ncr5380: Fix SCSI...
421

d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
422
  	if (instance->irq != NO_IRQ) {
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
423
424
  		if (request_irq(instance->irq, generic_NCR5380_intr,
  				0, "NCR5380", instance)) {
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
425
  			instance->irq = NO_IRQ;
70439e933   Finn Thain   scsi: g_NCR5380: ...
426
427
428
429
430
431
432
  			shost_printk(KERN_INFO, instance,
  			             "irq %d denied
  ", instance->irq);
  		} else {
  			shost_printk(KERN_INFO, instance,
  			             "irq %d acquired
  ", instance->irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  		}
d91f5afe5   Ondrej Zary   scsi: g_NCR5380: ...
434
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
436
437
438
439
440
441
  	ret = scsi_add_host(instance, pdev);
  	if (ret)
  		goto out_free_irq;
  	scsi_scan_host(instance);
  	dev_set_drvdata(pdev, instance);
  	return 0;
0ad0eff98   Finn Thain   ncr5380: Introduc...
442

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
443
444
445
446
  out_free_irq:
  	if (instance->irq != NO_IRQ)
  		free_irq(instance->irq, instance);
  	NCR5380_exit(instance);
0ad0eff98   Finn Thain   ncr5380: Introduc...
447
  out_unregister:
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
448
  	scsi_host_put(instance);
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
449
  out_unmap:
0ad0eff98   Finn Thain   ncr5380: Introduc...
450
  	iounmap(iomem);
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
451
452
453
454
455
  out_release:
  	if (is_pmio)
  		release_region(base, region_size);
  	else
  		release_mem_region(base, region_size);
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
456
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  }
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
458
  static void generic_NCR5380_release_resources(struct Scsi_Host *instance)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  {
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
460
  	struct NCR5380_hostdata *hostdata = shost_priv(instance);
820682b1b   Finn Thain   scsi: ncr5380: St...
461
462
463
464
  	void __iomem *iomem = hostdata->io;
  	unsigned long io_port = hostdata->io_port;
  	unsigned long base = hostdata->base;
  	unsigned long region_size = hostdata->region_size;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
465

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
466
  	scsi_remove_host(instance);
22f5f10d2   Finn Thain   ncr5380: Fix SCSI...
467
  	if (instance->irq != NO_IRQ)
1e6416643   Jeff Garzik   [SCSI] NCR5380: F...
468
  		free_irq(instance->irq, instance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	NCR5380_exit(instance);
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
470
  	scsi_host_put(instance);
820682b1b   Finn Thain   scsi: ncr5380: St...
471
472
473
474
475
  	iounmap(iomem);
  	if (io_port)
  		release_region(io_port, region_size);
  	else
  		release_mem_region(base, region_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
478
479
480
481
482
483
484
485
486
487
488
489
  /* wait_for_53c80_access - wait for 53C80 registers to become accessible
   * @hostdata: scsi host private data
   *
   * The registers within the 53C80 logic block are inaccessible until
   * bit 7 in the 53C400 control status register gets asserted.
   */
  
  static void wait_for_53c80_access(struct NCR5380_hostdata *hostdata)
  {
  	int count = 10000;
  
  	do {
facfc963a   Ondrej Zary   scsi: g_NCR5380: ...
490
491
  		if (hostdata->board == BOARD_DTC3181E)
  			udelay(4); /* DTC436 chip hangs without this */
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
492
493
494
495
496
497
498
499
500
501
  		if (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
  			return;
  	} while (--count > 0);
  
  	scmd_printk(KERN_ERR, hostdata->connected,
  	            "53c80 registers not accessible, device will be reset
  ");
  	NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
  	NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  /**
ab2ace2df   Finn Thain   scsi: g_NCR5380: ...
503
   * generic_NCR5380_precv - pseudo DMA receive
24c43341a   Finn Thain   scsi: g_NCR5380: ...
504
505
506
   * @hostdata: scsi host private data
   * @dst: buffer to write into
   * @len: transfer size
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
   *
24c43341a   Finn Thain   scsi: g_NCR5380: ...
508
   * Perform a pseudo DMA mode receive from a 53C400 or equivalent device.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
   */
24c43341a   Finn Thain   scsi: g_NCR5380: ...
510

ab2ace2df   Finn Thain   scsi: g_NCR5380: ...
511
  static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
6c4b88ca5   Finn Thain   ncr5380: Use DMA ...
512
                                          unsigned char *dst, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  {
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
514
  	int residual;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  	int start = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516

12150797d   Ondrej Zary   ncr5380: Use runt...
517
  	NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  	NCR5380_write(hostdata->c400_blk_cnt, len / 128);
  
  	do {
  		if (start == len - 128) {
  			/* Ignore End of DMA interrupt for the final buffer */
  			if (NCR5380_poll_politely(hostdata, hostdata->c400_ctl_status,
  			                          CSR_HOST_BUF_NOT_RDY, 0, HZ / 64) < 0)
  				break;
  		} else {
  			if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
  			                           CSR_HOST_BUF_NOT_RDY, 0,
  			                           hostdata->c400_ctl_status,
  			                           CSR_GATED_53C80_IRQ,
  			                           CSR_GATED_53C80_IRQ, HZ / 64) < 0 ||
  			    NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
  				break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535

820682b1b   Finn Thain   scsi: ncr5380: St...
536
537
  		if (hostdata->io_port && hostdata->io_width == 2)
  			insw(hostdata->io_port + hostdata->c400_host_buf,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
538
  			     dst + start, 64);
820682b1b   Finn Thain   scsi: ncr5380: St...
539
540
  		else if (hostdata->io_port)
  			insb(hostdata->io_port + hostdata->c400_host_buf,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
541
  			     dst + start, 128);
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
542
543
  		else
  			memcpy_fromio(dst + start,
820682b1b   Finn Thain   scsi: ncr5380: St...
544
  				hostdata->io + NCR53C400_host_buffer, 128);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  		start += 128;
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
546
  	} while (start < len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
548
  	residual = len - start;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
549

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
550
551
552
553
  	if (residual != 0) {
  		/* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */
  		NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
  		NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  	}
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
555
  	wait_for_53c80_access(hostdata);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
557
558
559
560
561
562
563
  	if (residual == 0 && NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
  	                                           BASR_END_DMA_TRANSFER,
  	                                           BASR_END_DMA_TRANSFER,
  	                                           HZ / 64) < 0)
  		scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout
  ",
  		            __func__);
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
564

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
565
  	hostdata->pdma_residual = residual;
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
566

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
  	return 0;
  }
  
  /**
ab2ace2df   Finn Thain   scsi: g_NCR5380: ...
571
   * generic_NCR5380_psend - pseudo DMA send
24c43341a   Finn Thain   scsi: g_NCR5380: ...
572
573
574
   * @hostdata: scsi host private data
   * @src: buffer to read from
   * @len: transfer size
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
   *
24c43341a   Finn Thain   scsi: g_NCR5380: ...
576
   * Perform a pseudo DMA mode send to a 53C400 or equivalent device.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
   */
ab2ace2df   Finn Thain   scsi: g_NCR5380: ...
578
579
  static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata,
                                          unsigned char *src, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
581
  	int residual;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  	int start = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583

12150797d   Ondrej Zary   ncr5380: Use runt...
584
  	NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  	NCR5380_write(hostdata->c400_blk_cnt, len / 128);
  
  	do {
  		if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
  		                           CSR_HOST_BUF_NOT_RDY, 0,
  		                           hostdata->c400_ctl_status,
  		                           CSR_GATED_53C80_IRQ,
  		                           CSR_GATED_53C80_IRQ, HZ / 64) < 0 ||
  		    NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) {
  			/* Both 128 B buffers are in use */
  			if (start >= 128)
  				start -= 128;
  			if (start >= 128)
  				start -= 128;
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
602
  		if (start >= len && NCR5380_read(hostdata->c400_blk_cnt) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
  			break;
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
604

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
605
606
607
608
609
610
  		if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
  			/* Host buffer is empty, other one is in use */
  			if (start >= 128)
  				start -= 128;
  			break;
  		}
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
611

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
612
613
  		if (start >= len)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614

820682b1b   Finn Thain   scsi: ncr5380: St...
615
616
  		if (hostdata->io_port && hostdata->io_width == 2)
  			outsw(hostdata->io_port + hostdata->c400_host_buf,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
617
  			      src + start, 64);
820682b1b   Finn Thain   scsi: ncr5380: St...
618
619
  		else if (hostdata->io_port)
  			outsb(hostdata->io_port + hostdata->c400_host_buf,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
620
  			      src + start, 128);
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
621
  		else
820682b1b   Finn Thain   scsi: ncr5380: St...
622
  			memcpy_toio(hostdata->io + NCR53C400_host_buffer,
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
623
  			            src + start, 128);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  		start += 128;
99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
625
  	} while (1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
627
  	residual = len - start;
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
628

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
  	if (residual != 0) {
  		/* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */
  		NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
  		NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
  	}
  	wait_for_53c80_access(hostdata);
  
  	if (residual == 0) {
  		if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
  		                          TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT,
  		                          HZ / 64) < 0)
  			scmd_printk(KERN_ERR, hostdata->connected,
  			            "%s: Last Byte Sent timeout
  ", __func__);
  
  		if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
  		                          BASR_END_DMA_TRANSFER, BASR_END_DMA_TRANSFER,
  		                          HZ / 64) < 0)
  			scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout
  ",
  			            __func__);
aeb51152b   Ondrej Zary   ncr5380: Enable P...
650
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651

99a974e6b   Ondrej Zary   scsi: g_NCR5380: ...
652
  	hostdata->pdma_residual = residual;
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
653

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
  	return 0;
  }
ff3d45788   Finn Thain   ncr5380: Implemen...
656

4a98f896b   Finn Thain   scsi: ncr5380: Us...
657
  static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata,
7e9ec8d9c   Finn Thain   ncr5380: Remove F...
658
                                          struct scsi_cmnd *cmd)
ff3d45788   Finn Thain   ncr5380: Implemen...
659
  {
12b859b70   Ondrej Zary   scsi: g_NCR5380: ...
660
  	int transfersize = cmd->SCp.this_residual;
ff3d45788   Finn Thain   ncr5380: Implemen...
661

7e9ec8d9c   Finn Thain   ncr5380: Remove F...
662
663
  	if (hostdata->flags & FLAG_NO_PSEUDO_DMA)
  		return 0;
f03946210   Ondrej Zary   ncr5380: Fix pseu...
664
665
  	/* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */
  	if (transfersize % 128)
facfc963a   Ondrej Zary   scsi: g_NCR5380: ...
666
667
668
669
670
671
  		return 0;
  
  	/* Limit PDMA send to 512 B to avoid random corruption on DTC3181E */
  	if (hostdata->board == BOARD_DTC3181E &&
  	    cmd->sc_data_direction == DMA_TO_DEVICE)
  		transfersize = min(cmd->SCp.this_residual, 512);
f03946210   Ondrej Zary   ncr5380: Fix pseu...
672

12b859b70   Ondrej Zary   scsi: g_NCR5380: ...
673
  	return min(transfersize, DMA_MAX_SIZE);
ff3d45788   Finn Thain   ncr5380: Implemen...
674
  }
e9dbadf78   Ondrej Zary   scsi: g_NCR5380: ...
675
676
677
678
  static int generic_NCR5380_dma_residual(struct NCR5380_hostdata *hostdata)
  {
  	return hostdata->pdma_residual;
  }
24c43341a   Finn Thain   scsi: g_NCR5380: ...
679
  /* Include the core driver code. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  #include "NCR5380.c"
d0be4a7d2   Christoph Hellwig   [SCSI] remove Scs...
681
  static struct scsi_host_template driver_template = {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
682
  	.module			= THIS_MODULE,
aa2e2cb1d   Finn Thain   ncr5380: Fix and ...
683
  	.proc_name		= DRV_MODULE_NAME,
aa2e2cb1d   Finn Thain   ncr5380: Fix and ...
684
  	.name			= "Generic NCR5380/NCR53C400 SCSI",
aa2e2cb1d   Finn Thain   ncr5380: Fix and ...
685
686
  	.info			= generic_NCR5380_info,
  	.queuecommand		= generic_NCR5380_queue_command,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  	.eh_abort_handler	= generic_NCR5380_abort,
12e5fc665   Hannes Reinecke   scsi: NCR5380: Mo...
688
  	.eh_host_reset_handler	= generic_NCR5380_host_reset,
aa2e2cb1d   Finn Thain   ncr5380: Fix and ...
689
690
691
692
  	.can_queue		= 16,
  	.this_id		= 7,
  	.sg_tablesize		= SG_ALL,
  	.cmd_per_lun		= 2,
4af14d113   Christoph Hellwig   scsi: remove the ...
693
  	.dma_boundary		= PAGE_SIZE - 1,
32b26a104   Finn Thain   ncr5380: Use stan...
694
  	.cmd_size		= NCR5380_CMD_SIZE,
0a4e36125   Finn Thain   ncr5380: Fix soft...
695
  	.max_sectors		= 128,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
  };
161c0059a   Finn Thain   ncr5380: Cleanup ...
697

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
698
699
700
  static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev)
  {
  	int ret = generic_NCR5380_init_one(&driver_template, pdev, base[ndev],
24c43341a   Finn Thain   scsi: g_NCR5380: ...
701
  	                                   irq[ndev], card[ndev]);
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
702
703
704
705
706
707
708
  	if (ret) {
  		if (base[ndev])
  			printk(KERN_WARNING "Card not found at address 0x%03x
  ",
  			       base[ndev]);
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
710
711
712
713
  	return 1;
  }
  
  static int generic_NCR5380_isa_remove(struct device *pdev,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
714
                                        unsigned int ndev)
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
715
716
717
718
719
720
721
722
723
724
725
726
727
  {
  	generic_NCR5380_release_resources(dev_get_drvdata(pdev));
  	dev_set_drvdata(pdev, NULL);
  	return 0;
  }
  
  static struct isa_driver generic_NCR5380_isa_driver = {
  	.match		= generic_NCR5380_isa_match,
  	.remove		= generic_NCR5380_isa_remove,
  	.driver		= {
  		.name	= DRV_MODULE_NAME
  	},
  };
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
728
  #ifdef CONFIG_PNP
60747936b   Arvind Yadav   scsi: ncr5380: co...
729
  static const struct pnp_device_id generic_NCR5380_pnp_ids[] = {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
730
731
732
733
734
735
  	{ .id = "DTC436e", .driver_data = BOARD_DTC3181E },
  	{ .id = "" }
  };
  MODULE_DEVICE_TABLE(pnp, generic_NCR5380_pnp_ids);
  
  static int generic_NCR5380_pnp_probe(struct pnp_dev *pdev,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
736
                                       const struct pnp_device_id *id)
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
737
738
739
740
741
742
743
744
745
746
  {
  	int base, irq;
  
  	if (pnp_activate_dev(pdev) < 0)
  		return -EBUSY;
  
  	base = pnp_port_start(pdev, 0);
  	irq = pnp_irq(pdev, 0);
  
  	return generic_NCR5380_init_one(&driver_template, &pdev->dev, base, irq,
24c43341a   Finn Thain   scsi: g_NCR5380: ...
747
  	                                id->driver_data);
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
748
749
750
751
752
753
754
755
756
757
758
759
760
  }
  
  static void generic_NCR5380_pnp_remove(struct pnp_dev *pdev)
  {
  	generic_NCR5380_release_resources(pnp_get_drvdata(pdev));
  	pnp_set_drvdata(pdev, NULL);
  }
  
  static struct pnp_driver generic_NCR5380_pnp_driver = {
  	.name		= DRV_MODULE_NAME,
  	.id_table	= generic_NCR5380_pnp_ids,
  	.probe		= generic_NCR5380_pnp_probe,
  	.remove		= generic_NCR5380_pnp_remove,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
  };
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
762
  #endif /* defined(CONFIG_PNP) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763

a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
764
765
766
767
768
769
770
  static int pnp_registered, isa_registered;
  
  static int __init generic_NCR5380_init(void)
  {
  	int ret = 0;
  
  	/* compatibility with old-style parameters */
70439e933   Finn Thain   scsi: g_NCR5380: ...
771
  	if (irq[0] == -1 && base[0] == 0 && card[0] == -1) {
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
772
773
774
775
776
777
778
779
780
781
782
783
784
  		irq[0] = ncr_irq;
  		base[0] = ncr_addr;
  		if (ncr_5380)
  			card[0] = BOARD_NCR5380;
  		if (ncr_53c400)
  			card[0] = BOARD_NCR53C400;
  		if (ncr_53c400a)
  			card[0] = BOARD_NCR53C400A;
  		if (dtc_3181e)
  			card[0] = BOARD_DTC3181E;
  		if (hp_c2502)
  			card[0] = BOARD_HP_C2502;
  	}
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
785
  #ifdef CONFIG_PNP
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
786
787
  	if (!pnp_register_driver(&generic_NCR5380_pnp_driver))
  		pnp_registered = 1;
702a98c63   Ondrej Zary   g_NCR5380: fix br...
788
  #endif
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
789
790
791
792
793
794
795
796
797
  	ret = isa_register_driver(&generic_NCR5380_isa_driver, MAX_CARDS);
  	if (!ret)
  		isa_registered = 1;
  
  	return (pnp_registered || isa_registered) ? 0 : ret;
  }
  
  static void __exit generic_NCR5380_exit(void)
  {
b61bacbc2   Ondrej Zary   scsi: g_NCR5380: ...
798
  #ifdef CONFIG_PNP
a8cfbcaec   Ondrej Zary   scsi: g_NCR5380: ...
799
800
801
802
803
804
805
806
807
  	if (pnp_registered)
  		pnp_unregister_driver(&generic_NCR5380_pnp_driver);
  #endif
  	if (isa_registered)
  		isa_unregister_driver(&generic_NCR5380_isa_driver);
  }
  
  module_init(generic_NCR5380_init);
  module_exit(generic_NCR5380_exit);