0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <asm/io.h>
0027 #include <linux/blkdev.h>
0028 #include <linux/module.h>
0029 #include <scsi/scsi_host.h>
0030 #include <linux/init.h>
0031 #include <linux/ioport.h>
0032 #include <linux/isa.h>
0033 #include <linux/pnp.h>
0034 #include <linux/interrupt.h>
0035
0036
0037
0038 #define NCR5380_read(reg) \
0039 ioread8(hostdata->io + hostdata->offset + (reg))
0040 #define NCR5380_write(reg, value) \
0041 iowrite8(value, hostdata->io + hostdata->offset + (reg))
0042
0043 #define NCR5380_implementation_fields \
0044 int offset; \
0045 int c400_ctl_status; \
0046 int c400_blk_cnt; \
0047 int c400_host_buf; \
0048 int io_width; \
0049 int pdma_residual; \
0050 int board
0051
0052 #define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len
0053 #define NCR5380_dma_recv_setup generic_NCR5380_precv
0054 #define NCR5380_dma_send_setup generic_NCR5380_psend
0055 #define NCR5380_dma_residual generic_NCR5380_dma_residual
0056
0057 #define NCR5380_intr generic_NCR5380_intr
0058 #define NCR5380_queue_command generic_NCR5380_queue_command
0059 #define NCR5380_abort generic_NCR5380_abort
0060 #define NCR5380_host_reset generic_NCR5380_host_reset
0061 #define NCR5380_info generic_NCR5380_info
0062
0063 #define NCR5380_io_delay(x) udelay(x)
0064
0065 #include "NCR5380.h"
0066
0067 #define DRV_MODULE_NAME "g_NCR5380"
0068
0069 #define NCR53C400_mem_base 0x3880
0070 #define NCR53C400_host_buffer 0x3900
0071 #define NCR53C400_region_size 0x3a00
0072
0073 #define BOARD_NCR5380 0
0074 #define BOARD_NCR53C400 1
0075 #define BOARD_NCR53C400A 2
0076 #define BOARD_DTC3181E 3
0077 #define BOARD_HP_C2502 4
0078
0079 #define IRQ_AUTO 254
0080
0081 #define MAX_CARDS 8
0082 #define DMA_MAX_SIZE 32768
0083
0084
0085 static int ncr_irq = -1;
0086 static int ncr_addr;
0087 static int ncr_5380;
0088 static int ncr_53c400;
0089 static int ncr_53c400a;
0090 static int dtc_3181e;
0091 static int hp_c2502;
0092 module_param_hw(ncr_irq, int, irq, 0);
0093 module_param_hw(ncr_addr, int, ioport, 0);
0094 module_param(ncr_5380, int, 0);
0095 module_param(ncr_53c400, int, 0);
0096 module_param(ncr_53c400a, int, 0);
0097 module_param(dtc_3181e, int, 0);
0098 module_param(hp_c2502, int, 0);
0099
0100 static int irq[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
0101 module_param_hw_array(irq, int, irq, NULL, 0);
0102 MODULE_PARM_DESC(irq, "IRQ number(s) (0=none, 254=auto [default])");
0103
0104 static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
0105 module_param_hw_array(base, int, ioport, NULL, 0);
0106 MODULE_PARM_DESC(base, "base address(es)");
0107
0108 static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
0109 module_param_array(card, int, NULL, 0);
0110 MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)");
0111
0112 MODULE_ALIAS("g_NCR5380_mmio");
0113 MODULE_LICENSE("GPL");
0114
0115 static void g_NCR5380_trigger_irq(struct Scsi_Host *instance)
0116 {
0117 struct NCR5380_hostdata *hostdata = shost_priv(instance);
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 NCR5380_write(TARGET_COMMAND_REG,
0128 PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
0129 NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
0130 NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
0131 NCR5380_write(INITIATOR_COMMAND_REG,
0132 ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
0133
0134 msleep(1);
0135
0136 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
0137 NCR5380_write(SELECT_ENABLE_REG, 0);
0138 NCR5380_write(TARGET_COMMAND_REG, 0);
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 static int g_NCR5380_probe_irq(struct Scsi_Host *instance)
0150 {
0151 struct NCR5380_hostdata *hostdata = shost_priv(instance);
0152 int irq_mask, irq;
0153
0154 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
0155 irq_mask = probe_irq_on();
0156 g_NCR5380_trigger_irq(instance);
0157 irq = probe_irq_off(irq_mask);
0158 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
0159
0160 if (irq <= 0)
0161 return NO_IRQ;
0162 return irq;
0163 }
0164
0165
0166
0167
0168
0169 static void magic_configure(int idx, u8 irq, u8 magic[])
0170 {
0171 u8 cfg = 0;
0172
0173 outb(magic[0], 0x779);
0174 outb(magic[1], 0x379);
0175 outb(magic[2], 0x379);
0176 outb(magic[3], 0x379);
0177 outb(magic[4], 0x379);
0178
0179 if (irq == 9)
0180 irq = 2;
0181
0182 if (idx >= 0 && idx <= 7)
0183 cfg = 0x80 | idx | (irq << 4);
0184 outb(cfg, 0x379);
0185 }
0186
0187 static irqreturn_t legacy_empty_irq_handler(int irq, void *dev_id)
0188 {
0189 return IRQ_HANDLED;
0190 }
0191
0192 static int legacy_find_free_irq(int *irq_table)
0193 {
0194 while (*irq_table != -1) {
0195 if (!request_irq(*irq_table, legacy_empty_irq_handler,
0196 IRQF_PROBE_SHARED, "Test IRQ",
0197 (void *)irq_table)) {
0198 free_irq(*irq_table, (void *) irq_table);
0199 return *irq_table;
0200 }
0201 irq_table++;
0202 }
0203 return -1;
0204 }
0205
0206 static unsigned int ncr_53c400a_ports[] = {
0207 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
0208 };
0209 static unsigned int dtc_3181e_ports[] = {
0210 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
0211 };
0212 static u8 ncr_53c400a_magic[] = {
0213 0x59, 0xb9, 0xc5, 0xae, 0xa6
0214 };
0215 static u8 hp_c2502_magic[] = {
0216 0x0f, 0x22, 0xf0, 0x20, 0x80
0217 };
0218 static int hp_c2502_irqs[] = {
0219 9, 5, 7, 3, 4, -1
0220 };
0221
0222 static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
0223 struct device *pdev, int base, int irq, int board)
0224 {
0225 bool is_pmio = base <= 0xffff;
0226 int ret;
0227 int flags = 0;
0228 unsigned int *ports = NULL;
0229 u8 *magic = NULL;
0230 int i;
0231 int port_idx = -1;
0232 unsigned long region_size;
0233 struct Scsi_Host *instance;
0234 struct NCR5380_hostdata *hostdata;
0235 u8 __iomem *iomem;
0236
0237 switch (board) {
0238 case BOARD_NCR5380:
0239 flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP;
0240 break;
0241 case BOARD_NCR53C400A:
0242 ports = ncr_53c400a_ports;
0243 magic = ncr_53c400a_magic;
0244 break;
0245 case BOARD_HP_C2502:
0246 ports = ncr_53c400a_ports;
0247 magic = hp_c2502_magic;
0248 break;
0249 case BOARD_DTC3181E:
0250 ports = dtc_3181e_ports;
0251 magic = ncr_53c400a_magic;
0252 break;
0253 }
0254
0255 if (is_pmio && ports && magic) {
0256
0257
0258
0259 magic_configure(-1, 0, magic);
0260
0261 region_size = 16;
0262 if (base)
0263 for (i = 0; ports[i]; i++) {
0264 if (base == ports[i]) {
0265 if (!request_region(ports[i],
0266 region_size,
0267 "ncr53c80"))
0268 return -EBUSY;
0269 break;
0270 }
0271 }
0272 else
0273 for (i = 0; ports[i]; i++) {
0274 if (!request_region(ports[i], region_size,
0275 "ncr53c80"))
0276 continue;
0277 if (inb(ports[i]) == 0xff)
0278 break;
0279 release_region(ports[i], region_size);
0280 }
0281 if (ports[i]) {
0282
0283 magic_configure(i, 0, magic);
0284 base = ports[i];
0285 outb(0xc0, base + 9);
0286 if (inb(base + 9) != 0x80) {
0287 ret = -ENODEV;
0288 goto out_release;
0289 }
0290 port_idx = i;
0291 } else
0292 return -EINVAL;
0293 } else if (is_pmio) {
0294
0295 region_size = 8;
0296 if (!base || !request_region(base, region_size, "ncr5380"))
0297 return -EBUSY;
0298 } else {
0299 region_size = NCR53C400_region_size;
0300 if (!request_mem_region(base, region_size, "ncr5380"))
0301 return -EBUSY;
0302 }
0303
0304 if (is_pmio)
0305 iomem = ioport_map(base, region_size);
0306 else
0307 iomem = ioremap(base, region_size);
0308
0309 if (!iomem) {
0310 ret = -ENOMEM;
0311 goto out_release;
0312 }
0313
0314 instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
0315 if (instance == NULL) {
0316 ret = -ENOMEM;
0317 goto out_unmap;
0318 }
0319 hostdata = shost_priv(instance);
0320
0321 hostdata->board = board;
0322 hostdata->io = iomem;
0323 hostdata->region_size = region_size;
0324
0325 if (is_pmio) {
0326 hostdata->io_port = base;
0327 hostdata->io_width = 1;
0328 hostdata->offset = 0;
0329
0330
0331
0332
0333
0334 switch (board) {
0335 case BOARD_NCR53C400:
0336 hostdata->io_port += 8;
0337 hostdata->c400_ctl_status = 0;
0338 hostdata->c400_blk_cnt = 1;
0339 hostdata->c400_host_buf = 4;
0340 break;
0341 case BOARD_DTC3181E:
0342 hostdata->io_width = 2;
0343 fallthrough;
0344 case BOARD_NCR53C400A:
0345 case BOARD_HP_C2502:
0346 hostdata->c400_ctl_status = 9;
0347 hostdata->c400_blk_cnt = 10;
0348 hostdata->c400_host_buf = 8;
0349 break;
0350 }
0351 } else {
0352 hostdata->base = base;
0353 hostdata->offset = NCR53C400_mem_base;
0354 switch (board) {
0355 case BOARD_NCR53C400:
0356 hostdata->c400_ctl_status = 0x100;
0357 hostdata->c400_blk_cnt = 0x101;
0358 hostdata->c400_host_buf = 0x104;
0359 break;
0360 case BOARD_DTC3181E:
0361 case BOARD_NCR53C400A:
0362 case BOARD_HP_C2502:
0363 pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
0364 ret = -EINVAL;
0365 goto out_unregister;
0366 }
0367 }
0368
0369
0370 NCR5380_write(MODE_REG, 0);
0371 if (NCR5380_read(MODE_REG) != 0) {
0372 ret = -ENODEV;
0373 goto out_unregister;
0374 }
0375
0376 ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP);
0377 if (ret)
0378 goto out_unregister;
0379
0380 switch (board) {
0381 case BOARD_NCR53C400:
0382 case BOARD_DTC3181E:
0383 case BOARD_NCR53C400A:
0384 case BOARD_HP_C2502:
0385 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
0386 }
0387
0388 NCR5380_maybe_reset_bus(instance);
0389
0390
0391 if (irq == 255 || irq == 0)
0392 irq = NO_IRQ;
0393 else if (irq == -1)
0394 irq = IRQ_AUTO;
0395
0396 if (board == BOARD_HP_C2502) {
0397 int *irq_table = hp_c2502_irqs;
0398 int board_irq = -1;
0399
0400 switch (irq) {
0401 case NO_IRQ:
0402 board_irq = 0;
0403 break;
0404 case IRQ_AUTO:
0405 board_irq = legacy_find_free_irq(irq_table);
0406 break;
0407 default:
0408 while (*irq_table != -1)
0409 if (*irq_table++ == irq)
0410 board_irq = irq;
0411 }
0412
0413 if (board_irq <= 0) {
0414 board_irq = 0;
0415 irq = NO_IRQ;
0416 }
0417
0418 magic_configure(port_idx, board_irq, magic);
0419 }
0420
0421 if (irq == IRQ_AUTO) {
0422 instance->irq = g_NCR5380_probe_irq(instance);
0423 if (instance->irq == NO_IRQ)
0424 shost_printk(KERN_INFO, instance, "no irq detected\n");
0425 } else {
0426 instance->irq = irq;
0427 if (instance->irq == NO_IRQ)
0428 shost_printk(KERN_INFO, instance, "no irq provided\n");
0429 }
0430
0431 if (instance->irq != NO_IRQ) {
0432 if (request_irq(instance->irq, generic_NCR5380_intr,
0433 0, "NCR5380", instance)) {
0434 instance->irq = NO_IRQ;
0435 shost_printk(KERN_INFO, instance,
0436 "irq %d denied\n", instance->irq);
0437 } else {
0438 shost_printk(KERN_INFO, instance,
0439 "irq %d acquired\n", instance->irq);
0440 }
0441 }
0442
0443 ret = scsi_add_host(instance, pdev);
0444 if (ret)
0445 goto out_free_irq;
0446 scsi_scan_host(instance);
0447 dev_set_drvdata(pdev, instance);
0448 return 0;
0449
0450 out_free_irq:
0451 if (instance->irq != NO_IRQ)
0452 free_irq(instance->irq, instance);
0453 NCR5380_exit(instance);
0454 out_unregister:
0455 scsi_host_put(instance);
0456 out_unmap:
0457 iounmap(iomem);
0458 out_release:
0459 if (is_pmio)
0460 release_region(base, region_size);
0461 else
0462 release_mem_region(base, region_size);
0463 return ret;
0464 }
0465
0466 static void generic_NCR5380_release_resources(struct Scsi_Host *instance)
0467 {
0468 struct NCR5380_hostdata *hostdata = shost_priv(instance);
0469 void __iomem *iomem = hostdata->io;
0470 unsigned long io_port = hostdata->io_port;
0471 unsigned long base = hostdata->base;
0472 unsigned long region_size = hostdata->region_size;
0473
0474 scsi_remove_host(instance);
0475 if (instance->irq != NO_IRQ)
0476 free_irq(instance->irq, instance);
0477 NCR5380_exit(instance);
0478 scsi_host_put(instance);
0479 iounmap(iomem);
0480 if (io_port)
0481 release_region(io_port, region_size);
0482 else
0483 release_mem_region(base, region_size);
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493 static void wait_for_53c80_access(struct NCR5380_hostdata *hostdata)
0494 {
0495 int count = 10000;
0496
0497 do {
0498 if (hostdata->board == BOARD_DTC3181E)
0499 udelay(4);
0500 if (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
0501 return;
0502 } while (--count > 0);
0503
0504 scmd_printk(KERN_ERR, hostdata->connected,
0505 "53c80 registers not accessible, device will be reset\n");
0506 NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
0507 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
0508 }
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519 static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
0520 unsigned char *dst, int len)
0521 {
0522 int residual;
0523 int start = 0;
0524
0525 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
0526 NCR5380_write(hostdata->c400_blk_cnt, len / 128);
0527
0528 do {
0529 if (start == len - 128) {
0530
0531 if (NCR5380_poll_politely(hostdata, hostdata->c400_ctl_status,
0532 CSR_HOST_BUF_NOT_RDY, 0, 0) < 0)
0533 break;
0534 } else {
0535 if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
0536 CSR_HOST_BUF_NOT_RDY, 0,
0537 hostdata->c400_ctl_status,
0538 CSR_GATED_53C80_IRQ,
0539 CSR_GATED_53C80_IRQ, 0) < 0 ||
0540 NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
0541 break;
0542 }
0543
0544 if (hostdata->io_port && hostdata->io_width == 2)
0545 insw(hostdata->io_port + hostdata->c400_host_buf,
0546 dst + start, 64);
0547 else if (hostdata->io_port)
0548 insb(hostdata->io_port + hostdata->c400_host_buf,
0549 dst + start, 128);
0550 else
0551 memcpy_fromio(dst + start,
0552 hostdata->io + NCR53C400_host_buffer, 128);
0553 start += 128;
0554 } while (start < len);
0555
0556 residual = len - start;
0557
0558 if (residual != 0) {
0559
0560 NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
0561 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
0562 }
0563 wait_for_53c80_access(hostdata);
0564
0565 if (residual == 0 && NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
0566 BASR_END_DMA_TRANSFER,
0567 BASR_END_DMA_TRANSFER,
0568 0) < 0)
0569 scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
0570 __func__);
0571
0572 hostdata->pdma_residual = residual;
0573
0574 return 0;
0575 }
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586 static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata,
0587 unsigned char *src, int len)
0588 {
0589 int residual;
0590 int start = 0;
0591
0592 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
0593 NCR5380_write(hostdata->c400_blk_cnt, len / 128);
0594
0595 do {
0596 if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
0597 CSR_HOST_BUF_NOT_RDY, 0,
0598 hostdata->c400_ctl_status,
0599 CSR_GATED_53C80_IRQ,
0600 CSR_GATED_53C80_IRQ, 0) < 0 ||
0601 NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) {
0602
0603 if (start >= 128)
0604 start -= 128;
0605 if (start >= 128)
0606 start -= 128;
0607 break;
0608 }
0609
0610 if (start >= len && NCR5380_read(hostdata->c400_blk_cnt) == 0)
0611 break;
0612
0613 if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
0614
0615 if (start >= 128)
0616 start -= 128;
0617 break;
0618 }
0619
0620 if (start >= len)
0621 continue;
0622
0623 if (hostdata->io_port && hostdata->io_width == 2)
0624 outsw(hostdata->io_port + hostdata->c400_host_buf,
0625 src + start, 64);
0626 else if (hostdata->io_port)
0627 outsb(hostdata->io_port + hostdata->c400_host_buf,
0628 src + start, 128);
0629 else
0630 memcpy_toio(hostdata->io + NCR53C400_host_buffer,
0631 src + start, 128);
0632 start += 128;
0633 } while (1);
0634
0635 residual = len - start;
0636
0637 if (residual != 0) {
0638
0639 NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
0640 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
0641 }
0642 wait_for_53c80_access(hostdata);
0643
0644 if (residual == 0) {
0645 if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
0646 TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT,
0647 0) < 0)
0648 scmd_printk(KERN_ERR, hostdata->connected,
0649 "%s: Last Byte Sent timeout\n", __func__);
0650
0651 if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
0652 BASR_END_DMA_TRANSFER, BASR_END_DMA_TRANSFER,
0653 0) < 0)
0654 scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
0655 __func__);
0656 }
0657
0658 hostdata->pdma_residual = residual;
0659
0660 return 0;
0661 }
0662
0663 static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata,
0664 struct scsi_cmnd *cmd)
0665 {
0666 int transfersize = NCR5380_to_ncmd(cmd)->this_residual;
0667
0668 if (hostdata->flags & FLAG_NO_PSEUDO_DMA)
0669 return 0;
0670
0671
0672 if (transfersize % 128)
0673 return 0;
0674
0675
0676 if (hostdata->board == BOARD_DTC3181E &&
0677 cmd->sc_data_direction == DMA_TO_DEVICE)
0678 transfersize = min(transfersize, 512);
0679
0680 return min(transfersize, DMA_MAX_SIZE);
0681 }
0682
0683 static int generic_NCR5380_dma_residual(struct NCR5380_hostdata *hostdata)
0684 {
0685 return hostdata->pdma_residual;
0686 }
0687
0688
0689
0690 #include "NCR5380.c"
0691
0692 static struct scsi_host_template driver_template = {
0693 .module = THIS_MODULE,
0694 .proc_name = DRV_MODULE_NAME,
0695 .name = "Generic NCR5380/NCR53C400 SCSI",
0696 .info = generic_NCR5380_info,
0697 .queuecommand = generic_NCR5380_queue_command,
0698 .eh_abort_handler = generic_NCR5380_abort,
0699 .eh_host_reset_handler = generic_NCR5380_host_reset,
0700 .can_queue = 16,
0701 .this_id = 7,
0702 .sg_tablesize = SG_ALL,
0703 .cmd_per_lun = 2,
0704 .dma_boundary = PAGE_SIZE - 1,
0705 .cmd_size = sizeof(struct NCR5380_cmd),
0706 .max_sectors = 128,
0707 };
0708
0709 static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev)
0710 {
0711 int ret = generic_NCR5380_init_one(&driver_template, pdev, base[ndev],
0712 irq[ndev], card[ndev]);
0713 if (ret) {
0714 if (base[ndev])
0715 printk(KERN_WARNING "Card not found at address 0x%03x\n",
0716 base[ndev]);
0717 return 0;
0718 }
0719
0720 return 1;
0721 }
0722
0723 static void generic_NCR5380_isa_remove(struct device *pdev,
0724 unsigned int ndev)
0725 {
0726 generic_NCR5380_release_resources(dev_get_drvdata(pdev));
0727 dev_set_drvdata(pdev, NULL);
0728 }
0729
0730 static struct isa_driver generic_NCR5380_isa_driver = {
0731 .match = generic_NCR5380_isa_match,
0732 .remove = generic_NCR5380_isa_remove,
0733 .driver = {
0734 .name = DRV_MODULE_NAME
0735 },
0736 };
0737
0738 #ifdef CONFIG_PNP
0739 static const struct pnp_device_id generic_NCR5380_pnp_ids[] = {
0740 { .id = "DTC436e", .driver_data = BOARD_DTC3181E },
0741 { .id = "" }
0742 };
0743 MODULE_DEVICE_TABLE(pnp, generic_NCR5380_pnp_ids);
0744
0745 static int generic_NCR5380_pnp_probe(struct pnp_dev *pdev,
0746 const struct pnp_device_id *id)
0747 {
0748 int base, irq;
0749
0750 if (pnp_activate_dev(pdev) < 0)
0751 return -EBUSY;
0752
0753 base = pnp_port_start(pdev, 0);
0754 irq = pnp_irq(pdev, 0);
0755
0756 return generic_NCR5380_init_one(&driver_template, &pdev->dev, base, irq,
0757 id->driver_data);
0758 }
0759
0760 static void generic_NCR5380_pnp_remove(struct pnp_dev *pdev)
0761 {
0762 generic_NCR5380_release_resources(pnp_get_drvdata(pdev));
0763 pnp_set_drvdata(pdev, NULL);
0764 }
0765
0766 static struct pnp_driver generic_NCR5380_pnp_driver = {
0767 .name = DRV_MODULE_NAME,
0768 .id_table = generic_NCR5380_pnp_ids,
0769 .probe = generic_NCR5380_pnp_probe,
0770 .remove = generic_NCR5380_pnp_remove,
0771 };
0772 #endif
0773
0774 static int pnp_registered, isa_registered;
0775
0776 static int __init generic_NCR5380_init(void)
0777 {
0778 int ret = 0;
0779
0780
0781 if (irq[0] == -1 && base[0] == 0 && card[0] == -1) {
0782 irq[0] = ncr_irq;
0783 base[0] = ncr_addr;
0784 if (ncr_5380)
0785 card[0] = BOARD_NCR5380;
0786 if (ncr_53c400)
0787 card[0] = BOARD_NCR53C400;
0788 if (ncr_53c400a)
0789 card[0] = BOARD_NCR53C400A;
0790 if (dtc_3181e)
0791 card[0] = BOARD_DTC3181E;
0792 if (hp_c2502)
0793 card[0] = BOARD_HP_C2502;
0794 }
0795
0796 #ifdef CONFIG_PNP
0797 if (!pnp_register_driver(&generic_NCR5380_pnp_driver))
0798 pnp_registered = 1;
0799 #endif
0800 ret = isa_register_driver(&generic_NCR5380_isa_driver, MAX_CARDS);
0801 if (!ret)
0802 isa_registered = 1;
0803
0804 return (pnp_registered || isa_registered) ? 0 : ret;
0805 }
0806
0807 static void __exit generic_NCR5380_exit(void)
0808 {
0809 #ifdef CONFIG_PNP
0810 if (pnp_registered)
0811 pnp_unregister_driver(&generic_NCR5380_pnp_driver);
0812 #endif
0813 if (isa_registered)
0814 isa_unregister_driver(&generic_NCR5380_isa_driver);
0815 }
0816
0817 module_init(generic_NCR5380_init);
0818 module_exit(generic_NCR5380_exit);