From 4df4db5c6c6daeb10a8693d09ce872bce8cd84e6 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 5 Feb 2007 16:28:29 -0800 Subject: [PATCH] [TC] dec_esp: Driver model for the PMAZ-A This is a set of changes that converts the PMAZ-A support to the driver model. The use of the driver model required switching to the hotplug SCSI initialization model, which in turn required a change to the core NCR53C9x driver. I decided not to break all the frontend drivers and introduced an additional parameter for esp_allocate() to select between the old and the new model. I hope this is OK, but I would be fine with converting NCR53C9x to the new model unconditionally as long as I do not have to fix all the other frontends (OK, perhaps I could do some of them ;-) ). Signed-off-by: Maciej W. Rozycki Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Ralf Baechle --- drivers/scsi/NCR53C9x.c | 8 +- drivers/scsi/NCR53C9x.h | 2 +- drivers/scsi/blz1230.c | 3 +- drivers/scsi/blz2060.c | 2 +- drivers/scsi/cyberstorm.c | 2 +- drivers/scsi/cyberstormII.c | 2 +- drivers/scsi/dec_esp.c | 355 +++++++++++++++++++++++------------- drivers/scsi/fastlane.c | 2 +- drivers/scsi/jazz_esp.c | 2 +- drivers/scsi/mac_esp.c | 2 +- drivers/scsi/mca_53c9x.c | 2 +- drivers/scsi/oktagon_esp.c | 2 +- drivers/scsi/sun3x_esp.c | 2 +- 13 files changed, 250 insertions(+), 136 deletions(-) diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 3c912ee29d..8b5334c56f 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -528,12 +528,16 @@ void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs) /* Allocate structure and insert basic data such as SCSI chip frequency * data and a pointer to the device */ -struct NCR_ESP* esp_allocate(struct scsi_host_template *tpnt, void *esp_dev) +struct NCR_ESP* esp_allocate(struct scsi_host_template *tpnt, void *esp_dev, + int hotplug) { struct NCR_ESP *esp, *elink; struct Scsi_Host *esp_host; - esp_host = scsi_register(tpnt, sizeof(struct NCR_ESP)); + if (hotplug) + esp_host = scsi_host_alloc(tpnt, sizeof(struct NCR_ESP)); + else + esp_host = scsi_register(tpnt, sizeof(struct NCR_ESP)); if(!esp_host) panic("Cannot register ESP SCSI host"); esp = (struct NCR_ESP *) esp_host->hostdata; diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h index 521e3f842c..d85cb73a9f 100644 --- a/drivers/scsi/NCR53C9x.h +++ b/drivers/scsi/NCR53C9x.h @@ -652,7 +652,7 @@ extern int nesps, esps_in_use, esps_running; /* External functions */ extern void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs); -extern struct NCR_ESP *esp_allocate(struct scsi_host_template *, void *); +extern struct NCR_ESP *esp_allocate(struct scsi_host_template *, void *, int); extern void esp_deallocate(struct NCR_ESP *); extern void esp_release(void); extern void esp_initialize(struct NCR_ESP *); diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c index 329a8f297b..23f7c24ab8 100644 --- a/drivers/scsi/blz1230.c +++ b/drivers/scsi/blz1230.c @@ -121,7 +121,8 @@ int __init blz1230_esp_detect(struct scsi_host_template *tpnt) */ address = ZTWO_VADDR(board); eregs = (struct ESP_regs *)(address + REAL_BLZ1230_ESP_ADDR); - esp = esp_allocate(tpnt, (void *)board+REAL_BLZ1230_ESP_ADDR); + esp = esp_allocate(tpnt, (void *)board + REAL_BLZ1230_ESP_ADDR, + 0); esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7)); udelay(5); diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c index b6c137b973..b6203ec009 100644 --- a/drivers/scsi/blz2060.c +++ b/drivers/scsi/blz2060.c @@ -100,7 +100,7 @@ int __init blz2060_esp_detect(struct scsi_host_template *tpnt) unsigned long board = z->resource.start; if (request_mem_region(board+BLZ2060_ESP_ADDR, sizeof(struct ESP_regs), "NCR53C9x")) { - esp = esp_allocate(tpnt, (void *)board+BLZ2060_ESP_ADDR); + esp = esp_allocate(tpnt, (void *)board + BLZ2060_ESP_ADDR, 0); /* Do command transfer with programmed I/O */ esp->do_pio_cmds = 1; diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c index 7c7cfb54e8..c6b98a42e8 100644 --- a/drivers/scsi/cyberstorm.c +++ b/drivers/scsi/cyberstorm.c @@ -126,7 +126,7 @@ int __init cyber_esp_detect(struct scsi_host_template *tpnt) sizeof(struct ESP_regs)); return 0; } - esp = esp_allocate(tpnt, (void *)board+CYBER_ESP_ADDR); + esp = esp_allocate(tpnt, (void *)board + CYBER_ESP_ADDR, 0); /* Do command transfer with programmed I/O */ esp->do_pio_cmds = 1; diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c index d88cb9cf09..e336e853e6 100644 --- a/drivers/scsi/cyberstormII.c +++ b/drivers/scsi/cyberstormII.c @@ -98,7 +98,7 @@ int __init cyberII_esp_detect(struct scsi_host_template *tpnt) address = (unsigned long)ZTWO_VADDR(board); eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR); - esp = esp_allocate(tpnt, (void *)board+CYBERII_ESP_ADDR); + esp = esp_allocate(tpnt, (void *)board + CYBERII_ESP_ADDR, 0); esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7)); udelay(5); diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c index c29ccbc446..d42ad663ff 100644 --- a/drivers/scsi/dec_esp.c +++ b/drivers/scsi/dec_esp.c @@ -18,7 +18,7 @@ * 20001005 - Initialization fixes for 2.4.0-test9 * Florian Lohoff * - * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki + * Copyright (C) 2002, 2003, 2005, 2006 Maciej W. Rozycki */ #include @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #define DEC_SCSI_SREG 0 #define DEC_SCSI_DMAREG 0x40000 @@ -98,51 +98,33 @@ static irqreturn_t scsi_dma_merr_int(int, void *); static irqreturn_t scsi_dma_err_int(int, void *); static irqreturn_t scsi_dma_int(int, void *); -static int dec_esp_detect(struct scsi_host_template * tpnt); - -static int dec_esp_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); - return 0; -} - -static struct scsi_host_template driver_template = { - .proc_name = "dec_esp", - .proc_info = esp_proc_info, +static struct scsi_host_template dec_esp_template = { + .module = THIS_MODULE, .name = "NCR53C94", - .detect = dec_esp_detect, - .slave_alloc = esp_slave_alloc, - .slave_destroy = esp_slave_destroy, - .release = dec_esp_release, .info = esp_info, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, + .proc_info = esp_proc_info, + .proc_name = "dec_esp", .can_queue = 7, - .this_id = 7, .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, }; - -#include "scsi_module.c" +static struct NCR_ESP *dec_esp_platform; /***************************************************************** Detection */ -static int dec_esp_detect(struct scsi_host_template * tpnt) +static int dec_esp_platform_probe(void) { struct NCR_ESP *esp; - struct ConfigDev *esp_dev; - int slot; - unsigned long mem_start; + int err = 0; if (IOASIC) { - esp_dev = 0; - esp = esp_allocate(tpnt, (void *) esp_dev); + esp = esp_allocate(&dec_esp_template, NULL, 1); /* Do command transfer with programmed I/O */ esp->do_pio_cmds = 1; @@ -200,112 +182,175 @@ static int dec_esp_detect(struct scsi_host_template * tpnt) /* Check for differential SCSI-bus */ esp->diff = 0; + err = request_irq(esp->irq, esp_intr, IRQF_DISABLED, + "ncr53c94", esp->ehost); + if (err) + goto err_alloc; + err = request_irq(dec_interrupt[DEC_IRQ_ASC_MERR], + scsi_dma_merr_int, IRQF_DISABLED, + "ncr53c94 error", esp->ehost); + if (err) + goto err_irq; + err = request_irq(dec_interrupt[DEC_IRQ_ASC_ERR], + scsi_dma_err_int, IRQF_DISABLED, + "ncr53c94 overrun", esp->ehost); + if (err) + goto err_irq_merr; + err = request_irq(dec_interrupt[DEC_IRQ_ASC_DMA], scsi_dma_int, + IRQF_DISABLED, "ncr53c94 dma", esp->ehost); + if (err) + goto err_irq_err; + esp_initialize(esp); - if (request_irq(esp->irq, esp_intr, IRQF_DISABLED, - "ncr53c94", esp->ehost)) - goto err_dealloc; - if (request_irq(dec_interrupt[DEC_IRQ_ASC_MERR], - scsi_dma_merr_int, IRQF_DISABLED, - "ncr53c94 error", esp->ehost)) - goto err_free_irq; - if (request_irq(dec_interrupt[DEC_IRQ_ASC_ERR], - scsi_dma_err_int, IRQF_DISABLED, - "ncr53c94 overrun", esp->ehost)) - goto err_free_irq_merr; - if (request_irq(dec_interrupt[DEC_IRQ_ASC_DMA], - scsi_dma_int, IRQF_DISABLED, - "ncr53c94 dma", esp->ehost)) - goto err_free_irq_err; + err = scsi_add_host(esp->ehost, NULL); + if (err) { + printk(KERN_ERR "ESP: Unable to register adapter\n"); + goto err_irq_dma; + } + + scsi_scan_host(esp->ehost); + dec_esp_platform = esp; } - if (TURBOCHANNEL) { - while ((slot = search_tc_card("PMAZ-AA")) >= 0) { - claim_tc_card(slot); - - esp_dev = 0; - esp = esp_allocate(tpnt, (void *) esp_dev); - - mem_start = get_tc_base_addr(slot); - - /* Store base addr into esp struct */ - esp->slot = CPHYSADDR(mem_start); - - esp->dregs = 0; - esp->eregs = (void *)CKSEG1ADDR(mem_start + - DEC_SCSI_SREG); - esp->do_pio_cmds = 1; - - /* Set the command buffer */ - esp->esp_command = (volatile unsigned char *) pmaz_cmd_buffer; - - /* get virtual dma address for command buffer */ - esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer); - - esp->cfreq = get_tc_speed(); - - esp->irq = get_tc_irq_nr(slot); - - /* Required functions */ - esp->dma_bytes_sent = &dma_bytes_sent; - esp->dma_can_transfer = &dma_can_transfer; - esp->dma_dump_state = &dma_dump_state; - esp->dma_init_read = &pmaz_dma_init_read; - esp->dma_init_write = &pmaz_dma_init_write; - esp->dma_ints_off = &pmaz_dma_ints_off; - esp->dma_ints_on = &pmaz_dma_ints_on; - esp->dma_irq_p = &dma_irq_p; - esp->dma_ports_p = &dma_ports_p; - esp->dma_setup = &pmaz_dma_setup; - - /* Optional functions */ - esp->dma_barrier = 0; - esp->dma_drain = &pmaz_dma_drain; - esp->dma_invalidate = 0; - esp->dma_irq_entry = 0; - esp->dma_irq_exit = 0; - esp->dma_poll = 0; - esp->dma_reset = 0; - esp->dma_led_off = 0; - esp->dma_led_on = 0; - - esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one; - esp->dma_mmu_get_scsi_sgl = 0; - esp->dma_mmu_release_scsi_one = 0; - esp->dma_mmu_release_scsi_sgl = 0; - esp->dma_advance_sg = 0; - - if (request_irq(esp->irq, esp_intr, IRQF_DISABLED, - "PMAZ_AA", esp->ehost)) { - esp_deallocate(esp); - release_tc_card(slot); - continue; - } - esp->scsi_id = 7; - esp->diff = 0; - esp_initialize(esp); - } + return 0; + +err_irq_dma: + free_irq(dec_interrupt[DEC_IRQ_ASC_DMA], esp->ehost); +err_irq_err: + free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], esp->ehost); +err_irq_merr: + free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], esp->ehost); +err_irq: + free_irq(esp->irq, esp->ehost); +err_alloc: + esp_deallocate(esp); + scsi_host_put(esp->ehost); + return err; +} + +static int __init dec_esp_probe(struct device *dev) +{ + struct NCR_ESP *esp; + resource_size_t start, len; + int err; + + esp = esp_allocate(&dec_esp_template, NULL, 1); + + dev_set_drvdata(dev, esp); + + start = to_tc_dev(dev)->resource.start; + len = to_tc_dev(dev)->resource.end - start + 1; + + if (!request_mem_region(start, len, dev->bus_id)) { + printk(KERN_ERR "%s: Unable to reserve MMIO resource\n", + dev->bus_id); + err = -EBUSY; + goto err_alloc; } - if(nesps) { - printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); - esps_running = esps_in_use; - return esps_in_use; + /* Store base addr into esp struct. */ + esp->slot = start; + + esp->dregs = 0; + esp->eregs = (void *)CKSEG1ADDR(start + DEC_SCSI_SREG); + esp->do_pio_cmds = 1; + + /* Set the command buffer. */ + esp->esp_command = (volatile unsigned char *)pmaz_cmd_buffer; + + /* Get virtual dma address for command buffer. */ + esp->esp_command_dvma = virt_to_phys(pmaz_cmd_buffer); + + esp->cfreq = tc_get_speed(to_tc_dev(dev)->bus); + + esp->irq = to_tc_dev(dev)->interrupt; + + /* Required functions. */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &pmaz_dma_init_read; + esp->dma_init_write = &pmaz_dma_init_write; + esp->dma_ints_off = &pmaz_dma_ints_off; + esp->dma_ints_on = &pmaz_dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &pmaz_dma_setup; + + /* Optional functions. */ + esp->dma_barrier = 0; + esp->dma_drain = &pmaz_dma_drain; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_poll = 0; + esp->dma_reset = 0; + esp->dma_led_off = 0; + esp->dma_led_on = 0; + + esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one; + esp->dma_mmu_get_scsi_sgl = 0; + esp->dma_mmu_release_scsi_one = 0; + esp->dma_mmu_release_scsi_sgl = 0; + esp->dma_advance_sg = 0; + + err = request_irq(esp->irq, esp_intr, IRQF_DISABLED, "PMAZ_AA", + esp->ehost); + if (err) { + printk(KERN_ERR "%s: Unable to get IRQ %d\n", + dev->bus_id, esp->irq); + goto err_resource; + } + + esp->scsi_id = 7; + esp->diff = 0; + esp_initialize(esp); + + err = scsi_add_host(esp->ehost, dev); + if (err) { + printk(KERN_ERR "%s: Unable to register adapter\n", + dev->bus_id); + goto err_irq; } + + scsi_scan_host(esp->ehost); + return 0; -err_free_irq_err: - free_irq(dec_interrupt[DEC_IRQ_ASC_ERR], scsi_dma_err_int); -err_free_irq_merr: - free_irq(dec_interrupt[DEC_IRQ_ASC_MERR], scsi_dma_merr_int); -err_free_irq: - free_irq(esp->irq, esp_intr); -err_dealloc: +err_irq: + free_irq(esp->irq, esp->ehost); + +err_resource: + release_mem_region(start, len); + +err_alloc: esp_deallocate(esp); - return 0; + scsi_host_put(esp->ehost); + return err; +} + +static void __exit dec_esp_platform_remove(void) +{ + struct NCR_ESP *esp = dec_esp_platform; + + free_irq(esp->irq, esp->ehost); + esp_deallocate(esp); + scsi_host_put(esp->ehost); + dec_esp_platform = NULL; } +static void __exit dec_esp_remove(struct device *dev) +{ + struct NCR_ESP *esp = dev_get_drvdata(dev); + + free_irq(esp->irq, esp->ehost); + esp_deallocate(esp); + scsi_host_put(esp->ehost); +} + + /************************************************************* DMA Functions */ static irqreturn_t scsi_dma_merr_int(int irq, void *dev_id) { @@ -576,3 +621,67 @@ static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, struct scsi_cmnd * sp { sp->SCp.ptr = (char *)virt_to_phys(sp->request_buffer); } + + +#ifdef CONFIG_TC +static int __init dec_esp_tc_probe(struct device *dev); +static int __exit dec_esp_tc_remove(struct device *dev); + +static const struct tc_device_id dec_esp_tc_table[] = { + { "DEC ", "PMAZ-AA " }, + { } +}; +MODULE_DEVICE_TABLE(tc, dec_esp_tc_table); + +static struct tc_driver dec_esp_tc_driver = { + .id_table = dec_esp_tc_table, + .driver = { + .name = "dec_esp", + .bus = &tc_bus_type, + .probe = dec_esp_tc_probe, + .remove = __exit_p(dec_esp_tc_remove), + }, +}; + +static int __init dec_esp_tc_probe(struct device *dev) +{ + int status = dec_esp_probe(dev); + if (!status) + get_device(dev); + return status; +} + +static int __exit dec_esp_tc_remove(struct device *dev) +{ + put_device(dev); + dec_esp_remove(dev); + return 0; +} +#endif + +static int __init dec_esp_init(void) +{ + int status; + + status = tc_register_driver(&dec_esp_tc_driver); + if (!status) + dec_esp_platform_probe(); + + if (nesps) { + pr_info("ESP: Total of %d ESP hosts found, " + "%d actually in use.\n", nesps, esps_in_use); + esps_running = esps_in_use; + } + + return status; +} + +static void __exit dec_esp_exit(void) +{ + dec_esp_platform_remove(); + tc_unregister_driver(&dec_esp_tc_driver); +} + + +module_init(dec_esp_init); +module_exit(dec_esp_exit); diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c index 2a1c5c22b9..4266a2139b 100644 --- a/drivers/scsi/fastlane.c +++ b/drivers/scsi/fastlane.c @@ -142,7 +142,7 @@ int __init fastlane_esp_detect(struct scsi_host_template *tpnt) if (board < 0x1000000) { goto err_release; } - esp = esp_allocate(tpnt, (void *)board+FASTLANE_ESP_ADDR); + esp = esp_allocate(tpnt, (void *)board + FASTLANE_ESP_ADDR, 0); /* Do command transfer with programmed I/O */ esp->do_pio_cmds = 1; diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index bfac4441d8..19dd4b962e 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -75,7 +75,7 @@ static int jazz_esp_detect(struct scsi_host_template *tpnt) */ if (1) { esp_dev = NULL; - esp = esp_allocate(tpnt, (void *) esp_dev); + esp = esp_allocate(tpnt, esp_dev, 0); /* Do command transfer with programmed I/O */ esp->do_pio_cmds = 1; diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 3586fac9be..bcb49021b7 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -351,7 +351,7 @@ int mac_esp_detect(struct scsi_host_template * tpnt) for (chipnum = 0; chipnum < chipspresent; chipnum ++) { struct NCR_ESP * esp; - esp = esp_allocate(tpnt, (void *) NULL); + esp = esp_allocate(tpnt, NULL, 0); esp->eregs = (struct ESP_regs *) get_base(chipnum); esp->dma_irq_p = &esp_dafb_dma_irq_p; diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c index 998a8bbc1a..d693d0f213 100644 --- a/drivers/scsi/mca_53c9x.c +++ b/drivers/scsi/mca_53c9x.c @@ -122,7 +122,7 @@ static int mca_esp_detect(struct scsi_host_template *tpnt) if ((slot = mca_find_adapter(*id_to_check, 0)) != MCA_NOTFOUND) { - esp = esp_allocate(tpnt, (void *) NULL); + esp = esp_allocate(tpnt, NULL, 0); pos[0] = mca_read_stored_pos(slot, 2); pos[1] = mca_read_stored_pos(slot, 3); diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c index c116a6ae3c..26a6d55faf 100644 --- a/drivers/scsi/oktagon_esp.c +++ b/drivers/scsi/oktagon_esp.c @@ -133,7 +133,7 @@ int oktagon_esp_detect(struct scsi_host_template *tpnt) eregs = (struct ESP_regs *)(address + OKTAGON_ESP_ADDR); /* This line was 5 lines lower */ - esp = esp_allocate(tpnt, (void *)board+OKTAGON_ESP_ADDR); + esp = esp_allocate(tpnt, (void *)board + OKTAGON_ESP_ADDR, 0); /* we have to shift the registers only one bit for oktagon */ esp->shift = 1; diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index 6b60536ac9..80fb3f88af 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -53,7 +53,7 @@ int sun3x_esp_detect(struct scsi_host_template *tpnt) struct ConfigDev *esp_dev; esp_dev = 0; - esp = esp_allocate(tpnt, (void *) esp_dev); + esp = esp_allocate(tpnt, esp_dev, 0); /* Do command transfer with DMA */ esp->do_pio_cmds = 0; -- 2.39.5