]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/scsi/aha1542.c
aha1542: rework locking
[mirror_ubuntu-artful-kernel.git] / drivers / scsi / aha1542.c
CommitLineData
1d084d20
OZ
1/*
2 * Driver for Adaptec AHA-1542 SCSI host adapters
1da177e4
LT
3 *
4 * Copyright (C) 1992 Tommy Thorn
5 * Copyright (C) 1993, 1994, 1995 Eric Youngdale
1d084d20 6 * Copyright (C) 2015 Ondrej Zary
1da177e4
LT
7 */
8
1da177e4
LT
9#include <linux/module.h>
10#include <linux/interrupt.h>
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/string.h>
1da177e4 14#include <linux/delay.h>
1da177e4
LT
15#include <linux/init.h>
16#include <linux/spinlock.h>
643a7c43
OZ
17#include <linux/isa.h>
18#include <linux/pnp.h>
5a0e3ad6 19#include <linux/slab.h>
954a9fd7 20#include <linux/io.h>
1da177e4 21#include <asm/dma.h>
954a9fd7
OZ
22#include <scsi/scsi_cmnd.h>
23#include <scsi/scsi_device.h>
1da177e4
LT
24#include <scsi/scsi_host.h>
25#include "aha1542.h"
1da177e4 26
f71429ab 27#define MAXBOARDS 4
1da177e4 28
f71429ab
OZ
29static bool isapnp = 1;
30module_param(isapnp, bool, 0);
31MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
1da177e4 32
f71429ab
OZ
33static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
34module_param_array(io, int, NULL, 0);
35MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
1da177e4 36
f71429ab
OZ
37/* time AHA spends on the AT-bus during data transfer */
38static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */
39module_param_array(bus_on, int, NULL, 0);
40MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])");
1da177e4 41
f71429ab
OZ
42/* time AHA spends off the bus (not to monopolize it) during data transfer */
43static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */
44module_param_array(bus_off, int, NULL, 0);
45MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])");
1da177e4 46
f71429ab
OZ
47/* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */
48static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 };
49module_param_array(dma_speed, int, NULL, 0);
50MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])");
1da177e4 51
1da177e4
LT
52#define BIOS_TRANSLATION_6432 1 /* Default case these days */
53#define BIOS_TRANSLATION_25563 2 /* Big disk case */
54
55struct aha1542_hostdata {
56 /* This will effectively start both of them at the first mailbox */
57 int bios_translation; /* Mapping bios uses - for compatibility */
58 int aha1542_last_mbi_used;
59 int aha1542_last_mbo_used;
55b28f9f 60 struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
1da177e4
LT
61 struct mailbox mb[2 * AHA1542_MAILBOXES];
62 struct ccb ccb[AHA1542_MAILBOXES];
63};
64
f1bbef63
OZ
65static inline void aha1542_intr_reset(u16 base)
66{
67 outb(IRST, CONTROL(base));
68}
1da177e4 69
2093bfa1
OZ
70static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
71{
72 bool delayed = true;
73
74 if (timeout == 0) {
75 timeout = 3000000;
76 delayed = false;
77 }
78
79 while (1) {
80 u8 bits = inb(port) & mask;
81 if ((bits & allof) == allof && ((bits & noneof) == 0))
82 break;
83 if (delayed)
84 mdelay(1);
85 if (--timeout == 0)
86 return false;
87 }
88
89 return true;
90}
1da177e4 91
cad2fc72 92static int aha1542_outb(unsigned int base, u8 val)
1da177e4 93{
0c2b6481 94 while (1) {
2906b3ce 95 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
0c2b6481 96 return 1;
1b0224b0 97 if (inb(STATUS(base)) & CDF)
0c2b6481 98 continue;
cad2fc72 99 outb(val, DATA(base));
0c2b6481 100 return 0;
1da177e4 101 }
0c2b6481
OZ
102}
103
cad2fc72 104static int aha1542_out(unsigned int base, u8 *buf, int len)
0c2b6481 105{
0c2b6481 106 while (len--) {
1b0224b0 107 if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
0c2b6481 108 return 1;
cad2fc72 109 outb(*buf++, DATA(base));
0c2b6481 110 }
23e6940a
OZ
111 if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
112 return 1;
0c2b6481 113
1da177e4 114 return 0;
1da177e4
LT
115}
116
117/* Only used at boot time, so we do not need to worry about latency as much
118 here */
119
cad2fc72 120static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
1da177e4 121{
1da177e4 122 while (len--) {
1b0224b0 123 if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
a13b3722 124 return 1;
cad2fc72 125 *buf++ = inb(DATA(base));
1da177e4 126 }
1da177e4 127 return 0;
1da177e4
LT
128}
129
130static int makecode(unsigned hosterr, unsigned scsierr)
131{
132 switch (hosterr) {
133 case 0x0:
134 case 0xa: /* Linked command complete without error and linked normally */
135 case 0xb: /* Linked command complete without error, interrupt generated */
136 hosterr = 0;
137 break;
138
139 case 0x11: /* Selection time out-The initiator selection or target
140 reselection was not complete within the SCSI Time out period */
141 hosterr = DID_TIME_OUT;
142 break;
143
144 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
145 than was allocated by the Data Length field or the sum of the
146 Scatter / Gather Data Length fields. */
147
148 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
149
150 case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
151 invalid. This usually indicates a software failure. */
152
153 case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
154 This usually indicates a software failure. */
155
156 case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
157 of linked CCB's does not specify the same logical unit number as
158 the first. */
159 case 0x18: /* Invalid Target Direction received from Host-The direction of a
160 Target Mode CCB was invalid. */
161
162 case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
163 received to service data transfer between the same target LUN
164 and initiator SCSI ID in the same direction. */
165
166 case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
167 length segment or invalid segment list boundaries was received.
168 A CCB parameter was invalid. */
fde1fb8a
OZ
169#ifdef DEBUG
170 printk("Aha1542: %x %x\n", hosterr, scsierr);
171#endif
1da177e4
LT
172 hosterr = DID_ERROR; /* Couldn't find any better */
173 break;
174
175 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
176 phase sequence was requested by the target. The host adapter
177 will generate a SCSI Reset Condition, notifying the host with
178 a SCRD interrupt */
179 hosterr = DID_RESET;
180 break;
181 default:
182 printk(KERN_ERR "aha1542: makecode: unknown hoststatus %x\n", hosterr);
183 break;
184 }
185 return scsierr | (hosterr << 16);
186}
187
68ea9de3 188static int aha1542_test_port(struct Scsi_Host *sh)
1da177e4 189{
cb5b570c 190 u8 inquiry_result[4];
cad2fc72 191 int i;
1da177e4
LT
192
193 /* Quick and dirty test for presence of the card. */
68ea9de3 194 if (inb(STATUS(sh->io_port)) == 0xff)
1da177e4
LT
195 return 0;
196
197 /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */
198
1da177e4 199 /* In case some other card was probing here, reset interrupts */
68ea9de3 200 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
1da177e4 201
68ea9de3 202 outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port));
1da177e4
LT
203
204 mdelay(20); /* Wait a little bit for things to settle down. */
205
1da177e4 206 /* Expect INIT and IDLE, any of the others are bad */
68ea9de3 207 if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0))
a13b3722 208 return 0;
1da177e4 209
1da177e4 210 /* Shouldn't have generated any interrupts during reset */
68ea9de3 211 if (inb(INTRFLAGS(sh->io_port)) & INTRMASK)
a13b3722 212 return 0;
1da177e4 213
1da177e4
LT
214 /* Perform a host adapter inquiry instead so we do not need to set
215 up the mailboxes ahead of time */
216
68ea9de3 217 aha1542_outb(sh->io_port, CMD_INQUIRY);
1da177e4 218
cad2fc72 219 for (i = 0; i < 4; i++) {
68ea9de3 220 if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0))
a13b3722 221 return 0;
68ea9de3 222 inquiry_result[i] = inb(DATA(sh->io_port));
1da177e4
LT
223 }
224
1da177e4 225 /* Reading port should reset DF */
68ea9de3 226 if (inb(STATUS(sh->io_port)) & DF)
a13b3722 227 return 0;
1da177e4 228
1da177e4 229 /* When HACC, command is completed, and we're though testing */
68ea9de3 230 if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0))
a13b3722 231 return 0;
1da177e4 232
1da177e4 233 /* Clear interrupts */
68ea9de3 234 outb(IRST, CONTROL(sh->io_port));
1da177e4 235
bdebe224 236 return 1;
1da177e4
LT
237}
238
1b0224b0 239static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
1da177e4 240{
1b0224b0 241 struct Scsi_Host *sh = dev_id;
c2532f68 242 struct aha1542_hostdata *aha1542 = shost_priv(sh);
55b28f9f 243 void (*my_done)(struct scsi_cmnd *) = NULL;
1da177e4
LT
244 int errstatus, mbi, mbo, mbistatus;
245 int number_serviced;
246 unsigned long flags;
55b28f9f 247 struct scsi_cmnd *tmp_cmd;
1da177e4 248 int flag;
e98878f7
OZ
249 struct mailbox *mb = aha1542->mb;
250 struct ccb *ccb = aha1542->ccb;
1da177e4
LT
251
252#ifdef DEBUG
253 {
c2532f68 254 flag = inb(INTRFLAGS(sh->io_port));
2906b3ce 255 shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: ");
1da177e4
LT
256 if (!(flag & ANYINTR))
257 printk("no interrupt?");
258 if (flag & MBIF)
259 printk("MBIF ");
260 if (flag & MBOA)
261 printk("MBOF ");
262 if (flag & HACC)
263 printk("HACC ");
264 if (flag & SCRD)
265 printk("SCRD ");
c2532f68 266 printk("status %02x\n", inb(STATUS(sh->io_port)));
1da177e4
LT
267 };
268#endif
269 number_serviced = 0;
1da177e4 270
1b0224b0
OZ
271 spin_lock_irqsave(sh->host_lock, flags);
272 while (1) {
c2532f68 273 flag = inb(INTRFLAGS(sh->io_port));
1da177e4
LT
274
275 /* Check for unusual interrupts. If any of these happen, we should
276 probably do something special, but for now just printing a message
277 is sufficient. A SCSI reset detected is something that we really
278 need to deal with in some way. */
279 if (flag & ~MBIF) {
280 if (flag & MBOA)
281 printk("MBOF ");
282 if (flag & HACC)
283 printk("HACC ");
dfd7c991 284 if (flag & SCRD)
1da177e4 285 printk("SCRD ");
1da177e4 286 }
c2532f68 287 aha1542_intr_reset(sh->io_port);
1da177e4 288
e98878f7 289 mbi = aha1542->aha1542_last_mbi_used + 1;
1da177e4
LT
290 if (mbi >= 2 * AHA1542_MAILBOXES)
291 mbi = AHA1542_MAILBOXES;
292
293 do {
294 if (mb[mbi].status != 0)
295 break;
296 mbi++;
297 if (mbi >= 2 * AHA1542_MAILBOXES)
298 mbi = AHA1542_MAILBOXES;
e98878f7 299 } while (mbi != aha1542->aha1542_last_mbi_used);
1da177e4
LT
300
301 if (mb[mbi].status == 0) {
1b0224b0 302 spin_unlock_irqrestore(sh->host_lock, flags);
1da177e4 303 /* Hmm, no mail. Must have read it the last time around */
dfd7c991 304 if (!number_serviced)
2906b3ce 305 shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
1b0224b0 306 return IRQ_HANDLED;
1da177e4
LT
307 };
308
10be6250 309 mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
1da177e4
LT
310 mbistatus = mb[mbi].status;
311 mb[mbi].status = 0;
e98878f7 312 aha1542->aha1542_last_mbi_used = mbi;
1da177e4
LT
313
314#ifdef DEBUG
fde1fb8a
OZ
315 if (ccb[mbo].tarstat | ccb[mbo].hastat)
316 shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n",
317 ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
1da177e4
LT
318#endif
319
320 if (mbistatus == 3)
321 continue; /* Aborted command not found */
322
323#ifdef DEBUG
2906b3ce 324 shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi);
1da177e4
LT
325#endif
326
55b28f9f 327 tmp_cmd = aha1542->int_cmds[mbo];
1da177e4 328
55b28f9f 329 if (!tmp_cmd || !tmp_cmd->scsi_done) {
1b0224b0 330 spin_unlock_irqrestore(sh->host_lock, flags);
2906b3ce
OZ
331 shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
332 shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
1da177e4 333 ccb[mbo].hastat, ccb[mbo].idlun, mbo);
1b0224b0 334 return IRQ_HANDLED;
1da177e4 335 }
55b28f9f
OZ
336 my_done = tmp_cmd->scsi_done;
337 kfree(tmp_cmd->host_scribble);
338 tmp_cmd->host_scribble = NULL;
1da177e4
LT
339 /* Fetch the sense data, and tuck it away, in the required slot. The
340 Adaptec automatically fetches it, and there is no guarantee that
341 we will still have it in the cdb when we come back */
342 if (ccb[mbo].tarstat == 2)
55b28f9f 343 memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
b80ca4f7 344 SCSI_SENSE_BUFFERSIZE);
1da177e4
LT
345
346
347 /* is there mail :-) */
348
349 /* more error checking left out here */
350 if (mbistatus != 1)
351 /* This is surely wrong, but I don't know what's right */
352 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
353 else
354 errstatus = 0;
355
356#ifdef DEBUG
357 if (errstatus)
2906b3ce 358 shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus,
1da177e4 359 ccb[mbo].hastat, ccb[mbo].tarstat);
6ddc8cf4
OZ
360 if (ccb[mbo].tarstat == 2)
361 print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12);
fde1fb8a
OZ
362 if (errstatus)
363 printk("aha1542_intr_handle: returning %6x\n", errstatus);
364#endif
55b28f9f
OZ
365 tmp_cmd->result = errstatus;
366 aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as
e98878f7 367 far as queuecommand is concerned */
55b28f9f 368 my_done(tmp_cmd);
1da177e4
LT
369 number_serviced++;
370 };
371}
372
1b0224b0 373static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
09a44833 374{
2906b3ce 375 struct aha1542_hostdata *aha1542 = shost_priv(sh);
cb5b570c 376 u8 direction;
55b28f9f
OZ
377 u8 target = cmd->device->id;
378 u8 lun = cmd->device->lun;
1da177e4 379 unsigned long flags;
55b28f9f 380 int bufflen = scsi_bufflen(cmd);
1da177e4 381 int mbo;
e98878f7
OZ
382 struct mailbox *mb = aha1542->mb;
383 struct ccb *ccb = aha1542->ccb;
1da177e4 384
55b28f9f 385 if (*cmd->cmnd == REQUEST_SENSE) {
1da177e4 386 /* Don't do the command - we have the sense data already */
55b28f9f 387 cmd->result = 0;
1b0224b0 388 cmd->scsi_done(cmd);
1da177e4
LT
389 return 0;
390 }
391#ifdef DEBUG
764a0c7e
OZ
392 {
393 int i = -1;
394 if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10)
395 i = xscsi2int(cmd->cmnd + 2);
396 else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6)
397 i = scsi2int(cmd->cmnd + 2);
398 shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d",
399 target, *cmd->cmnd, i, bufflen);
400 print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
401 }
1da177e4
LT
402#endif
403 /* Use the outgoing mailboxes in a round-robin fashion, because this
404 is how the host adapter will scan for them */
405
1b0224b0 406 spin_lock_irqsave(sh->host_lock, flags);
e98878f7 407 mbo = aha1542->aha1542_last_mbo_used + 1;
1da177e4
LT
408 if (mbo >= AHA1542_MAILBOXES)
409 mbo = 0;
410
411 do {
55b28f9f 412 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
1da177e4
LT
413 break;
414 mbo++;
415 if (mbo >= AHA1542_MAILBOXES)
416 mbo = 0;
e98878f7 417 } while (mbo != aha1542->aha1542_last_mbo_used);
1da177e4 418
55b28f9f 419 if (mb[mbo].status || aha1542->int_cmds[mbo])
1da177e4
LT
420 panic("Unable to find empty mailbox for aha1542.\n");
421
55b28f9f 422 aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from
e98878f7 423 screwing with this cdb. */
1da177e4 424
e98878f7 425 aha1542->aha1542_last_mbo_used = mbo;
1da177e4
LT
426
427#ifdef DEBUG
1b0224b0 428 shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
1da177e4
LT
429#endif
430
10be6250 431 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
1da177e4
LT
432
433 memset(&ccb[mbo], 0, sizeof(struct ccb));
434
55b28f9f 435 ccb[mbo].cdblen = cmd->cmd_len;
1da177e4
LT
436
437 direction = 0;
55b28f9f 438 if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6)
1da177e4 439 direction = 8;
55b28f9f 440 else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6)
1da177e4
LT
441 direction = 16;
442
55b28f9f 443 memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen);
1da177e4 444
fc3fdfcc 445 if (bufflen) {
51cf2249 446 struct scatterlist *sg;
1da177e4 447 struct chain *cptr;
55b28f9f 448 int i, sg_count = scsi_sg_count(cmd);
6ddc8cf4 449
1da177e4 450 ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
55b28f9f 451 cmd->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
fc3fdfcc 452 GFP_KERNEL | GFP_DMA);
55b28f9f 453 cptr = (struct chain *) cmd->host_scribble;
1da177e4
LT
454 if (cptr == NULL) {
455 /* free the claimed mailbox slot */
55b28f9f 456 aha1542->int_cmds[mbo] = NULL;
1b0224b0 457 spin_unlock_irqrestore(sh->host_lock, flags);
1da177e4
LT
458 return SCSI_MLQUEUE_HOST_BUSY;
459 }
55b28f9f 460 scsi_for_each_sg(cmd, sg, sg_count, i) {
10be6250
OZ
461 any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
462 + sg->offset);
51cf2249 463 any2scsi(cptr[i].datalen, sg->length);
1da177e4 464 };
fc3fdfcc 465 any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain));
10be6250 466 any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr));
1da177e4 467#ifdef DEBUG
6ddc8cf4
OZ
468 shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr);
469 print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18);
1da177e4
LT
470#endif
471 } else {
472 ccb[mbo].op = 0; /* SCSI Initiator Command */
55b28f9f 473 cmd->host_scribble = NULL;
fc3fdfcc
BH
474 any2scsi(ccb[mbo].datalen, 0);
475 any2scsi(ccb[mbo].dataptr, 0);
1da177e4
LT
476 };
477 ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7); /*SCSI Target Id */
478 ccb[mbo].rsalen = 16;
479 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
480 ccb[mbo].commlinkid = 0;
481
482#ifdef DEBUG
6ddc8cf4 483 print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
1b0224b0 484 printk("aha1542_queuecommand: now waiting for interrupt ");
1da177e4 485#endif
1b0224b0
OZ
486 mb[mbo].status = 1;
487 aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
488 spin_unlock_irqrestore(sh->host_lock, flags);
1da177e4
LT
489
490 return 0;
491}
492
493/* Initialize mailboxes */
68ea9de3 494static void setup_mailboxes(struct Scsi_Host *sh)
1da177e4 495{
c2532f68 496 struct aha1542_hostdata *aha1542 = shost_priv(sh);
1da177e4 497 int i;
e98878f7
OZ
498 struct mailbox *mb = aha1542->mb;
499 struct ccb *ccb = aha1542->ccb;
1da177e4 500
cad2fc72 501 u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};
1da177e4 502
1da177e4
LT
503 for (i = 0; i < AHA1542_MAILBOXES; i++) {
504 mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;
10be6250 505 any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i]));
1da177e4 506 };
68ea9de3 507 aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */
cad2fc72 508 any2scsi((mb_cmd + 2), isa_virt_to_bus(mb));
68ea9de3 509 if (aha1542_out(sh->io_port, mb_cmd, 5))
2906b3ce 510 shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n");
68ea9de3 511 aha1542_intr_reset(sh->io_port);
1da177e4
LT
512}
513
68ea9de3 514static int aha1542_getconfig(struct Scsi_Host *sh)
1da177e4 515{
cb5b570c 516 u8 inquiry_result[3];
1da177e4 517 int i;
68ea9de3 518 i = inb(STATUS(sh->io_port));
1da177e4 519 if (i & DF) {
68ea9de3 520 i = inb(DATA(sh->io_port));
1da177e4 521 };
68ea9de3
OZ
522 aha1542_outb(sh->io_port, CMD_RETCONF);
523 aha1542_in(sh->io_port, inquiry_result, 3, 0);
524 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
2906b3ce 525 shost_printk(KERN_ERR, sh, "error querying board settings\n");
68ea9de3 526 aha1542_intr_reset(sh->io_port);
1da177e4
LT
527 switch (inquiry_result[0]) {
528 case 0x80:
68ea9de3 529 sh->dma_channel = 7;
1da177e4
LT
530 break;
531 case 0x40:
68ea9de3 532 sh->dma_channel = 6;
1da177e4
LT
533 break;
534 case 0x20:
68ea9de3 535 sh->dma_channel = 5;
1da177e4
LT
536 break;
537 case 0x01:
68ea9de3 538 sh->dma_channel = 0;
1da177e4
LT
539 break;
540 case 0:
541 /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
542 Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
68ea9de3 543 sh->dma_channel = 0xFF;
1da177e4
LT
544 break;
545 default:
2906b3ce 546 shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n");
1da177e4
LT
547 return -1;
548 };
549 switch (inquiry_result[1]) {
550 case 0x40:
68ea9de3 551 sh->irq = 15;
1da177e4
LT
552 break;
553 case 0x20:
68ea9de3 554 sh->irq = 14;
1da177e4
LT
555 break;
556 case 0x8:
68ea9de3 557 sh->irq = 12;
1da177e4
LT
558 break;
559 case 0x4:
68ea9de3 560 sh->irq = 11;
1da177e4
LT
561 break;
562 case 0x2:
68ea9de3 563 sh->irq = 10;
1da177e4
LT
564 break;
565 case 0x1:
68ea9de3 566 sh->irq = 9;
1da177e4
LT
567 break;
568 default:
2906b3ce 569 shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n");
1da177e4
LT
570 return -1;
571 };
68ea9de3 572 sh->this_id = inquiry_result[2] & 7;
1da177e4
LT
573 return 0;
574}
575
576/* This function should only be called for 1542C boards - we can detect
577 the special firmware settings and unlock the board */
578
68ea9de3 579static int aha1542_mbenable(struct Scsi_Host *sh)
1da177e4 580{
cb5b570c
OZ
581 static u8 mbenable_cmd[3];
582 static u8 mbenable_result[2];
1da177e4
LT
583 int retval;
584
585 retval = BIOS_TRANSLATION_6432;
586
68ea9de3
OZ
587 aha1542_outb(sh->io_port, CMD_EXTBIOS);
588 if (aha1542_in(sh->io_port, mbenable_result, 2, 100))
1da177e4 589 return retval;
68ea9de3 590 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100))
2093bfa1 591 goto fail;
68ea9de3 592 aha1542_intr_reset(sh->io_port);
1da177e4
LT
593
594 if ((mbenable_result[0] & 0x08) || mbenable_result[1]) {
595 mbenable_cmd[0] = CMD_MBENABLE;
596 mbenable_cmd[1] = 0;
597 mbenable_cmd[2] = mbenable_result[1];
598
599 if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
600 retval = BIOS_TRANSLATION_25563;
601
68ea9de3 602 if (aha1542_out(sh->io_port, mbenable_cmd, 3))
2093bfa1 603 goto fail;
1da177e4
LT
604 };
605 while (0) {
606fail:
2906b3ce 607 shost_printk(KERN_ERR, sh, "Mailbox init failed\n");
1da177e4 608 }
68ea9de3 609 aha1542_intr_reset(sh->io_port);
1da177e4
LT
610 return retval;
611}
612
613/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
68ea9de3 614static int aha1542_query(struct Scsi_Host *sh)
1da177e4 615{
68ea9de3 616 struct aha1542_hostdata *aha1542 = shost_priv(sh);
cb5b570c 617 u8 inquiry_result[4];
1da177e4 618 int i;
68ea9de3 619 i = inb(STATUS(sh->io_port));
1da177e4 620 if (i & DF) {
68ea9de3 621 i = inb(DATA(sh->io_port));
1da177e4 622 };
68ea9de3
OZ
623 aha1542_outb(sh->io_port, CMD_INQUIRY);
624 aha1542_in(sh->io_port, inquiry_result, 4, 0);
625 if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0))
2906b3ce 626 shost_printk(KERN_ERR, sh, "error querying card type\n");
68ea9de3 627 aha1542_intr_reset(sh->io_port);
1da177e4 628
68ea9de3 629 aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */
1da177e4
LT
630
631 /* For an AHA1740 series board, we ignore the board since there is a
632 hardware bug which can lead to wrong blocks being returned if the board
633 is operating in the 1542 emulation mode. Since there is an extended mode
634 driver, we simply ignore the board and let the 1740 driver pick it up.
635 */
636
637 if (inquiry_result[0] == 0x43) {
2906b3ce 638 shost_printk(KERN_INFO, sh, "Emulation mode not supported for AHA-1740 hardware, use aha1740 driver instead.\n");
1da177e4
LT
639 return 1;
640 };
641
642 /* Always call this - boards that do not support extended bios translation
643 will ignore the command, and we will set the proper default */
644
68ea9de3 645 aha1542->bios_translation = aha1542_mbenable(sh);
1da177e4
LT
646
647 return 0;
648}
649
f71429ab 650static u8 dma_speed_hw(int dma_speed)
1da177e4 651{
f71429ab
OZ
652 switch (dma_speed) {
653 case 5:
654 return 0x00;
655 case 6:
656 return 0x04;
657 case 7:
658 return 0x01;
659 case 8:
660 return 0x02;
661 case 10:
662 return 0x03;
1da177e4 663 }
1da177e4 664
f71429ab 665 return 0xff; /* invalid */
1da177e4
LT
666}
667
f71429ab 668/* Set the Bus on/off-times as not to ruin floppy performance */
37d607bd 669static void aha1542_set_bus_times(struct Scsi_Host *sh, int bus_on, int bus_off, int dma_speed)
1da177e4 670{
37d607bd
OZ
671 if (bus_on > 0) {
672 u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) };
1da177e4 673
37d607bd
OZ
674 aha1542_intr_reset(sh->io_port);
675 if (aha1542_out(sh->io_port, oncmd, 2))
f71429ab
OZ
676 goto fail;
677 }
1da177e4 678
37d607bd
OZ
679 if (bus_off > 0) {
680 u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) };
1da177e4 681
37d607bd
OZ
682 aha1542_intr_reset(sh->io_port);
683 if (aha1542_out(sh->io_port, offcmd, 2))
f71429ab
OZ
684 goto fail;
685 }
1da177e4 686
37d607bd
OZ
687 if (dma_speed_hw(dma_speed) != 0xff) {
688 u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) };
b847fd0d 689
37d607bd
OZ
690 aha1542_intr_reset(sh->io_port);
691 if (aha1542_out(sh->io_port, dmacmd, 2))
b847fd0d
OZ
692 goto fail;
693 }
37d607bd 694 aha1542_intr_reset(sh->io_port);
b847fd0d
OZ
695 return;
696fail:
2906b3ce 697 shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n");
37d607bd 698 aha1542_intr_reset(sh->io_port);
b847fd0d
OZ
699}
700
1da177e4 701/* return non-zero on detection */
643a7c43 702static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx)
1da177e4 703{
f71429ab 704 unsigned int base_io = io[indx];
c2532f68 705 struct Scsi_Host *sh;
e98878f7 706 struct aha1542_hostdata *aha1542;
2906b3ce 707 char dma_info[] = "no DMA";
1da177e4 708
3a70c006
OZ
709 if (base_io == 0)
710 return NULL;
1da177e4 711
3a70c006
OZ
712 if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542"))
713 return NULL;
1da177e4 714
c2532f68
OZ
715 sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata));
716 if (!sh)
3a70c006 717 goto release;
c2532f68 718 aha1542 = shost_priv(sh);
b847fd0d 719
68ea9de3
OZ
720 sh->unique_id = base_io;
721 sh->io_port = base_io;
722 sh->n_io_port = AHA1542_REGION_SIZE;
723 aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1;
724 aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1;
725
726 if (!aha1542_test_port(sh))
3a70c006 727 goto unregister;
1da177e4 728
37d607bd 729 aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]);
68ea9de3 730 if (aha1542_query(sh))
3a70c006 731 goto unregister;
68ea9de3 732 if (aha1542_getconfig(sh) == -1)
3a70c006 733 goto unregister;
1da177e4 734
c2532f68 735 if (sh->dma_channel != 0xFF)
2906b3ce
OZ
736 snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel);
737 shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n",
738 sh->this_id, base_io, sh->irq, dma_info);
3a70c006 739 if (aha1542->bios_translation == BIOS_TRANSLATION_25563)
2906b3ce 740 shost_printk(KERN_INFO, sh, "Using extended bios translation\n");
1da177e4 741
68ea9de3 742 setup_mailboxes(sh);
1da177e4 743
1b0224b0 744 if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
2906b3ce 745 shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
3a70c006
OZ
746 goto unregister;
747 }
c2532f68
OZ
748 if (sh->dma_channel != 0xFF) {
749 if (request_dma(sh->dma_channel, "aha1542")) {
2906b3ce 750 shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n");
3a70c006
OZ
751 goto free_irq;
752 }
c2532f68
OZ
753 if (sh->dma_channel == 0 || sh->dma_channel >= 5) {
754 set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE);
755 enable_dma(sh->dma_channel);
3a70c006
OZ
756 }
757 }
1da177e4 758
c2532f68 759 if (scsi_add_host(sh, pdev))
3a70c006 760 goto free_dma;
1da177e4 761
c2532f68 762 scsi_scan_host(sh);
1da177e4 763
c2532f68 764 return sh;
3a70c006 765free_dma:
c2532f68
OZ
766 if (sh->dma_channel != 0xff)
767 free_dma(sh->dma_channel);
3a70c006 768free_irq:
c2532f68 769 free_irq(sh->irq, sh);
3a70c006 770unregister:
c2532f68 771 scsi_host_put(sh);
3a70c006
OZ
772release:
773 release_region(base_io, AHA1542_REGION_SIZE);
1da177e4 774
643a7c43 775 return NULL;
1da177e4
LT
776}
777
c2532f68 778static int aha1542_release(struct Scsi_Host *sh)
1da177e4 779{
c2532f68
OZ
780 scsi_remove_host(sh);
781 if (sh->dma_channel != 0xff)
782 free_dma(sh->dma_channel);
783 if (sh->irq)
784 free_irq(sh->irq, sh);
785 if (sh->io_port && sh->n_io_port)
786 release_region(sh->io_port, sh->n_io_port);
787 scsi_host_put(sh);
1da177e4
LT
788 return 0;
789}
790
1da177e4 791
1da177e4
LT
792/*
793 * This is a device reset. This is handled by sending a special command
794 * to the device.
795 */
55b28f9f 796static int aha1542_dev_reset(struct scsi_cmnd *cmd)
1da177e4 797{
1b0224b0
OZ
798 struct Scsi_Host *sh = cmd->device->host;
799 struct aha1542_hostdata *aha1542 = shost_priv(sh);
1da177e4 800 unsigned long flags;
e98878f7 801 struct mailbox *mb = aha1542->mb;
55b28f9f
OZ
802 u8 target = cmd->device->id;
803 u8 lun = cmd->device->lun;
1da177e4 804 int mbo;
e98878f7 805 struct ccb *ccb = aha1542->ccb;
1da177e4 806
1b0224b0 807 spin_lock_irqsave(sh->host_lock, flags);
e98878f7 808 mbo = aha1542->aha1542_last_mbo_used + 1;
1da177e4
LT
809 if (mbo >= AHA1542_MAILBOXES)
810 mbo = 0;
811
812 do {
55b28f9f 813 if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL)
1da177e4
LT
814 break;
815 mbo++;
816 if (mbo >= AHA1542_MAILBOXES)
817 mbo = 0;
e98878f7 818 } while (mbo != aha1542->aha1542_last_mbo_used);
1da177e4 819
55b28f9f 820 if (mb[mbo].status || aha1542->int_cmds[mbo])
1da177e4
LT
821 panic("Unable to find empty mailbox for aha1542.\n");
822
55b28f9f 823 aha1542->int_cmds[mbo] = cmd; /* This will effectively
e98878f7
OZ
824 prevent someone else from
825 screwing with this cdb. */
1da177e4 826
e98878f7 827 aha1542->aha1542_last_mbo_used = mbo;
1da177e4 828
10be6250 829 any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
1da177e4
LT
830
831 memset(&ccb[mbo], 0, sizeof(struct ccb));
832
833 ccb[mbo].op = 0x81; /* BUS DEVICE RESET */
834
835 ccb[mbo].idlun = (target & 7) << 5 | (lun & 7); /*SCSI Target Id */
836
837 ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
838 ccb[mbo].commlinkid = 0;
839
840 /*
841 * Now tell the 1542 to flush all pending commands for this
842 * target
843 */
1b0224b0
OZ
844 aha1542_outb(sh->io_port, CMD_START_SCSI);
845 spin_unlock_irqrestore(sh->host_lock, flags);
1da177e4 846
55b28f9f 847 scmd_printk(KERN_WARNING, cmd,
017560fc 848 "Trying device reset for target\n");
1da177e4
LT
849
850 return SUCCESS;
1da177e4
LT
851}
852
55b28f9f 853static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
1da177e4 854{
1b0224b0
OZ
855 struct Scsi_Host *sh = cmd->device->host;
856 struct aha1542_hostdata *aha1542 = shost_priv(sh);
857 unsigned long flags;
1da177e4
LT
858 int i;
859
1b0224b0 860 spin_lock_irqsave(sh->host_lock, flags);
1da177e4
LT
861 /*
862 * This does a scsi reset for all devices on the bus.
863 * In principle, we could also reset the 1542 - should
864 * we do this? Try this first, and we can add that later
865 * if it turns out to be useful.
866 */
55b28f9f 867 outb(reset_cmd, CONTROL(cmd->device->host->io_port));
1da177e4 868
55b28f9f 869 if (!wait_mask(STATUS(cmd->device->host->io_port),
a13b3722 870 STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
1b0224b0 871 spin_unlock_irqrestore(sh->host_lock, flags);
a13b3722
OZ
872 return FAILED;
873 }
1b0224b0 874
8537cba8
OZ
875 /*
876 * We need to do this too before the 1542 can interact with
877 * us again after host reset.
878 */
879 if (reset_cmd & HRST)
68ea9de3 880 setup_mailboxes(cmd->device->host);
1b0224b0 881
1da177e4
LT
882 /*
883 * Now try to pick up the pieces. For all pending commands,
884 * free any internal data structures, and basically clear things
885 * out. We do not try and restart any commands or anything -
886 * the strategy handler takes care of that crap.
887 */
2906b3ce 888 shost_printk(KERN_WARNING, cmd->device->host, "Sent BUS RESET to scsi host %d\n", cmd->device->host->host_no);
1da177e4
LT
889
890 for (i = 0; i < AHA1542_MAILBOXES; i++) {
55b28f9f
OZ
891 if (aha1542->int_cmds[i] != NULL) {
892 struct scsi_cmnd *tmp_cmd;
893 tmp_cmd = aha1542->int_cmds[i];
1da177e4 894
55b28f9f 895 if (tmp_cmd->device->soft_reset) {
1da177e4
LT
896 /*
897 * If this device implements the soft reset option,
898 * then it is still holding onto the command, and
899 * may yet complete it. In this case, we don't
900 * flush the data.
901 */
902 continue;
903 }
55b28f9f
OZ
904 kfree(tmp_cmd->host_scribble);
905 tmp_cmd->host_scribble = NULL;
906 aha1542->int_cmds[i] = NULL;
e98878f7 907 aha1542->mb[i].status = 0;
1da177e4
LT
908 }
909 }
910
1b0224b0 911 spin_unlock_irqrestore(sh->host_lock, flags);
1da177e4 912 return SUCCESS;
1da177e4
LT
913}
914
55b28f9f 915static int aha1542_bus_reset(struct scsi_cmnd *cmd)
1da177e4 916{
55b28f9f 917 return aha1542_reset(cmd, SCRST);
8537cba8 918}
1da177e4 919
55b28f9f 920static int aha1542_host_reset(struct scsi_cmnd *cmd)
8537cba8 921{
55b28f9f 922 return aha1542_reset(cmd, HRST | SCRST);
1da177e4
LT
923}
924
1da177e4 925static int aha1542_biosparam(struct scsi_device *sdev,
17787a09 926 struct block_device *bdev, sector_t capacity, int geom[])
1da177e4 927{
e98878f7 928 struct aha1542_hostdata *aha1542 = shost_priv(sdev->host);
1da177e4 929
17787a09
OZ
930 if (capacity >= 0x200000 &&
931 aha1542->bios_translation == BIOS_TRANSLATION_25563) {
1da177e4 932 /* Please verify that this is the same as what DOS returns */
17787a09
OZ
933 geom[0] = 255; /* heads */
934 geom[1] = 63; /* sectors */
1da177e4 935 } else {
17787a09
OZ
936 geom[0] = 64; /* heads */
937 geom[1] = 32; /* sectors */
1da177e4 938 }
17787a09 939 geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */
1da177e4
LT
940
941 return 0;
942}
943MODULE_LICENSE("GPL");
944
d0be4a7d 945static struct scsi_host_template driver_template = {
643a7c43 946 .module = THIS_MODULE,
1da177e4
LT
947 .proc_name = "aha1542",
948 .name = "Adaptec 1542",
1da177e4 949 .queuecommand = aha1542_queuecommand,
1da177e4
LT
950 .eh_device_reset_handler= aha1542_dev_reset,
951 .eh_bus_reset_handler = aha1542_bus_reset,
952 .eh_host_reset_handler = aha1542_host_reset,
953 .bios_param = aha1542_biosparam,
954 .can_queue = AHA1542_MAILBOXES,
955 .this_id = 7,
10be6250
OZ
956 .sg_tablesize = 16,
957 .cmd_per_lun = 1,
1da177e4
LT
958 .unchecked_isa_dma = 1,
959 .use_clustering = ENABLE_CLUSTERING,
960};
643a7c43
OZ
961
962static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
963{
964 struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev);
965
966 if (!sh)
967 return 0;
968
969 dev_set_drvdata(pdev, sh);
970 return 1;
971}
972
973static int aha1542_isa_remove(struct device *pdev,
974 unsigned int ndev)
975{
976 aha1542_release(dev_get_drvdata(pdev));
977 dev_set_drvdata(pdev, NULL);
978 return 0;
979}
980
981static struct isa_driver aha1542_isa_driver = {
982 .match = aha1542_isa_match,
983 .remove = aha1542_isa_remove,
984 .driver = {
985 .name = "aha1542"
986 },
987};
988static int isa_registered;
989
990#ifdef CONFIG_PNP
991static struct pnp_device_id aha1542_pnp_ids[] = {
992 { .id = "ADP1542" },
993 { .id = "" }
994};
995MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids);
996
997static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
998{
999 int indx;
1000 struct Scsi_Host *sh;
1001
f71429ab
OZ
1002 for (indx = 0; indx < ARRAY_SIZE(io); indx++) {
1003 if (io[indx])
643a7c43
OZ
1004 continue;
1005
1006 if (pnp_activate_dev(pdev) < 0)
1007 continue;
1008
f71429ab 1009 io[indx] = pnp_port_start(pdev, 0);
643a7c43
OZ
1010
1011 /* The card can be queried for its DMA, we have
1012 the DMA set up that is enough */
1013
2906b3ce 1014 dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]);
643a7c43
OZ
1015 }
1016
1017 sh = aha1542_hw_init(&driver_template, &pdev->dev, indx);
1018 if (!sh)
1019 return -ENODEV;
1020
1021 pnp_set_drvdata(pdev, sh);
1022 return 0;
1023}
1024
1025static void aha1542_pnp_remove(struct pnp_dev *pdev)
1026{
1027 aha1542_release(pnp_get_drvdata(pdev));
1028 pnp_set_drvdata(pdev, NULL);
1029}
1030
1031static struct pnp_driver aha1542_pnp_driver = {
1032 .name = "aha1542",
1033 .id_table = aha1542_pnp_ids,
1034 .probe = aha1542_pnp_probe,
1035 .remove = aha1542_pnp_remove,
1036};
1037static int pnp_registered;
1038#endif /* CONFIG_PNP */
1039
1040static int __init aha1542_init(void)
1041{
1042 int ret = 0;
643a7c43
OZ
1043
1044#ifdef CONFIG_PNP
1045 if (isapnp) {
1046 ret = pnp_register_driver(&aha1542_pnp_driver);
1047 if (!ret)
1048 pnp_registered = 1;
1049 }
1050#endif
1051 ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS);
1052 if (!ret)
1053 isa_registered = 1;
1054
1055#ifdef CONFIG_PNP
1056 if (pnp_registered)
1057 ret = 0;
1058#endif
1059 if (isa_registered)
1060 ret = 0;
1061
1062 return ret;
1063}
1064
1065static void __exit aha1542_exit(void)
1066{
1067#ifdef CONFIG_PNP
1068 if (pnp_registered)
1069 pnp_unregister_driver(&aha1542_pnp_driver);
1070#endif
1071 if (isa_registered)
1072 isa_unregister_driver(&aha1542_isa_driver);
1073}
1074
1075module_init(aha1542_init);
1076module_exit(aha1542_exit);