/* zorrro_esp.c: ESP front-end for Amiga ZORRO SCSI systems. * * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) * * Copyright (C) 2011 Michael Schmitz (schmitz@debian.org) for * migration to ESP SCSI core */ /* * ZORRO bus code from: */ /* * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. * Amiga MacroSystemUS WarpEngine SCSI controller. * Amiga Technologies/DKB A4091 SCSI controller. * * Written 1997 by Alan Hourihane * plus modifications of the 53c7xx.c driver to support the Amiga. * * Rewritten to use 53c700.c by Kars de Jong */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "esp_scsi.h" MODULE_AUTHOR("Michael Schmitz "); MODULE_DESCRIPTION("Amiga Zorro NCR5C9x (ESP) driver"); MODULE_LICENSE("GPL"); #define DMA_WRITE 0x80000000 static struct zorro_driver_data { const char *name; unsigned long offset; unsigned long dma_offset; int absolute; int zorro3; /* offset is absolute address */ } zorro_esp_driver_data[] = { { .name = "CyberStormI", .offset = 0xf400, .dma_offset = 0xf800, .absolute = 0, .zorro3 = 0 }, { .name = "CyberStormII", .offset = 0x1ff03, .dma_offset = 0x1ff43, .absolute = 0, .zorro3 = 0 }, { .name = "Blizzard 2060", .offset = 0x1ff00, .dma_offset = 0x1ffe0, .absolute = 0, .zorro3 = 0 }, { .name = "Blizzard 1230", .offset = 0x8000, .dma_offset = 0x10000, .absolute = 0, .zorro3 = 0 }, { .name = "Blizzard 1230II", .offset = 0x10000, .dma_offset = 0x10021, .absolute = 0, .zorro3 = 0 }, { .name = "Fastlane", .offset = 0x1000001, .dma_offset = 0x1000041, .absolute = 0, .zorro3 = 1 }, { 0 } }; static struct zorro_device_id zorro_esp_zorro_tbl[] = { { .id = ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, .driver_data = (unsigned long)&zorro_esp_driver_data[0], }, { .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, .driver_data = (unsigned long)&zorro_esp_driver_data[0], }, { .id = ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, .driver_data = (unsigned long)&zorro_esp_driver_data[1], }, { .id = ZORRO_PROD_PHASE5_BLIZZARD_2060, .driver_data = (unsigned long)&zorro_esp_driver_data[2], }, { .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260, .driver_data = (unsigned long)&zorro_esp_driver_data[3], }, { .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, .driver_data = (unsigned long)&zorro_esp_driver_data[4], }, { 0 } }; MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); struct blz1230_dma_registers { volatile unsigned char dma_addr; /* DMA address [0x0000] */ unsigned char dmapad2[0x7fff]; volatile unsigned char dma_latch; /* DMA latch [0x8000] */ }; struct blz2060_dma_registers { volatile unsigned char dma_led_ctrl; /* DMA led control [0x000] */ unsigned char dmapad1[0x0f]; volatile unsigned char dma_addr0; /* DMA address (MSB) [0x010] */ unsigned char dmapad2[0x03]; volatile unsigned char dma_addr1; /* DMA address [0x014] */ unsigned char dmapad3[0x03]; volatile unsigned char dma_addr2; /* DMA address [0x018] */ unsigned char dmapad4[0x03]; volatile unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */ }; /* DMA control bits */ #define BLZ2060_DMA_LED 0x02 /* HD led control 1 = off */ /* * m68k always assumes readl/writel operate on little endian * mmio space; this is wrong at least for Sun3x, so we * need to workaround this until a proper way is found */ #if 0 #define dma_read32(REG) \ readl(esp->dma_regs + (REG)) #define dma_write32(VAL, REG) \ writel((VAL), esp->dma_regs + (REG)) #else #define dma_read32(REG) \ *(volatile u32 *)(esp->dma_regs + (REG)) #define dma_write32(VAL, REG) \ do { *(volatile u32 *)(esp->dma_regs + (REG)) = (VAL); } while (0) #endif /* * On all implementations except for the Oktagon, padding between ESP * registers is three bytes. * On Oktagon, it is one byte - use a different accessor there. * * Oktagon currently unsupported! */ static void zorro_esp_write8(struct esp *esp, u8 val, unsigned long reg) { writeb(val, esp->regs + (reg * 4UL)); } static u8 zorro_esp_read8(struct esp *esp, unsigned long reg) { return readb(esp->regs + (reg * 4UL)); } static dma_addr_t zorro_esp_map_single(struct esp *esp, void *buf, size_t sz, int dir) { return dma_map_single(esp->dev, buf, sz, dir); } static int zorro_esp_map_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { return dma_map_sg(esp->dev, sg, num_sg, dir); } static void zorro_esp_unmap_single(struct esp *esp, dma_addr_t addr, size_t sz, int dir) { dma_unmap_single(esp->dev, addr, sz, dir); } static void zorro_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { dma_unmap_sg(esp->dev, sg, num_sg, dir); } static int zorro_esp_irq_pending(struct esp *esp) { /* check ESP status register; DMA has no status reg. */ if ( zorro_esp_read8(esp,ESP_STATUS) & ESP_STAT_INTR ) return 1; return 0; } static void zorro_esp_reset_dma(struct esp *esp) { /* nothing to do here */ } static void zorro_esp_dma_drain(struct esp *esp) { /* nothing to do here */ } static void zorro_esp_dma_invalidate(struct esp *esp) { /* nothing to do here */ } #ifdef ZORRO_ESP_PIO_CMD static void zorro_esp_send_pio_cmd(struct esp *esp, u32 esp_count, int write, u8 cmd) { /* NOTE that this function is only for esp->command_block! */ u32 i, j; u32 fbytes = 0; if (esp_count > 16) { printk( "zorro_esp: PIO: Too many bytes for command block transfer!\n" ); return; } cmd &= ~(ESP_CMD_DMA); if (write) { scsi_esp_cmd(esp, cmd); j = 0; while (1) { i = 0; fbytes = 0; while (!fbytes) { fbytes = zorro_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES; i++; if ( i > 1000000 ) break; udelay(1); } if (!fbytes) break; while (fbytes) { esp->command_block[j++] = zorro_esp_read8(esp, ESP_FDATA); fbytes--; } if ( j == esp_count ) break; i = 0; while (!zorro_esp_irq_pending(esp)) { i++; if ( i > 1000000 ) break; udelay(1); } if ( i > 1000000 ) { printk( "zorro_esp: PIO: IRQ TIMEOUT!\n" ); break; } scsi_esp_cmd(esp, ESP_CMD_TI); } } else { scsi_esp_cmd(esp, ESP_CMD_FLUSH); fbytes = esp_count; for (i=0;icommand_block[i], ESP_FDATA); scsi_esp_cmd(esp, cmd); } if ( j != esp_count ) printk( "zorro_esp: PIO: %d bytes transferred out of %d expected.\n" ); } #endif /* ZORRO_ESP_PIO_CMD */ // Blizzard 1230/60 SCSI-IV DMA static void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, u32 dma_count, int write, u8 cmd) { struct blz1230_dma_registers *dregs = (struct blz1230_dma_registers *) (esp->dma_regs); #ifdef ZORRO_ESP_PIO_CMD if (addr == esp->command_block_dma) { zorro_esp_send_pio_cmd(esp, esp_count, write, cmd); return; } #endif BUG_ON(!(cmd & ESP_CMD_DMA)); if (write) cache_clear(addr, esp_count); else cache_push(addr, esp_count); addr >>= 1; if (write) addr &= ~(DMA_WRITE); else addr |= DMA_WRITE; dregs->dma_latch = (addr >> 24) & 0xff; dregs->dma_addr = (addr >> 24) & 0xff; dregs->dma_addr = (addr >> 16) & 0xff; dregs->dma_addr = (addr >> 8) & 0xff; dregs->dma_addr = (addr ) & 0xff; scsi_esp_cmd(esp, ESP_CMD_DMA); zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); // zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); scsi_esp_cmd(esp, cmd); } // Blizzard 2060 DMA static void zorro_esp_send_blz2060_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, u32 dma_count, int write, u8 cmd) { struct blz2060_dma_registers *dregs = (struct blz2060_dma_registers *) (esp->dma_regs); #ifdef ZORRO_ESP_PIO_CMD if (addr == esp->command_block_dma) { zorro_esp_send_pio_cmd(esp, esp_count, write, cmd); return; } #endif BUG_ON(!(cmd & ESP_CMD_DMA)); if (write) cache_clear(addr, esp_count); else cache_push(addr, esp_count); addr >>= 1; if (write) addr &= ~(DMA_WRITE); else addr |= DMA_WRITE; dregs->dma_addr3 = (addr ) & 0xff; dregs->dma_addr2 = (addr >> 8) & 0xff; dregs->dma_addr1 = (addr >> 16) & 0xff; dregs->dma_addr0 = (addr >> 24) & 0xff; scsi_esp_cmd(esp, ESP_CMD_DMA); zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); // zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); scsi_esp_cmd(esp, cmd); } static int zorro_esp_dma_error(struct esp *esp) { /* nothing to do here - there seems to be no way to check for DMA errors */ return 0; } static struct esp_driver_ops zorro_esp_ops = { .esp_write8 = zorro_esp_write8, .esp_read8 = zorro_esp_read8, .map_single = zorro_esp_map_single, .map_sg = zorro_esp_map_sg, .unmap_single = zorro_esp_unmap_single, .unmap_sg = zorro_esp_unmap_sg, .irq_pending = zorro_esp_irq_pending, .reset_dma = zorro_esp_reset_dma, .dma_drain = zorro_esp_dma_drain, .dma_invalidate = zorro_esp_dma_invalidate, .send_dma_cmd = zorro_esp_send_blz2060_dma_cmd, .dma_error = zorro_esp_dma_error, }; static int zorro_esp_slave_configure(struct scsi_device *dev) { /* This function is used instead of the original esp_scsi.c: esp_slave_configure() to hardwire TCQ off until someone finds out where things go wrong. */ struct esp *esp = shost_priv(dev->host); struct esp_target_data *tp = &esp->target[dev->id]; scsi_deactivate_tcq(dev, dev->host->cmd_per_lun); tp->flags |= ESP_TGT_DISCONNECT; if (!spi_initial_dv(dev->sdev_target)) spi_dv_device(dev); return 0; } static int zorro_esp_init_one(struct zorro_dev *z, const struct zorro_device_id *ent) { struct scsi_host_template *tpnt = &scsi_esp_template; struct Scsi_Host *host; struct esp *esp; struct zorro_driver_data *zdd; unsigned long board, ioaddr, dmaaddr; int err = -ENOMEM; board = zorro_resource_start(z); zdd = (struct zorro_driver_data *)ent->driver_data; printk( "zorro_esp: %s found at address 0x%lx.\n", zdd->name, board ); if (zdd->absolute) { ioaddr = zdd->offset; dmaaddr = zdd->dma_offset; } else { ioaddr = board + zdd->offset; dmaaddr = board + zdd->dma_offset; } if (!zorro_request_device(z, zdd->name)) { printk(KERN_ERR "zorro_esp: cannot reserve region 0x%lx, abort\n", board); return -EBUSY; } host = scsi_host_alloc(tpnt, sizeof(struct esp)); if (!host) { printk(KERN_ERR "zorro_esp: No host detected; " "board configuration problem?\n"); goto out_free; } host->base = ioaddr; host->this_id = 7; esp = shost_priv(host); esp->host = host; esp->dev = &z->dev; esp->scsi_id = host->this_id; esp->scsi_id_mask = (1 << esp->scsi_id); /* Switch to the correct the DMA routine and clock frequency. */ switch ( ent->id ) { case ZORRO_PROD_PHASE5_BLIZZARD_2060: { zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz2060_dma_cmd; esp->cfreq = 40000000; break; } case ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260: { zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz1230_dma_cmd; esp->cfreq = 40000000; break; } default: { /* Oh noes */ printk(KERN_ERR "zorro_esp: Unsupported board!\n"); goto fail_free_host; break; } } esp->ops = &zorro_esp_ops; if (ioaddr > 0xffffff) esp->regs = ioremap_nocache(ioaddr, 0x20); else esp->regs = (void __iomem *)ZTWO_VADDR(ioaddr); if (!esp->regs) goto fail_free_host; /* Let's check whether a Blizzard 12x0 really has SCSI */ if ((ent->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260) || (ent->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060)) { zorro_esp_write8(esp, (ESP_CONFIG1_PENABLE | 7), ESP_CFG1); if ( zorro_esp_read8(esp, ESP_CFG1) != (ESP_CONFIG1_PENABLE | 7) ) goto fail_free_host; } if (ioaddr > 0xffffff) { // I guess the Fastlane Z3 will be the only one to catch this? // Here's a placeholder for now... if ( ent->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260 ) esp->dma_regs = ioremap_nocache( dmaaddr, sizeof(struct blz1230_dma_registers) ); } else esp->dma_regs = (void __iomem *)ZTWO_VADDR(dmaaddr); if (!esp->dma_regs) goto fail_unmap_regs; esp->command_block = dma_alloc_coherent(esp->dev, 16, &esp->command_block_dma, GFP_KERNEL); if (!esp->command_block) goto fail_unmap_dma_regs; host->irq = IRQ_AMIGA_PORTS; err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Amiga Zorro ESP", esp); if (err < 0) goto fail_free_command_block; // esp->flags = ESP_FLAG_DISABLE_SYNC; /* register the chip */ err = scsi_esp_register(esp, &z->dev); if (err) goto fail_free_irq; esp->config2 = ESP_CONFIG2_SCSI2ENAB; zorro_esp_write8(esp, esp->config2, ESP_CFG2); zorro_set_drvdata(z, host); return 0; fail_free_irq: free_irq(host->irq, esp); fail_free_command_block: dma_free_coherent(esp->dev, 16, esp->command_block, esp->command_block_dma); fail_unmap_dma_regs: if (ioaddr > 0xffffff) iounmap(esp->dma_regs); fail_unmap_regs: if (ioaddr > 0xffffff) iounmap(esp->regs); fail_free_host: scsi_host_put(host); out_free: zorro_release_device(z); return -ENODEV; } static void zorro_esp_remove_one(struct zorro_dev *z) { struct Scsi_Host *host = zorro_get_drvdata(z); struct esp *esp = shost_priv(host); scsi_esp_unregister(esp); /* Disable interrupts. Perhaps use disable_irq instead ... */ free_irq(host->irq, esp); dma_free_coherent(esp->dev, 16, esp->command_block, esp->command_block_dma); if ( host->base > 0xffffff ) { iounmap(esp->dma_regs); iounmap(esp->regs); } scsi_host_put(host); zorro_release_device(z); } static struct zorro_driver zorro_esp_driver = { .name = "zorro_esp-scsi", .id_table = zorro_esp_zorro_tbl, .probe = zorro_esp_init_one, .remove = zorro_esp_remove_one, }; static int __init zorro_esp_scsi_init(void) { return zorro_register_driver(&zorro_esp_driver); } static void __exit zorro_esp_scsi_exit(void) { zorro_unregister_driver(&zorro_esp_driver); } module_init(zorro_esp_scsi_init); module_exit(zorro_esp_scsi_exit);