162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * atari_scsi.c -- Device dependent functions for the Atari generic SCSI port 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Loosely based on the work of Robert De Vries' team and added: 762306a36Sopenharmony_ci * - working real DMA 862306a36Sopenharmony_ci * - Falcon support (untested yet!) ++bjoern fixed and now it works 962306a36Sopenharmony_ci * - lots of extensions and bug fixes. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 1262306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 1362306a36Sopenharmony_ci * for more details. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* 1862306a36Sopenharmony_ci * Notes for Falcon SCSI DMA 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * The 5380 device is one of several that all share the DMA chip. Hence 2162306a36Sopenharmony_ci * "locking" and "unlocking" access to this chip is required. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Two possible schemes for ST DMA acquisition by atari_scsi are: 2462306a36Sopenharmony_ci * 1) The lock is taken for each command separately (i.e. can_queue == 1). 2562306a36Sopenharmony_ci * 2) The lock is taken when the first command arrives and released 2662306a36Sopenharmony_ci * when the last command is finished (i.e. can_queue > 1). 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * The first alternative limits SCSI bus utilization, since interleaving 2962306a36Sopenharmony_ci * commands is not possible. The second gives better performance but is 3062306a36Sopenharmony_ci * unfair to other drivers needing to use the ST DMA chip. In order to 3162306a36Sopenharmony_ci * allow the IDE and floppy drivers equal access to the ST DMA chip 3262306a36Sopenharmony_ci * the default is can_queue == 1. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <linux/module.h> 3662306a36Sopenharmony_ci#include <linux/types.h> 3762306a36Sopenharmony_ci#include <linux/blkdev.h> 3862306a36Sopenharmony_ci#include <linux/interrupt.h> 3962306a36Sopenharmony_ci#include <linux/init.h> 4062306a36Sopenharmony_ci#include <linux/nvram.h> 4162306a36Sopenharmony_ci#include <linux/bitops.h> 4262306a36Sopenharmony_ci#include <linux/wait.h> 4362306a36Sopenharmony_ci#include <linux/platform_device.h> 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include <asm/setup.h> 4662306a36Sopenharmony_ci#include <asm/atarihw.h> 4762306a36Sopenharmony_ci#include <asm/atariints.h> 4862306a36Sopenharmony_ci#include <asm/atari_stdma.h> 4962306a36Sopenharmony_ci#include <asm/atari_stram.h> 5062306a36Sopenharmony_ci#include <asm/io.h> 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#include <scsi/scsi_host.h> 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define DMA_MIN_SIZE 32 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Definitions for the core NCR5380 driver. */ 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define NCR5380_implementation_fields /* none */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic u8 (*atari_scsi_reg_read)(unsigned int); 6162306a36Sopenharmony_cistatic void (*atari_scsi_reg_write)(unsigned int, u8); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define NCR5380_read(reg) atari_scsi_reg_read(reg) 6462306a36Sopenharmony_ci#define NCR5380_write(reg, value) atari_scsi_reg_write(reg, value) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define NCR5380_queue_command atari_scsi_queue_command 6762306a36Sopenharmony_ci#define NCR5380_abort atari_scsi_abort 6862306a36Sopenharmony_ci#define NCR5380_info atari_scsi_info 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define NCR5380_dma_xfer_len atari_scsi_dma_xfer_len 7162306a36Sopenharmony_ci#define NCR5380_dma_recv_setup atari_scsi_dma_recv_setup 7262306a36Sopenharmony_ci#define NCR5380_dma_send_setup atari_scsi_dma_send_setup 7362306a36Sopenharmony_ci#define NCR5380_dma_residual atari_scsi_dma_residual 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define NCR5380_acquire_dma_irq(instance) falcon_get_lock(instance) 7662306a36Sopenharmony_ci#define NCR5380_release_dma_irq(instance) falcon_release_lock() 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#include "NCR5380.h" 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define IS_A_TT() ATARIHW_PRESENT(TT_SCSI) 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define SCSI_DMA_WRITE_P(elt,val) \ 8462306a36Sopenharmony_ci do { \ 8562306a36Sopenharmony_ci unsigned long v = val; \ 8662306a36Sopenharmony_ci tt_scsi_dma.elt##_lo = v & 0xff; \ 8762306a36Sopenharmony_ci v >>= 8; \ 8862306a36Sopenharmony_ci tt_scsi_dma.elt##_lmd = v & 0xff; \ 8962306a36Sopenharmony_ci v >>= 8; \ 9062306a36Sopenharmony_ci tt_scsi_dma.elt##_hmd = v & 0xff; \ 9162306a36Sopenharmony_ci v >>= 8; \ 9262306a36Sopenharmony_ci tt_scsi_dma.elt##_hi = v & 0xff; \ 9362306a36Sopenharmony_ci } while(0) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define SCSI_DMA_READ_P(elt) \ 9662306a36Sopenharmony_ci (((((((unsigned long)tt_scsi_dma.elt##_hi << 8) | \ 9762306a36Sopenharmony_ci (unsigned long)tt_scsi_dma.elt##_hmd) << 8) | \ 9862306a36Sopenharmony_ci (unsigned long)tt_scsi_dma.elt##_lmd) << 8) | \ 9962306a36Sopenharmony_ci (unsigned long)tt_scsi_dma.elt##_lo) 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic inline void SCSI_DMA_SETADR(unsigned long adr) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci st_dma.dma_lo = (unsigned char)adr; 10562306a36Sopenharmony_ci MFPDELAY(); 10662306a36Sopenharmony_ci adr >>= 8; 10762306a36Sopenharmony_ci st_dma.dma_md = (unsigned char)adr; 10862306a36Sopenharmony_ci MFPDELAY(); 10962306a36Sopenharmony_ci adr >>= 8; 11062306a36Sopenharmony_ci st_dma.dma_hi = (unsigned char)adr; 11162306a36Sopenharmony_ci MFPDELAY(); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline unsigned long SCSI_DMA_GETADR(void) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci unsigned long adr; 11762306a36Sopenharmony_ci adr = st_dma.dma_lo; 11862306a36Sopenharmony_ci MFPDELAY(); 11962306a36Sopenharmony_ci adr |= (st_dma.dma_md & 0xff) << 8; 12062306a36Sopenharmony_ci MFPDELAY(); 12162306a36Sopenharmony_ci adr |= (st_dma.dma_hi & 0xff) << 16; 12262306a36Sopenharmony_ci MFPDELAY(); 12362306a36Sopenharmony_ci return adr; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic void atari_scsi_fetch_restbytes(void); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic unsigned long atari_dma_residual, atari_dma_startaddr; 12962306a36Sopenharmony_cistatic short atari_dma_active; 13062306a36Sopenharmony_ci/* pointer to the dribble buffer */ 13162306a36Sopenharmony_cistatic char *atari_dma_buffer; 13262306a36Sopenharmony_ci/* precalculated physical address of the dribble buffer */ 13362306a36Sopenharmony_cistatic unsigned long atari_dma_phys_buffer; 13462306a36Sopenharmony_ci/* != 0 tells the Falcon int handler to copy data from the dribble buffer */ 13562306a36Sopenharmony_cistatic char *atari_dma_orig_addr; 13662306a36Sopenharmony_ci/* size of the dribble buffer; 4k seems enough, since the Falcon cannot use 13762306a36Sopenharmony_ci * scatter-gather anyway, so most transfers are 1024 byte only. In the rare 13862306a36Sopenharmony_ci * cases where requests to physical contiguous buffers have been merged, this 13962306a36Sopenharmony_ci * request is <= 4k (one page). So I don't think we have to split transfers 14062306a36Sopenharmony_ci * just due to this buffer size... 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci#define STRAM_BUFFER_SIZE (4096) 14362306a36Sopenharmony_ci/* mask for address bits that can't be used with the ST-DMA */ 14462306a36Sopenharmony_cistatic unsigned long atari_dma_stram_mask; 14562306a36Sopenharmony_ci#define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0) 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int setup_can_queue = -1; 14862306a36Sopenharmony_cimodule_param(setup_can_queue, int, 0); 14962306a36Sopenharmony_cistatic int setup_cmd_per_lun = -1; 15062306a36Sopenharmony_cimodule_param(setup_cmd_per_lun, int, 0); 15162306a36Sopenharmony_cistatic int setup_sg_tablesize = -1; 15262306a36Sopenharmony_cimodule_param(setup_sg_tablesize, int, 0); 15362306a36Sopenharmony_cistatic int setup_hostid = -1; 15462306a36Sopenharmony_cimodule_param(setup_hostid, int, 0); 15562306a36Sopenharmony_cistatic int setup_toshiba_delay = -1; 15662306a36Sopenharmony_cimodule_param(setup_toshiba_delay, int, 0); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic int scsi_dma_is_ignored_buserr(unsigned char dma_stat) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci int i; 16262306a36Sopenharmony_ci unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (dma_stat & 0x01) { 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* A bus error happens when DMA-ing from the last page of a 16762306a36Sopenharmony_ci * physical memory chunk (DMA prefetch!), but that doesn't hurt. 16862306a36Sopenharmony_ci * Check for this case: 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci for (i = 0; i < m68k_num_memory; ++i) { 17262306a36Sopenharmony_ci end_addr = m68k_memory[i].addr + m68k_memory[i].size; 17362306a36Sopenharmony_ci if (end_addr <= addr && addr <= end_addr + 4) 17462306a36Sopenharmony_ci return 1; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci return 0; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic irqreturn_t scsi_tt_intr(int irq, void *dev) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct Scsi_Host *instance = dev; 18462306a36Sopenharmony_ci struct NCR5380_hostdata *hostdata = shost_priv(instance); 18562306a36Sopenharmony_ci int dma_stat; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci dma_stat = tt_scsi_dma.dma_ctrl; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci dsprintk(NDEBUG_INTR, instance, "NCR5380 interrupt, DMA status = %02x\n", 19062306a36Sopenharmony_ci dma_stat & 0xff); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* Look if it was the DMA that has interrupted: First possibility 19362306a36Sopenharmony_ci * is that a bus error occurred... 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_ci if (dma_stat & 0x80) { 19662306a36Sopenharmony_ci if (!scsi_dma_is_ignored_buserr(dma_stat)) { 19762306a36Sopenharmony_ci printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n", 19862306a36Sopenharmony_ci SCSI_DMA_READ_P(dma_addr)); 19962306a36Sopenharmony_ci printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!"); 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* If the DMA is active but not finished, we have the case 20462306a36Sopenharmony_ci * that some other 5380 interrupt occurred within the DMA transfer. 20562306a36Sopenharmony_ci * This means we have residual bytes, if the desired end address 20662306a36Sopenharmony_ci * is not yet reached. Maybe we have to fetch some bytes from the 20762306a36Sopenharmony_ci * rest data register, too. The residual must be calculated from 20862306a36Sopenharmony_ci * the address pointer, not the counter register, because only the 20962306a36Sopenharmony_ci * addr reg counts bytes not yet written and pending in the rest 21062306a36Sopenharmony_ci * data reg! 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { 21362306a36Sopenharmony_ci atari_dma_residual = hostdata->dma_len - 21462306a36Sopenharmony_ci (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n", 21762306a36Sopenharmony_ci atari_dma_residual); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if ((signed int)atari_dma_residual < 0) 22062306a36Sopenharmony_ci atari_dma_residual = 0; 22162306a36Sopenharmony_ci if ((dma_stat & 1) == 0) { 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * After read operations, we maybe have to 22462306a36Sopenharmony_ci * transport some rest bytes 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci atari_scsi_fetch_restbytes(); 22762306a36Sopenharmony_ci } else { 22862306a36Sopenharmony_ci /* 22962306a36Sopenharmony_ci * There seems to be a nasty bug in some SCSI-DMA/NCR 23062306a36Sopenharmony_ci * combinations: If a target disconnects while a write 23162306a36Sopenharmony_ci * operation is going on, the address register of the 23262306a36Sopenharmony_ci * DMA may be a few bytes farer than it actually read. 23362306a36Sopenharmony_ci * This is probably due to DMA prefetching and a delay 23462306a36Sopenharmony_ci * between DMA and NCR. Experiments showed that the 23562306a36Sopenharmony_ci * dma_addr is 9 bytes to high, but this could vary. 23662306a36Sopenharmony_ci * The problem is, that the residual is thus calculated 23762306a36Sopenharmony_ci * wrong and the next transfer will start behind where 23862306a36Sopenharmony_ci * it should. So we round up the residual to the next 23962306a36Sopenharmony_ci * multiple of a sector size, if it isn't already a 24062306a36Sopenharmony_ci * multiple and the originally expected transfer size 24162306a36Sopenharmony_ci * was. The latter condition is there to ensure that 24262306a36Sopenharmony_ci * the correction is taken only for "real" data 24362306a36Sopenharmony_ci * transfers and not for, e.g., the parameters of some 24462306a36Sopenharmony_ci * other command. These shouldn't disconnect anyway. 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ci if (atari_dma_residual & 0x1ff) { 24762306a36Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: DMA bug corrected, " 24862306a36Sopenharmony_ci "difference %ld bytes\n", 24962306a36Sopenharmony_ci 512 - (atari_dma_residual & 0x1ff)); 25062306a36Sopenharmony_ci atari_dma_residual = (atari_dma_residual + 511) & ~0x1ff; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* If the DMA is finished, fetch the rest bytes and turn it off */ 25762306a36Sopenharmony_ci if (dma_stat & 0x40) { 25862306a36Sopenharmony_ci atari_dma_residual = 0; 25962306a36Sopenharmony_ci if ((dma_stat & 1) == 0) 26062306a36Sopenharmony_ci atari_scsi_fetch_restbytes(); 26162306a36Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci NCR5380_intr(irq, dev); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci return IRQ_HANDLED; 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic irqreturn_t scsi_falcon_intr(int irq, void *dev) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct Scsi_Host *instance = dev; 27362306a36Sopenharmony_ci struct NCR5380_hostdata *hostdata = shost_priv(instance); 27462306a36Sopenharmony_ci int dma_stat; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* Turn off DMA and select sector counter register before 27762306a36Sopenharmony_ci * accessing the status register (Atari recommendation!) 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci st_dma.dma_mode_status = 0x90; 28062306a36Sopenharmony_ci dma_stat = st_dma.dma_mode_status; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* Bit 0 indicates some error in the DMA process... don't know 28362306a36Sopenharmony_ci * what happened exactly (no further docu). 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci if (!(dma_stat & 0x01)) { 28662306a36Sopenharmony_ci /* DMA error */ 28762306a36Sopenharmony_ci printk(KERN_CRIT "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR()); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* If the DMA was active, but now bit 1 is not clear, it is some 29162306a36Sopenharmony_ci * other 5380 interrupt that finishes the DMA transfer. We have to 29262306a36Sopenharmony_ci * calculate the number of residual bytes and give a warning if 29362306a36Sopenharmony_ci * bytes are stuck in the ST-DMA fifo (there's no way to reach them!) 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci if (atari_dma_active && (dma_stat & 0x02)) { 29662306a36Sopenharmony_ci unsigned long transferred; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci transferred = SCSI_DMA_GETADR() - atari_dma_startaddr; 29962306a36Sopenharmony_ci /* The ST-DMA address is incremented in 2-byte steps, but the 30062306a36Sopenharmony_ci * data are written only in 16-byte chunks. If the number of 30162306a36Sopenharmony_ci * transferred bytes is not divisible by 16, the remainder is 30262306a36Sopenharmony_ci * lost somewhere in outer space. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci if (transferred & 15) 30562306a36Sopenharmony_ci printk(KERN_ERR "SCSI DMA error: %ld bytes lost in " 30662306a36Sopenharmony_ci "ST-DMA fifo\n", transferred & 15); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci atari_dma_residual = hostdata->dma_len - transferred; 30962306a36Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n", 31062306a36Sopenharmony_ci atari_dma_residual); 31162306a36Sopenharmony_ci } else 31262306a36Sopenharmony_ci atari_dma_residual = 0; 31362306a36Sopenharmony_ci atari_dma_active = 0; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (atari_dma_orig_addr) { 31662306a36Sopenharmony_ci /* If the dribble buffer was used on a read operation, copy the DMA-ed 31762306a36Sopenharmony_ci * data to the original destination address. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr), 32062306a36Sopenharmony_ci hostdata->dma_len - atari_dma_residual); 32162306a36Sopenharmony_ci atari_dma_orig_addr = NULL; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci NCR5380_intr(irq, dev); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci return IRQ_HANDLED; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic void atari_scsi_fetch_restbytes(void) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci int nr; 33362306a36Sopenharmony_ci char *src, *dst; 33462306a36Sopenharmony_ci unsigned long phys_dst; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* fetch rest bytes in the DMA register */ 33762306a36Sopenharmony_ci phys_dst = SCSI_DMA_READ_P(dma_addr); 33862306a36Sopenharmony_ci nr = phys_dst & 3; 33962306a36Sopenharmony_ci if (nr) { 34062306a36Sopenharmony_ci /* there are 'nr' bytes left for the last long address 34162306a36Sopenharmony_ci before the DMA pointer */ 34262306a36Sopenharmony_ci phys_dst ^= nr; 34362306a36Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: there are %d rest bytes for phys addr 0x%08lx", 34462306a36Sopenharmony_ci nr, phys_dst); 34562306a36Sopenharmony_ci /* The content of the DMA pointer is a physical address! */ 34662306a36Sopenharmony_ci dst = phys_to_virt(phys_dst); 34762306a36Sopenharmony_ci dprintk(NDEBUG_DMA, " = virt addr %p\n", dst); 34862306a36Sopenharmony_ci for (src = (char *)&tt_scsi_dma.dma_restdata; nr != 0; --nr) 34962306a36Sopenharmony_ci *dst++ = *src++; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci/* This function releases the lock on the DMA chip if there is no 35562306a36Sopenharmony_ci * connected command and the disconnected queue is empty. 35662306a36Sopenharmony_ci */ 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic void falcon_release_lock(void) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci if (IS_A_TT()) 36162306a36Sopenharmony_ci return; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci if (stdma_is_locked_by(scsi_falcon_intr)) 36462306a36Sopenharmony_ci stdma_release(); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* This function manages the locking of the ST-DMA. 36862306a36Sopenharmony_ci * If the DMA isn't locked already for SCSI, it tries to lock it by 36962306a36Sopenharmony_ci * calling stdma_lock(). But if the DMA is locked by the SCSI code and 37062306a36Sopenharmony_ci * there are other drivers waiting for the chip, we do not issue the 37162306a36Sopenharmony_ci * command immediately but tell the SCSI mid-layer to defer. 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic int falcon_get_lock(struct Scsi_Host *instance) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci if (IS_A_TT()) 37762306a36Sopenharmony_ci return 1; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (stdma_is_locked_by(scsi_falcon_intr)) 38062306a36Sopenharmony_ci return 1; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* stdma_lock() may sleep which means it can't be used here */ 38362306a36Sopenharmony_ci return stdma_try_lock(scsi_falcon_intr, instance); 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci#ifndef MODULE 38762306a36Sopenharmony_cistatic int __init atari_scsi_setup(char *str) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci /* Format of atascsi parameter is: 39062306a36Sopenharmony_ci * atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> 39162306a36Sopenharmony_ci * Defaults depend on TT or Falcon, determined at run time. 39262306a36Sopenharmony_ci * Negative values mean don't change. 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_ci int ints[8]; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci get_options(str, ARRAY_SIZE(ints), ints); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (ints[0] < 1) { 39962306a36Sopenharmony_ci printk("atari_scsi_setup: no arguments!\n"); 40062306a36Sopenharmony_ci return 0; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci if (ints[0] >= 1) 40362306a36Sopenharmony_ci setup_can_queue = ints[1]; 40462306a36Sopenharmony_ci if (ints[0] >= 2) 40562306a36Sopenharmony_ci setup_cmd_per_lun = ints[2]; 40662306a36Sopenharmony_ci if (ints[0] >= 3) 40762306a36Sopenharmony_ci setup_sg_tablesize = ints[3]; 40862306a36Sopenharmony_ci if (ints[0] >= 4) 40962306a36Sopenharmony_ci setup_hostid = ints[4]; 41062306a36Sopenharmony_ci /* ints[5] (use_tagged_queuing) is ignored */ 41162306a36Sopenharmony_ci /* ints[6] (use_pdma) is ignored */ 41262306a36Sopenharmony_ci if (ints[0] >= 7) 41362306a36Sopenharmony_ci setup_toshiba_delay = ints[7]; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return 1; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci__setup("atascsi=", atari_scsi_setup); 41962306a36Sopenharmony_ci#endif /* !MODULE */ 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic unsigned long atari_scsi_dma_setup(struct NCR5380_hostdata *hostdata, 42262306a36Sopenharmony_ci void *data, unsigned long count, 42362306a36Sopenharmony_ci int dir) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci unsigned long addr = virt_to_phys(data); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci dprintk(NDEBUG_DMA, "scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, dir = %d\n", 42862306a36Sopenharmony_ci hostdata->host->host_no, data, addr, count, dir); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci if (!IS_A_TT() && !STRAM_ADDR(addr)) { 43162306a36Sopenharmony_ci /* If we have a non-DMAable address on a Falcon, use the dribble 43262306a36Sopenharmony_ci * buffer; 'orig_addr' != 0 in the read case tells the interrupt 43362306a36Sopenharmony_ci * handler to copy data from the dribble buffer to the originally 43462306a36Sopenharmony_ci * wanted address. 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_ci if (dir) 43762306a36Sopenharmony_ci memcpy(atari_dma_buffer, data, count); 43862306a36Sopenharmony_ci else 43962306a36Sopenharmony_ci atari_dma_orig_addr = data; 44062306a36Sopenharmony_ci addr = atari_dma_phys_buffer; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci atari_dma_startaddr = addr; /* Needed for calculating residual later. */ 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* Cache cleanup stuff: On writes, push any dirty cache out before sending 44662306a36Sopenharmony_ci * it to the peripheral. (Must be done before DMA setup, since at least 44762306a36Sopenharmony_ci * the ST-DMA begins to fill internal buffers right after setup. For 44862306a36Sopenharmony_ci * reads, invalidate any cache, may be altered after DMA without CPU 44962306a36Sopenharmony_ci * knowledge. 45062306a36Sopenharmony_ci * 45162306a36Sopenharmony_ci * ++roman: For the Medusa, there's no need at all for that cache stuff, 45262306a36Sopenharmony_ci * because the hardware does bus snooping (fine!). 45362306a36Sopenharmony_ci */ 45462306a36Sopenharmony_ci dma_cache_maintenance(addr, count, dir); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (IS_A_TT()) { 45762306a36Sopenharmony_ci tt_scsi_dma.dma_ctrl = dir; 45862306a36Sopenharmony_ci SCSI_DMA_WRITE_P(dma_addr, addr); 45962306a36Sopenharmony_ci SCSI_DMA_WRITE_P(dma_cnt, count); 46062306a36Sopenharmony_ci tt_scsi_dma.dma_ctrl = dir | 2; 46162306a36Sopenharmony_ci } else { /* ! IS_A_TT */ 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* set address */ 46462306a36Sopenharmony_ci SCSI_DMA_SETADR(addr); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* toggle direction bit to clear FIFO and set DMA direction */ 46762306a36Sopenharmony_ci dir <<= 8; 46862306a36Sopenharmony_ci st_dma.dma_mode_status = 0x90 | dir; 46962306a36Sopenharmony_ci st_dma.dma_mode_status = 0x90 | (dir ^ 0x100); 47062306a36Sopenharmony_ci st_dma.dma_mode_status = 0x90 | dir; 47162306a36Sopenharmony_ci udelay(40); 47262306a36Sopenharmony_ci /* On writes, round up the transfer length to the next multiple of 512 47362306a36Sopenharmony_ci * (see also comment at atari_dma_xfer_len()). */ 47462306a36Sopenharmony_ci st_dma.fdc_acces_seccount = (count + (dir ? 511 : 0)) >> 9; 47562306a36Sopenharmony_ci udelay(40); 47662306a36Sopenharmony_ci st_dma.dma_mode_status = 0x10 | dir; 47762306a36Sopenharmony_ci udelay(40); 47862306a36Sopenharmony_ci /* need not restore value of dir, only boolean value is tested */ 47962306a36Sopenharmony_ci atari_dma_active = 1; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return count; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic inline int atari_scsi_dma_recv_setup(struct NCR5380_hostdata *hostdata, 48662306a36Sopenharmony_ci unsigned char *data, int count) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci return atari_scsi_dma_setup(hostdata, data, count, 0); 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic inline int atari_scsi_dma_send_setup(struct NCR5380_hostdata *hostdata, 49262306a36Sopenharmony_ci unsigned char *data, int count) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci return atari_scsi_dma_setup(hostdata, data, count, 1); 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic int atari_scsi_dma_residual(struct NCR5380_hostdata *hostdata) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci return atari_dma_residual; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci#define CMD_SURELY_BLOCK_MODE 0 50462306a36Sopenharmony_ci#define CMD_SURELY_BYTE_MODE 1 50562306a36Sopenharmony_ci#define CMD_MODE_UNKNOWN 2 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic int falcon_classify_cmd(struct scsi_cmnd *cmd) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci unsigned char opcode = cmd->cmnd[0]; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (opcode == READ_DEFECT_DATA || opcode == READ_LONG || 51262306a36Sopenharmony_ci opcode == READ_BUFFER) 51362306a36Sopenharmony_ci return CMD_SURELY_BYTE_MODE; 51462306a36Sopenharmony_ci else if (opcode == READ_6 || opcode == READ_10 || 51562306a36Sopenharmony_ci opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE || 51662306a36Sopenharmony_ci opcode == RECOVER_BUFFERED_DATA) { 51762306a36Sopenharmony_ci /* In case of a sequential-access target (tape), special care is 51862306a36Sopenharmony_ci * needed here: The transfer is block-mode only if the 'fixed' bit is 51962306a36Sopenharmony_ci * set! */ 52062306a36Sopenharmony_ci if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1)) 52162306a36Sopenharmony_ci return CMD_SURELY_BYTE_MODE; 52262306a36Sopenharmony_ci else 52362306a36Sopenharmony_ci return CMD_SURELY_BLOCK_MODE; 52462306a36Sopenharmony_ci } else 52562306a36Sopenharmony_ci return CMD_MODE_UNKNOWN; 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci/* This function calculates the number of bytes that can be transferred via 53062306a36Sopenharmony_ci * DMA. On the TT, this is arbitrary, but on the Falcon we have to use the 53162306a36Sopenharmony_ci * ST-DMA chip. There are only multiples of 512 bytes possible and max. 53262306a36Sopenharmony_ci * 255*512 bytes :-( This means also, that defining READ_OVERRUNS is not 53362306a36Sopenharmony_ci * possible on the Falcon, since that would require to program the DMA for 53462306a36Sopenharmony_ci * n*512 - atari_read_overrun bytes. But it seems that the Falcon doesn't have 53562306a36Sopenharmony_ci * the overrun problem, so this question is academic :-) 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic int atari_scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, 53962306a36Sopenharmony_ci struct scsi_cmnd *cmd) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci int wanted_len = NCR5380_to_ncmd(cmd)->this_residual; 54262306a36Sopenharmony_ci int possible_len, limit; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (wanted_len < DMA_MIN_SIZE) 54562306a36Sopenharmony_ci return 0; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci if (IS_A_TT()) 54862306a36Sopenharmony_ci /* TT SCSI DMA can transfer arbitrary #bytes */ 54962306a36Sopenharmony_ci return wanted_len; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max. 55262306a36Sopenharmony_ci * 255*512 bytes, but this should be enough) 55362306a36Sopenharmony_ci * 55462306a36Sopenharmony_ci * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands 55562306a36Sopenharmony_ci * that return a number of bytes which cannot be known beforehand. In this 55662306a36Sopenharmony_ci * case, the given transfer length is an "allocation length". Now it 55762306a36Sopenharmony_ci * can happen that this allocation length is a multiple of 512 bytes and 55862306a36Sopenharmony_ci * the DMA is used. But if not n*512 bytes really arrive, some input data 55962306a36Sopenharmony_ci * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish 56062306a36Sopenharmony_ci * between commands that do block transfers and those that do byte 56162306a36Sopenharmony_ci * transfers. But this isn't easy... there are lots of vendor specific 56262306a36Sopenharmony_ci * commands, and the user can issue any command via the 56362306a36Sopenharmony_ci * SCSI_IOCTL_SEND_COMMAND. 56462306a36Sopenharmony_ci * 56562306a36Sopenharmony_ci * The solution: We classify SCSI commands in 1) surely block-mode cmd.s, 56662306a36Sopenharmony_ci * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1) 56762306a36Sopenharmony_ci * and 3), the thing to do is obvious: allow any number of blocks via DMA 56862306a36Sopenharmony_ci * or none. In case 2), we apply some heuristic: Byte mode is assumed if 56962306a36Sopenharmony_ci * the transfer (allocation) length is < 1024, hoping that no cmd. not 57062306a36Sopenharmony_ci * explicitly known as byte mode have such big allocation lengths... 57162306a36Sopenharmony_ci * BTW, all the discussion above applies only to reads. DMA writes are 57262306a36Sopenharmony_ci * unproblematic anyways, since the targets aborts the transfer after 57362306a36Sopenharmony_ci * receiving a sufficient number of bytes. 57462306a36Sopenharmony_ci * 57562306a36Sopenharmony_ci * Another point: If the transfer is from/to an non-ST-RAM address, we 57662306a36Sopenharmony_ci * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes. 57762306a36Sopenharmony_ci */ 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (cmd->sc_data_direction == DMA_TO_DEVICE) { 58062306a36Sopenharmony_ci /* Write operation can always use the DMA, but the transfer size must 58162306a36Sopenharmony_ci * be rounded up to the next multiple of 512 (atari_dma_setup() does 58262306a36Sopenharmony_ci * this). 58362306a36Sopenharmony_ci */ 58462306a36Sopenharmony_ci possible_len = wanted_len; 58562306a36Sopenharmony_ci } else { 58662306a36Sopenharmony_ci /* Read operations: if the wanted transfer length is not a multiple of 58762306a36Sopenharmony_ci * 512, we cannot use DMA, since the ST-DMA cannot split transfers 58862306a36Sopenharmony_ci * (no interrupt on DMA finished!) 58962306a36Sopenharmony_ci */ 59062306a36Sopenharmony_ci if (wanted_len & 0x1ff) 59162306a36Sopenharmony_ci possible_len = 0; 59262306a36Sopenharmony_ci else { 59362306a36Sopenharmony_ci /* Now classify the command (see above) and decide whether it is 59462306a36Sopenharmony_ci * allowed to do DMA at all */ 59562306a36Sopenharmony_ci switch (falcon_classify_cmd(cmd)) { 59662306a36Sopenharmony_ci case CMD_SURELY_BLOCK_MODE: 59762306a36Sopenharmony_ci possible_len = wanted_len; 59862306a36Sopenharmony_ci break; 59962306a36Sopenharmony_ci case CMD_SURELY_BYTE_MODE: 60062306a36Sopenharmony_ci possible_len = 0; /* DMA prohibited */ 60162306a36Sopenharmony_ci break; 60262306a36Sopenharmony_ci case CMD_MODE_UNKNOWN: 60362306a36Sopenharmony_ci default: 60462306a36Sopenharmony_ci /* For unknown commands assume block transfers if the transfer 60562306a36Sopenharmony_ci * size/allocation length is >= 1024 */ 60662306a36Sopenharmony_ci possible_len = (wanted_len < 1024) ? 0 : wanted_len; 60762306a36Sopenharmony_ci break; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* Last step: apply the hard limit on DMA transfers */ 61362306a36Sopenharmony_ci limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(NCR5380_to_ncmd(cmd)->ptr))) ? 61462306a36Sopenharmony_ci STRAM_BUFFER_SIZE : 255*512; 61562306a36Sopenharmony_ci if (possible_len > limit) 61662306a36Sopenharmony_ci possible_len = limit; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (possible_len != wanted_len) 61962306a36Sopenharmony_ci dprintk(NDEBUG_DMA, "DMA transfer now %d bytes instead of %d\n", 62062306a36Sopenharmony_ci possible_len, wanted_len); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return possible_len; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci/* NCR5380 register access functions 62762306a36Sopenharmony_ci * 62862306a36Sopenharmony_ci * There are separate functions for TT and Falcon, because the access 62962306a36Sopenharmony_ci * methods are quite different. The calling macros NCR5380_read and 63062306a36Sopenharmony_ci * NCR5380_write call these functions via function pointers. 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic u8 atari_scsi_tt_reg_read(unsigned int reg) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci return tt_scsi_regp[reg * 2]; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic void atari_scsi_tt_reg_write(unsigned int reg, u8 value) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci tt_scsi_regp[reg * 2] = value; 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic u8 atari_scsi_falcon_reg_read(unsigned int reg) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci unsigned long flags; 64662306a36Sopenharmony_ci u8 result; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci reg += 0x88; 64962306a36Sopenharmony_ci local_irq_save(flags); 65062306a36Sopenharmony_ci dma_wd.dma_mode_status = (u_short)reg; 65162306a36Sopenharmony_ci result = (u8)dma_wd.fdc_acces_seccount; 65262306a36Sopenharmony_ci local_irq_restore(flags); 65362306a36Sopenharmony_ci return result; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic void atari_scsi_falcon_reg_write(unsigned int reg, u8 value) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci unsigned long flags; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci reg += 0x88; 66162306a36Sopenharmony_ci local_irq_save(flags); 66262306a36Sopenharmony_ci dma_wd.dma_mode_status = (u_short)reg; 66362306a36Sopenharmony_ci dma_wd.fdc_acces_seccount = (u_short)value; 66462306a36Sopenharmony_ci local_irq_restore(flags); 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci#include "NCR5380.c" 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic int atari_scsi_host_reset(struct scsi_cmnd *cmd) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci int rv; 67362306a36Sopenharmony_ci unsigned long flags; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci local_irq_save(flags); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* Abort a maybe active DMA transfer */ 67862306a36Sopenharmony_ci if (IS_A_TT()) { 67962306a36Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 68062306a36Sopenharmony_ci } else { 68162306a36Sopenharmony_ci if (stdma_is_locked_by(scsi_falcon_intr)) 68262306a36Sopenharmony_ci st_dma.dma_mode_status = 0x90; 68362306a36Sopenharmony_ci atari_dma_active = 0; 68462306a36Sopenharmony_ci atari_dma_orig_addr = NULL; 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci rv = NCR5380_host_reset(cmd); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci /* The 5380 raises its IRQ line while _RST is active but the ST DMA 69062306a36Sopenharmony_ci * "lock" has been released so this interrupt may end up handled by 69162306a36Sopenharmony_ci * floppy or IDE driver (if one of them holds the lock). The NCR5380 69262306a36Sopenharmony_ci * interrupt flag has been cleared already. 69362306a36Sopenharmony_ci */ 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci local_irq_restore(flags); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci return rv; 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci#define DRV_MODULE_NAME "atari_scsi" 70162306a36Sopenharmony_ci#define PFX DRV_MODULE_NAME ": " 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic struct scsi_host_template atari_scsi_template = { 70462306a36Sopenharmony_ci .module = THIS_MODULE, 70562306a36Sopenharmony_ci .proc_name = DRV_MODULE_NAME, 70662306a36Sopenharmony_ci .name = "Atari native SCSI", 70762306a36Sopenharmony_ci .info = atari_scsi_info, 70862306a36Sopenharmony_ci .queuecommand = atari_scsi_queue_command, 70962306a36Sopenharmony_ci .eh_abort_handler = atari_scsi_abort, 71062306a36Sopenharmony_ci .eh_host_reset_handler = atari_scsi_host_reset, 71162306a36Sopenharmony_ci .this_id = 7, 71262306a36Sopenharmony_ci .cmd_per_lun = 2, 71362306a36Sopenharmony_ci .dma_boundary = PAGE_SIZE - 1, 71462306a36Sopenharmony_ci .cmd_size = sizeof(struct NCR5380_cmd), 71562306a36Sopenharmony_ci}; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic int __init atari_scsi_probe(struct platform_device *pdev) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci struct Scsi_Host *instance; 72062306a36Sopenharmony_ci int error; 72162306a36Sopenharmony_ci struct resource *irq; 72262306a36Sopenharmony_ci int host_flags = 0; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 72562306a36Sopenharmony_ci if (!irq) 72662306a36Sopenharmony_ci return -ENODEV; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (ATARIHW_PRESENT(TT_SCSI)) { 72962306a36Sopenharmony_ci atari_scsi_reg_read = atari_scsi_tt_reg_read; 73062306a36Sopenharmony_ci atari_scsi_reg_write = atari_scsi_tt_reg_write; 73162306a36Sopenharmony_ci } else { 73262306a36Sopenharmony_ci atari_scsi_reg_read = atari_scsi_falcon_reg_read; 73362306a36Sopenharmony_ci atari_scsi_reg_write = atari_scsi_falcon_reg_write; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci if (ATARIHW_PRESENT(TT_SCSI)) { 73762306a36Sopenharmony_ci atari_scsi_template.can_queue = 16; 73862306a36Sopenharmony_ci atari_scsi_template.sg_tablesize = SG_ALL; 73962306a36Sopenharmony_ci } else { 74062306a36Sopenharmony_ci atari_scsi_template.can_queue = 1; 74162306a36Sopenharmony_ci atari_scsi_template.sg_tablesize = 1; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci if (setup_can_queue > 0) 74562306a36Sopenharmony_ci atari_scsi_template.can_queue = setup_can_queue; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (setup_cmd_per_lun > 0) 74862306a36Sopenharmony_ci atari_scsi_template.cmd_per_lun = setup_cmd_per_lun; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* Don't increase sg_tablesize on Falcon! */ 75162306a36Sopenharmony_ci if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0) 75262306a36Sopenharmony_ci atari_scsi_template.sg_tablesize = setup_sg_tablesize; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci if (setup_hostid >= 0) { 75562306a36Sopenharmony_ci atari_scsi_template.this_id = setup_hostid & 7; 75662306a36Sopenharmony_ci } else if (IS_REACHABLE(CONFIG_NVRAM)) { 75762306a36Sopenharmony_ci /* Test if a host id is set in the NVRam */ 75862306a36Sopenharmony_ci if (ATARIHW_PRESENT(TT_CLK)) { 75962306a36Sopenharmony_ci unsigned char b; 76062306a36Sopenharmony_ci loff_t offset = 16; 76162306a36Sopenharmony_ci ssize_t count = nvram_read(&b, 1, &offset); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci /* Arbitration enabled? (for TOS) 76462306a36Sopenharmony_ci * If yes, use configured host ID 76562306a36Sopenharmony_ci */ 76662306a36Sopenharmony_ci if ((count == 1) && (b & 0x80)) 76762306a36Sopenharmony_ci atari_scsi_template.this_id = b & 7; 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci /* If running on a Falcon and if there's TT-Ram (i.e., more than one 77262306a36Sopenharmony_ci * memory block, since there's always ST-Ram in a Falcon), then 77362306a36Sopenharmony_ci * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers 77462306a36Sopenharmony_ci * from/to alternative Ram. 77562306a36Sopenharmony_ci */ 77662306a36Sopenharmony_ci if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) && 77762306a36Sopenharmony_ci m68k_realnum_memory > 1) { 77862306a36Sopenharmony_ci atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); 77962306a36Sopenharmony_ci if (!atari_dma_buffer) { 78062306a36Sopenharmony_ci pr_err(PFX "can't allocate ST-RAM double buffer\n"); 78162306a36Sopenharmony_ci return -ENOMEM; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); 78462306a36Sopenharmony_ci atari_dma_orig_addr = NULL; 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci instance = scsi_host_alloc(&atari_scsi_template, 78862306a36Sopenharmony_ci sizeof(struct NCR5380_hostdata)); 78962306a36Sopenharmony_ci if (!instance) { 79062306a36Sopenharmony_ci error = -ENOMEM; 79162306a36Sopenharmony_ci goto fail_alloc; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci instance->irq = irq->start; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP; 79762306a36Sopenharmony_ci host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci error = NCR5380_init(instance, host_flags); 80062306a36Sopenharmony_ci if (error) 80162306a36Sopenharmony_ci goto fail_init; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci if (IS_A_TT()) { 80462306a36Sopenharmony_ci error = request_irq(instance->irq, scsi_tt_intr, 0, 80562306a36Sopenharmony_ci "NCR5380", instance); 80662306a36Sopenharmony_ci if (error) { 80762306a36Sopenharmony_ci pr_err(PFX "request irq %d failed, aborting\n", 80862306a36Sopenharmony_ci instance->irq); 80962306a36Sopenharmony_ci goto fail_irq; 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */ 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 81462306a36Sopenharmony_ci atari_dma_residual = 0; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci /* While the read overruns (described by Drew Eckhardt in 81762306a36Sopenharmony_ci * NCR5380.c) never happened on TTs, they do in fact on the 81862306a36Sopenharmony_ci * Medusa (This was the cause why SCSI didn't work right for 81962306a36Sopenharmony_ci * so long there.) Since handling the overruns slows down 82062306a36Sopenharmony_ci * a bit, I turned the #ifdef's into a runtime condition. 82162306a36Sopenharmony_ci * 82262306a36Sopenharmony_ci * In principle it should be sufficient to do max. 1 byte with 82362306a36Sopenharmony_ci * PIO, but there is another problem on the Medusa with the DMA 82462306a36Sopenharmony_ci * rest data register. So read_overruns is currently set 82562306a36Sopenharmony_ci * to 4 to avoid having transfers that aren't a multiple of 4. 82662306a36Sopenharmony_ci * If the rest data bug is fixed, this can be lowered to 1. 82762306a36Sopenharmony_ci */ 82862306a36Sopenharmony_ci if (MACH_IS_MEDUSA) { 82962306a36Sopenharmony_ci struct NCR5380_hostdata *hostdata = 83062306a36Sopenharmony_ci shost_priv(instance); 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci hostdata->read_overruns = 4; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci } else { 83562306a36Sopenharmony_ci /* Nothing to do for the interrupt: the ST-DMA is initialized 83662306a36Sopenharmony_ci * already. 83762306a36Sopenharmony_ci */ 83862306a36Sopenharmony_ci atari_dma_residual = 0; 83962306a36Sopenharmony_ci atari_dma_active = 0; 84062306a36Sopenharmony_ci atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 84162306a36Sopenharmony_ci : 0xff000000); 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci NCR5380_maybe_reset_bus(instance); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci error = scsi_add_host(instance, NULL); 84762306a36Sopenharmony_ci if (error) 84862306a36Sopenharmony_ci goto fail_host; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci platform_set_drvdata(pdev, instance); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci scsi_scan_host(instance); 85362306a36Sopenharmony_ci return 0; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_cifail_host: 85662306a36Sopenharmony_ci if (IS_A_TT()) 85762306a36Sopenharmony_ci free_irq(instance->irq, instance); 85862306a36Sopenharmony_cifail_irq: 85962306a36Sopenharmony_ci NCR5380_exit(instance); 86062306a36Sopenharmony_cifail_init: 86162306a36Sopenharmony_ci scsi_host_put(instance); 86262306a36Sopenharmony_cifail_alloc: 86362306a36Sopenharmony_ci if (atari_dma_buffer) 86462306a36Sopenharmony_ci atari_stram_free(atari_dma_buffer); 86562306a36Sopenharmony_ci return error; 86662306a36Sopenharmony_ci} 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_cistatic int __exit atari_scsi_remove(struct platform_device *pdev) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci struct Scsi_Host *instance = platform_get_drvdata(pdev); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci scsi_remove_host(instance); 87362306a36Sopenharmony_ci if (IS_A_TT()) 87462306a36Sopenharmony_ci free_irq(instance->irq, instance); 87562306a36Sopenharmony_ci NCR5380_exit(instance); 87662306a36Sopenharmony_ci scsi_host_put(instance); 87762306a36Sopenharmony_ci if (atari_dma_buffer) 87862306a36Sopenharmony_ci atari_stram_free(atari_dma_buffer); 87962306a36Sopenharmony_ci return 0; 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cistatic struct platform_driver atari_scsi_driver = { 88362306a36Sopenharmony_ci .remove = __exit_p(atari_scsi_remove), 88462306a36Sopenharmony_ci .driver = { 88562306a36Sopenharmony_ci .name = DRV_MODULE_NAME, 88662306a36Sopenharmony_ci }, 88762306a36Sopenharmony_ci}; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cimodule_platform_driver_probe(atari_scsi_driver, atari_scsi_probe); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ciMODULE_ALIAS("platform:" DRV_MODULE_NAME); 89262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 893