18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * atari_scsi.c -- Device dependent functions for the Atari generic SCSI port 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Loosely based on the work of Robert De Vries' team and added: 78c2ecf20Sopenharmony_ci * - working real DMA 88c2ecf20Sopenharmony_ci * - Falcon support (untested yet!) ++bjoern fixed and now it works 98c2ecf20Sopenharmony_ci * - lots of extensions and bug fixes. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 128c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 138c2ecf20Sopenharmony_ci * for more details. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * Notes for Falcon SCSI DMA 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * The 5380 device is one of several that all share the DMA chip. Hence 218c2ecf20Sopenharmony_ci * "locking" and "unlocking" access to this chip is required. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Two possible schemes for ST DMA acquisition by atari_scsi are: 248c2ecf20Sopenharmony_ci * 1) The lock is taken for each command separately (i.e. can_queue == 1). 258c2ecf20Sopenharmony_ci * 2) The lock is taken when the first command arrives and released 268c2ecf20Sopenharmony_ci * when the last command is finished (i.e. can_queue > 1). 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * The first alternative limits SCSI bus utilization, since interleaving 298c2ecf20Sopenharmony_ci * commands is not possible. The second gives better performance but is 308c2ecf20Sopenharmony_ci * unfair to other drivers needing to use the ST DMA chip. In order to 318c2ecf20Sopenharmony_ci * allow the IDE and floppy drivers equal access to the ST DMA chip 328c2ecf20Sopenharmony_ci * the default is can_queue == 1. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/module.h> 368c2ecf20Sopenharmony_ci#include <linux/types.h> 378c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 388c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 398c2ecf20Sopenharmony_ci#include <linux/init.h> 408c2ecf20Sopenharmony_ci#include <linux/nvram.h> 418c2ecf20Sopenharmony_ci#include <linux/bitops.h> 428c2ecf20Sopenharmony_ci#include <linux/wait.h> 438c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include <asm/setup.h> 468c2ecf20Sopenharmony_ci#include <asm/atarihw.h> 478c2ecf20Sopenharmony_ci#include <asm/atariints.h> 488c2ecf20Sopenharmony_ci#include <asm/atari_stdma.h> 498c2ecf20Sopenharmony_ci#include <asm/atari_stram.h> 508c2ecf20Sopenharmony_ci#include <asm/io.h> 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define DMA_MIN_SIZE 32 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* Definitions for the core NCR5380 driver. */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define NCR5380_implementation_fields /* none */ 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic u8 (*atari_scsi_reg_read)(unsigned int); 618c2ecf20Sopenharmony_cistatic void (*atari_scsi_reg_write)(unsigned int, u8); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define NCR5380_read(reg) atari_scsi_reg_read(reg) 648c2ecf20Sopenharmony_ci#define NCR5380_write(reg, value) atari_scsi_reg_write(reg, value) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define NCR5380_queue_command atari_scsi_queue_command 678c2ecf20Sopenharmony_ci#define NCR5380_abort atari_scsi_abort 688c2ecf20Sopenharmony_ci#define NCR5380_info atari_scsi_info 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define NCR5380_dma_xfer_len atari_scsi_dma_xfer_len 718c2ecf20Sopenharmony_ci#define NCR5380_dma_recv_setup atari_scsi_dma_recv_setup 728c2ecf20Sopenharmony_ci#define NCR5380_dma_send_setup atari_scsi_dma_send_setup 738c2ecf20Sopenharmony_ci#define NCR5380_dma_residual atari_scsi_dma_residual 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define NCR5380_acquire_dma_irq(instance) falcon_get_lock(instance) 768c2ecf20Sopenharmony_ci#define NCR5380_release_dma_irq(instance) falcon_release_lock() 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#include "NCR5380.h" 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define IS_A_TT() ATARIHW_PRESENT(TT_SCSI) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define SCSI_DMA_WRITE_P(elt,val) \ 848c2ecf20Sopenharmony_ci do { \ 858c2ecf20Sopenharmony_ci unsigned long v = val; \ 868c2ecf20Sopenharmony_ci tt_scsi_dma.elt##_lo = v & 0xff; \ 878c2ecf20Sopenharmony_ci v >>= 8; \ 888c2ecf20Sopenharmony_ci tt_scsi_dma.elt##_lmd = v & 0xff; \ 898c2ecf20Sopenharmony_ci v >>= 8; \ 908c2ecf20Sopenharmony_ci tt_scsi_dma.elt##_hmd = v & 0xff; \ 918c2ecf20Sopenharmony_ci v >>= 8; \ 928c2ecf20Sopenharmony_ci tt_scsi_dma.elt##_hi = v & 0xff; \ 938c2ecf20Sopenharmony_ci } while(0) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define SCSI_DMA_READ_P(elt) \ 968c2ecf20Sopenharmony_ci (((((((unsigned long)tt_scsi_dma.elt##_hi << 8) | \ 978c2ecf20Sopenharmony_ci (unsigned long)tt_scsi_dma.elt##_hmd) << 8) | \ 988c2ecf20Sopenharmony_ci (unsigned long)tt_scsi_dma.elt##_lmd) << 8) | \ 998c2ecf20Sopenharmony_ci (unsigned long)tt_scsi_dma.elt##_lo) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic inline void SCSI_DMA_SETADR(unsigned long adr) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci st_dma.dma_lo = (unsigned char)adr; 1058c2ecf20Sopenharmony_ci MFPDELAY(); 1068c2ecf20Sopenharmony_ci adr >>= 8; 1078c2ecf20Sopenharmony_ci st_dma.dma_md = (unsigned char)adr; 1088c2ecf20Sopenharmony_ci MFPDELAY(); 1098c2ecf20Sopenharmony_ci adr >>= 8; 1108c2ecf20Sopenharmony_ci st_dma.dma_hi = (unsigned char)adr; 1118c2ecf20Sopenharmony_ci MFPDELAY(); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic inline unsigned long SCSI_DMA_GETADR(void) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci unsigned long adr; 1178c2ecf20Sopenharmony_ci adr = st_dma.dma_lo; 1188c2ecf20Sopenharmony_ci MFPDELAY(); 1198c2ecf20Sopenharmony_ci adr |= (st_dma.dma_md & 0xff) << 8; 1208c2ecf20Sopenharmony_ci MFPDELAY(); 1218c2ecf20Sopenharmony_ci adr |= (st_dma.dma_hi & 0xff) << 16; 1228c2ecf20Sopenharmony_ci MFPDELAY(); 1238c2ecf20Sopenharmony_ci return adr; 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic void atari_scsi_fetch_restbytes(void); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic unsigned long atari_dma_residual, atari_dma_startaddr; 1298c2ecf20Sopenharmony_cistatic short atari_dma_active; 1308c2ecf20Sopenharmony_ci/* pointer to the dribble buffer */ 1318c2ecf20Sopenharmony_cistatic char *atari_dma_buffer; 1328c2ecf20Sopenharmony_ci/* precalculated physical address of the dribble buffer */ 1338c2ecf20Sopenharmony_cistatic unsigned long atari_dma_phys_buffer; 1348c2ecf20Sopenharmony_ci/* != 0 tells the Falcon int handler to copy data from the dribble buffer */ 1358c2ecf20Sopenharmony_cistatic char *atari_dma_orig_addr; 1368c2ecf20Sopenharmony_ci/* size of the dribble buffer; 4k seems enough, since the Falcon cannot use 1378c2ecf20Sopenharmony_ci * scatter-gather anyway, so most transfers are 1024 byte only. In the rare 1388c2ecf20Sopenharmony_ci * cases where requests to physical contiguous buffers have been merged, this 1398c2ecf20Sopenharmony_ci * request is <= 4k (one page). So I don't think we have to split transfers 1408c2ecf20Sopenharmony_ci * just due to this buffer size... 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ci#define STRAM_BUFFER_SIZE (4096) 1438c2ecf20Sopenharmony_ci/* mask for address bits that can't be used with the ST-DMA */ 1448c2ecf20Sopenharmony_cistatic unsigned long atari_dma_stram_mask; 1458c2ecf20Sopenharmony_ci#define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0) 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic int setup_can_queue = -1; 1488c2ecf20Sopenharmony_cimodule_param(setup_can_queue, int, 0); 1498c2ecf20Sopenharmony_cistatic int setup_cmd_per_lun = -1; 1508c2ecf20Sopenharmony_cimodule_param(setup_cmd_per_lun, int, 0); 1518c2ecf20Sopenharmony_cistatic int setup_sg_tablesize = -1; 1528c2ecf20Sopenharmony_cimodule_param(setup_sg_tablesize, int, 0); 1538c2ecf20Sopenharmony_cistatic int setup_hostid = -1; 1548c2ecf20Sopenharmony_cimodule_param(setup_hostid, int, 0); 1558c2ecf20Sopenharmony_cistatic int setup_toshiba_delay = -1; 1568c2ecf20Sopenharmony_cimodule_param(setup_toshiba_delay, int, 0); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic int scsi_dma_is_ignored_buserr(unsigned char dma_stat) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci int i; 1628c2ecf20Sopenharmony_ci unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (dma_stat & 0x01) { 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* A bus error happens when DMA-ing from the last page of a 1678c2ecf20Sopenharmony_ci * physical memory chunk (DMA prefetch!), but that doesn't hurt. 1688c2ecf20Sopenharmony_ci * Check for this case: 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci for (i = 0; i < m68k_num_memory; ++i) { 1728c2ecf20Sopenharmony_ci end_addr = m68k_memory[i].addr + m68k_memory[i].size; 1738c2ecf20Sopenharmony_ci if (end_addr <= addr && addr <= end_addr + 4) 1748c2ecf20Sopenharmony_ci return 1; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci return 0; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic irqreturn_t scsi_tt_intr(int irq, void *dev) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct Scsi_Host *instance = dev; 1848c2ecf20Sopenharmony_ci struct NCR5380_hostdata *hostdata = shost_priv(instance); 1858c2ecf20Sopenharmony_ci int dma_stat; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci dma_stat = tt_scsi_dma.dma_ctrl; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci dsprintk(NDEBUG_INTR, instance, "NCR5380 interrupt, DMA status = %02x\n", 1908c2ecf20Sopenharmony_ci dma_stat & 0xff); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* Look if it was the DMA that has interrupted: First possibility 1938c2ecf20Sopenharmony_ci * is that a bus error occurred... 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_ci if (dma_stat & 0x80) { 1968c2ecf20Sopenharmony_ci if (!scsi_dma_is_ignored_buserr(dma_stat)) { 1978c2ecf20Sopenharmony_ci printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n", 1988c2ecf20Sopenharmony_ci SCSI_DMA_READ_P(dma_addr)); 1998c2ecf20Sopenharmony_ci printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!"); 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* If the DMA is active but not finished, we have the case 2048c2ecf20Sopenharmony_ci * that some other 5380 interrupt occurred within the DMA transfer. 2058c2ecf20Sopenharmony_ci * This means we have residual bytes, if the desired end address 2068c2ecf20Sopenharmony_ci * is not yet reached. Maybe we have to fetch some bytes from the 2078c2ecf20Sopenharmony_ci * rest data register, too. The residual must be calculated from 2088c2ecf20Sopenharmony_ci * the address pointer, not the counter register, because only the 2098c2ecf20Sopenharmony_ci * addr reg counts bytes not yet written and pending in the rest 2108c2ecf20Sopenharmony_ci * data reg! 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { 2138c2ecf20Sopenharmony_ci atari_dma_residual = hostdata->dma_len - 2148c2ecf20Sopenharmony_ci (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n", 2178c2ecf20Sopenharmony_ci atari_dma_residual); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if ((signed int)atari_dma_residual < 0) 2208c2ecf20Sopenharmony_ci atari_dma_residual = 0; 2218c2ecf20Sopenharmony_ci if ((dma_stat & 1) == 0) { 2228c2ecf20Sopenharmony_ci /* 2238c2ecf20Sopenharmony_ci * After read operations, we maybe have to 2248c2ecf20Sopenharmony_ci * transport some rest bytes 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci atari_scsi_fetch_restbytes(); 2278c2ecf20Sopenharmony_ci } else { 2288c2ecf20Sopenharmony_ci /* 2298c2ecf20Sopenharmony_ci * There seems to be a nasty bug in some SCSI-DMA/NCR 2308c2ecf20Sopenharmony_ci * combinations: If a target disconnects while a write 2318c2ecf20Sopenharmony_ci * operation is going on, the address register of the 2328c2ecf20Sopenharmony_ci * DMA may be a few bytes farer than it actually read. 2338c2ecf20Sopenharmony_ci * This is probably due to DMA prefetching and a delay 2348c2ecf20Sopenharmony_ci * between DMA and NCR. Experiments showed that the 2358c2ecf20Sopenharmony_ci * dma_addr is 9 bytes to high, but this could vary. 2368c2ecf20Sopenharmony_ci * The problem is, that the residual is thus calculated 2378c2ecf20Sopenharmony_ci * wrong and the next transfer will start behind where 2388c2ecf20Sopenharmony_ci * it should. So we round up the residual to the next 2398c2ecf20Sopenharmony_ci * multiple of a sector size, if it isn't already a 2408c2ecf20Sopenharmony_ci * multiple and the originally expected transfer size 2418c2ecf20Sopenharmony_ci * was. The latter condition is there to ensure that 2428c2ecf20Sopenharmony_ci * the correction is taken only for "real" data 2438c2ecf20Sopenharmony_ci * transfers and not for, e.g., the parameters of some 2448c2ecf20Sopenharmony_ci * other command. These shouldn't disconnect anyway. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci if (atari_dma_residual & 0x1ff) { 2478c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: DMA bug corrected, " 2488c2ecf20Sopenharmony_ci "difference %ld bytes\n", 2498c2ecf20Sopenharmony_ci 512 - (atari_dma_residual & 0x1ff)); 2508c2ecf20Sopenharmony_ci atari_dma_residual = (atari_dma_residual + 511) & ~0x1ff; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* If the DMA is finished, fetch the rest bytes and turn it off */ 2578c2ecf20Sopenharmony_ci if (dma_stat & 0x40) { 2588c2ecf20Sopenharmony_ci atari_dma_residual = 0; 2598c2ecf20Sopenharmony_ci if ((dma_stat & 1) == 0) 2608c2ecf20Sopenharmony_ci atari_scsi_fetch_restbytes(); 2618c2ecf20Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci NCR5380_intr(irq, dev); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic irqreturn_t scsi_falcon_intr(int irq, void *dev) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci struct Scsi_Host *instance = dev; 2738c2ecf20Sopenharmony_ci struct NCR5380_hostdata *hostdata = shost_priv(instance); 2748c2ecf20Sopenharmony_ci int dma_stat; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Turn off DMA and select sector counter register before 2778c2ecf20Sopenharmony_ci * accessing the status register (Atari recommendation!) 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci st_dma.dma_mode_status = 0x90; 2808c2ecf20Sopenharmony_ci dma_stat = st_dma.dma_mode_status; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* Bit 0 indicates some error in the DMA process... don't know 2838c2ecf20Sopenharmony_ci * what happened exactly (no further docu). 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_ci if (!(dma_stat & 0x01)) { 2868c2ecf20Sopenharmony_ci /* DMA error */ 2878c2ecf20Sopenharmony_ci printk(KERN_CRIT "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR()); 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* If the DMA was active, but now bit 1 is not clear, it is some 2918c2ecf20Sopenharmony_ci * other 5380 interrupt that finishes the DMA transfer. We have to 2928c2ecf20Sopenharmony_ci * calculate the number of residual bytes and give a warning if 2938c2ecf20Sopenharmony_ci * bytes are stuck in the ST-DMA fifo (there's no way to reach them!) 2948c2ecf20Sopenharmony_ci */ 2958c2ecf20Sopenharmony_ci if (atari_dma_active && (dma_stat & 0x02)) { 2968c2ecf20Sopenharmony_ci unsigned long transferred; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci transferred = SCSI_DMA_GETADR() - atari_dma_startaddr; 2998c2ecf20Sopenharmony_ci /* The ST-DMA address is incremented in 2-byte steps, but the 3008c2ecf20Sopenharmony_ci * data are written only in 16-byte chunks. If the number of 3018c2ecf20Sopenharmony_ci * transferred bytes is not divisible by 16, the remainder is 3028c2ecf20Sopenharmony_ci * lost somewhere in outer space. 3038c2ecf20Sopenharmony_ci */ 3048c2ecf20Sopenharmony_ci if (transferred & 15) 3058c2ecf20Sopenharmony_ci printk(KERN_ERR "SCSI DMA error: %ld bytes lost in " 3068c2ecf20Sopenharmony_ci "ST-DMA fifo\n", transferred & 15); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci atari_dma_residual = hostdata->dma_len - transferred; 3098c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n", 3108c2ecf20Sopenharmony_ci atari_dma_residual); 3118c2ecf20Sopenharmony_ci } else 3128c2ecf20Sopenharmony_ci atari_dma_residual = 0; 3138c2ecf20Sopenharmony_ci atari_dma_active = 0; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (atari_dma_orig_addr) { 3168c2ecf20Sopenharmony_ci /* If the dribble buffer was used on a read operation, copy the DMA-ed 3178c2ecf20Sopenharmony_ci * data to the original destination address. 3188c2ecf20Sopenharmony_ci */ 3198c2ecf20Sopenharmony_ci memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr), 3208c2ecf20Sopenharmony_ci hostdata->dma_len - atari_dma_residual); 3218c2ecf20Sopenharmony_ci atari_dma_orig_addr = NULL; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci NCR5380_intr(irq, dev); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic void atari_scsi_fetch_restbytes(void) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci int nr; 3338c2ecf20Sopenharmony_ci char *src, *dst; 3348c2ecf20Sopenharmony_ci unsigned long phys_dst; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* fetch rest bytes in the DMA register */ 3378c2ecf20Sopenharmony_ci phys_dst = SCSI_DMA_READ_P(dma_addr); 3388c2ecf20Sopenharmony_ci nr = phys_dst & 3; 3398c2ecf20Sopenharmony_ci if (nr) { 3408c2ecf20Sopenharmony_ci /* there are 'nr' bytes left for the last long address 3418c2ecf20Sopenharmony_ci before the DMA pointer */ 3428c2ecf20Sopenharmony_ci phys_dst ^= nr; 3438c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, "SCSI DMA: there are %d rest bytes for phys addr 0x%08lx", 3448c2ecf20Sopenharmony_ci nr, phys_dst); 3458c2ecf20Sopenharmony_ci /* The content of the DMA pointer is a physical address! */ 3468c2ecf20Sopenharmony_ci dst = phys_to_virt(phys_dst); 3478c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, " = virt addr %p\n", dst); 3488c2ecf20Sopenharmony_ci for (src = (char *)&tt_scsi_dma.dma_restdata; nr != 0; --nr) 3498c2ecf20Sopenharmony_ci *dst++ = *src++; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci/* This function releases the lock on the DMA chip if there is no 3558c2ecf20Sopenharmony_ci * connected command and the disconnected queue is empty. 3568c2ecf20Sopenharmony_ci */ 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void falcon_release_lock(void) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci if (IS_A_TT()) 3618c2ecf20Sopenharmony_ci return; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (stdma_is_locked_by(scsi_falcon_intr)) 3648c2ecf20Sopenharmony_ci stdma_release(); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci/* This function manages the locking of the ST-DMA. 3688c2ecf20Sopenharmony_ci * If the DMA isn't locked already for SCSI, it tries to lock it by 3698c2ecf20Sopenharmony_ci * calling stdma_lock(). But if the DMA is locked by the SCSI code and 3708c2ecf20Sopenharmony_ci * there are other drivers waiting for the chip, we do not issue the 3718c2ecf20Sopenharmony_ci * command immediately but tell the SCSI mid-layer to defer. 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic int falcon_get_lock(struct Scsi_Host *instance) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci if (IS_A_TT()) 3778c2ecf20Sopenharmony_ci return 1; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (stdma_is_locked_by(scsi_falcon_intr) && 3808c2ecf20Sopenharmony_ci instance->hostt->can_queue > 1) 3818c2ecf20Sopenharmony_ci return 1; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci if (in_interrupt()) 3848c2ecf20Sopenharmony_ci return stdma_try_lock(scsi_falcon_intr, instance); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci stdma_lock(scsi_falcon_intr, instance); 3878c2ecf20Sopenharmony_ci return 1; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci#ifndef MODULE 3918c2ecf20Sopenharmony_cistatic int __init atari_scsi_setup(char *str) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci /* Format of atascsi parameter is: 3948c2ecf20Sopenharmony_ci * atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> 3958c2ecf20Sopenharmony_ci * Defaults depend on TT or Falcon, determined at run time. 3968c2ecf20Sopenharmony_ci * Negative values mean don't change. 3978c2ecf20Sopenharmony_ci */ 3988c2ecf20Sopenharmony_ci int ints[8]; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci get_options(str, ARRAY_SIZE(ints), ints); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci if (ints[0] < 1) { 4038c2ecf20Sopenharmony_ci printk("atari_scsi_setup: no arguments!\n"); 4048c2ecf20Sopenharmony_ci return 0; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci if (ints[0] >= 1) 4078c2ecf20Sopenharmony_ci setup_can_queue = ints[1]; 4088c2ecf20Sopenharmony_ci if (ints[0] >= 2) 4098c2ecf20Sopenharmony_ci setup_cmd_per_lun = ints[2]; 4108c2ecf20Sopenharmony_ci if (ints[0] >= 3) 4118c2ecf20Sopenharmony_ci setup_sg_tablesize = ints[3]; 4128c2ecf20Sopenharmony_ci if (ints[0] >= 4) 4138c2ecf20Sopenharmony_ci setup_hostid = ints[4]; 4148c2ecf20Sopenharmony_ci /* ints[5] (use_tagged_queuing) is ignored */ 4158c2ecf20Sopenharmony_ci /* ints[6] (use_pdma) is ignored */ 4168c2ecf20Sopenharmony_ci if (ints[0] >= 7) 4178c2ecf20Sopenharmony_ci setup_toshiba_delay = ints[7]; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return 1; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci__setup("atascsi=", atari_scsi_setup); 4238c2ecf20Sopenharmony_ci#endif /* !MODULE */ 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic unsigned long atari_scsi_dma_setup(struct NCR5380_hostdata *hostdata, 4268c2ecf20Sopenharmony_ci void *data, unsigned long count, 4278c2ecf20Sopenharmony_ci int dir) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci unsigned long addr = virt_to_phys(data); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, "scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, dir = %d\n", 4328c2ecf20Sopenharmony_ci hostdata->host->host_no, data, addr, count, dir); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (!IS_A_TT() && !STRAM_ADDR(addr)) { 4358c2ecf20Sopenharmony_ci /* If we have a non-DMAable address on a Falcon, use the dribble 4368c2ecf20Sopenharmony_ci * buffer; 'orig_addr' != 0 in the read case tells the interrupt 4378c2ecf20Sopenharmony_ci * handler to copy data from the dribble buffer to the originally 4388c2ecf20Sopenharmony_ci * wanted address. 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci if (dir) 4418c2ecf20Sopenharmony_ci memcpy(atari_dma_buffer, data, count); 4428c2ecf20Sopenharmony_ci else 4438c2ecf20Sopenharmony_ci atari_dma_orig_addr = data; 4448c2ecf20Sopenharmony_ci addr = atari_dma_phys_buffer; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci atari_dma_startaddr = addr; /* Needed for calculating residual later. */ 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci /* Cache cleanup stuff: On writes, push any dirty cache out before sending 4508c2ecf20Sopenharmony_ci * it to the peripheral. (Must be done before DMA setup, since at least 4518c2ecf20Sopenharmony_ci * the ST-DMA begins to fill internal buffers right after setup. For 4528c2ecf20Sopenharmony_ci * reads, invalidate any cache, may be altered after DMA without CPU 4538c2ecf20Sopenharmony_ci * knowledge. 4548c2ecf20Sopenharmony_ci * 4558c2ecf20Sopenharmony_ci * ++roman: For the Medusa, there's no need at all for that cache stuff, 4568c2ecf20Sopenharmony_ci * because the hardware does bus snooping (fine!). 4578c2ecf20Sopenharmony_ci */ 4588c2ecf20Sopenharmony_ci dma_cache_maintenance(addr, count, dir); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci if (IS_A_TT()) { 4618c2ecf20Sopenharmony_ci tt_scsi_dma.dma_ctrl = dir; 4628c2ecf20Sopenharmony_ci SCSI_DMA_WRITE_P(dma_addr, addr); 4638c2ecf20Sopenharmony_ci SCSI_DMA_WRITE_P(dma_cnt, count); 4648c2ecf20Sopenharmony_ci tt_scsi_dma.dma_ctrl = dir | 2; 4658c2ecf20Sopenharmony_ci } else { /* ! IS_A_TT */ 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* set address */ 4688c2ecf20Sopenharmony_ci SCSI_DMA_SETADR(addr); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci /* toggle direction bit to clear FIFO and set DMA direction */ 4718c2ecf20Sopenharmony_ci dir <<= 8; 4728c2ecf20Sopenharmony_ci st_dma.dma_mode_status = 0x90 | dir; 4738c2ecf20Sopenharmony_ci st_dma.dma_mode_status = 0x90 | (dir ^ 0x100); 4748c2ecf20Sopenharmony_ci st_dma.dma_mode_status = 0x90 | dir; 4758c2ecf20Sopenharmony_ci udelay(40); 4768c2ecf20Sopenharmony_ci /* On writes, round up the transfer length to the next multiple of 512 4778c2ecf20Sopenharmony_ci * (see also comment at atari_dma_xfer_len()). */ 4788c2ecf20Sopenharmony_ci st_dma.fdc_acces_seccount = (count + (dir ? 511 : 0)) >> 9; 4798c2ecf20Sopenharmony_ci udelay(40); 4808c2ecf20Sopenharmony_ci st_dma.dma_mode_status = 0x10 | dir; 4818c2ecf20Sopenharmony_ci udelay(40); 4828c2ecf20Sopenharmony_ci /* need not restore value of dir, only boolean value is tested */ 4838c2ecf20Sopenharmony_ci atari_dma_active = 1; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci return count; 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic inline int atari_scsi_dma_recv_setup(struct NCR5380_hostdata *hostdata, 4908c2ecf20Sopenharmony_ci unsigned char *data, int count) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci return atari_scsi_dma_setup(hostdata, data, count, 0); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cistatic inline int atari_scsi_dma_send_setup(struct NCR5380_hostdata *hostdata, 4968c2ecf20Sopenharmony_ci unsigned char *data, int count) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci return atari_scsi_dma_setup(hostdata, data, count, 1); 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic int atari_scsi_dma_residual(struct NCR5380_hostdata *hostdata) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci return atari_dma_residual; 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci#define CMD_SURELY_BLOCK_MODE 0 5088c2ecf20Sopenharmony_ci#define CMD_SURELY_BYTE_MODE 1 5098c2ecf20Sopenharmony_ci#define CMD_MODE_UNKNOWN 2 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_cistatic int falcon_classify_cmd(struct scsi_cmnd *cmd) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci unsigned char opcode = cmd->cmnd[0]; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci if (opcode == READ_DEFECT_DATA || opcode == READ_LONG || 5168c2ecf20Sopenharmony_ci opcode == READ_BUFFER) 5178c2ecf20Sopenharmony_ci return CMD_SURELY_BYTE_MODE; 5188c2ecf20Sopenharmony_ci else if (opcode == READ_6 || opcode == READ_10 || 5198c2ecf20Sopenharmony_ci opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE || 5208c2ecf20Sopenharmony_ci opcode == RECOVER_BUFFERED_DATA) { 5218c2ecf20Sopenharmony_ci /* In case of a sequential-access target (tape), special care is 5228c2ecf20Sopenharmony_ci * needed here: The transfer is block-mode only if the 'fixed' bit is 5238c2ecf20Sopenharmony_ci * set! */ 5248c2ecf20Sopenharmony_ci if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1)) 5258c2ecf20Sopenharmony_ci return CMD_SURELY_BYTE_MODE; 5268c2ecf20Sopenharmony_ci else 5278c2ecf20Sopenharmony_ci return CMD_SURELY_BLOCK_MODE; 5288c2ecf20Sopenharmony_ci } else 5298c2ecf20Sopenharmony_ci return CMD_MODE_UNKNOWN; 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci/* This function calculates the number of bytes that can be transferred via 5348c2ecf20Sopenharmony_ci * DMA. On the TT, this is arbitrary, but on the Falcon we have to use the 5358c2ecf20Sopenharmony_ci * ST-DMA chip. There are only multiples of 512 bytes possible and max. 5368c2ecf20Sopenharmony_ci * 255*512 bytes :-( This means also, that defining READ_OVERRUNS is not 5378c2ecf20Sopenharmony_ci * possible on the Falcon, since that would require to program the DMA for 5388c2ecf20Sopenharmony_ci * n*512 - atari_read_overrun bytes. But it seems that the Falcon doesn't have 5398c2ecf20Sopenharmony_ci * the overrun problem, so this question is academic :-) 5408c2ecf20Sopenharmony_ci */ 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic int atari_scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, 5438c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci int wanted_len = cmd->SCp.this_residual; 5468c2ecf20Sopenharmony_ci int possible_len, limit; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci if (wanted_len < DMA_MIN_SIZE) 5498c2ecf20Sopenharmony_ci return 0; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci if (IS_A_TT()) 5528c2ecf20Sopenharmony_ci /* TT SCSI DMA can transfer arbitrary #bytes */ 5538c2ecf20Sopenharmony_ci return wanted_len; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max. 5568c2ecf20Sopenharmony_ci * 255*512 bytes, but this should be enough) 5578c2ecf20Sopenharmony_ci * 5588c2ecf20Sopenharmony_ci * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands 5598c2ecf20Sopenharmony_ci * that return a number of bytes which cannot be known beforehand. In this 5608c2ecf20Sopenharmony_ci * case, the given transfer length is an "allocation length". Now it 5618c2ecf20Sopenharmony_ci * can happen that this allocation length is a multiple of 512 bytes and 5628c2ecf20Sopenharmony_ci * the DMA is used. But if not n*512 bytes really arrive, some input data 5638c2ecf20Sopenharmony_ci * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish 5648c2ecf20Sopenharmony_ci * between commands that do block transfers and those that do byte 5658c2ecf20Sopenharmony_ci * transfers. But this isn't easy... there are lots of vendor specific 5668c2ecf20Sopenharmony_ci * commands, and the user can issue any command via the 5678c2ecf20Sopenharmony_ci * SCSI_IOCTL_SEND_COMMAND. 5688c2ecf20Sopenharmony_ci * 5698c2ecf20Sopenharmony_ci * The solution: We classify SCSI commands in 1) surely block-mode cmd.s, 5708c2ecf20Sopenharmony_ci * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1) 5718c2ecf20Sopenharmony_ci * and 3), the thing to do is obvious: allow any number of blocks via DMA 5728c2ecf20Sopenharmony_ci * or none. In case 2), we apply some heuristic: Byte mode is assumed if 5738c2ecf20Sopenharmony_ci * the transfer (allocation) length is < 1024, hoping that no cmd. not 5748c2ecf20Sopenharmony_ci * explicitly known as byte mode have such big allocation lengths... 5758c2ecf20Sopenharmony_ci * BTW, all the discussion above applies only to reads. DMA writes are 5768c2ecf20Sopenharmony_ci * unproblematic anyways, since the targets aborts the transfer after 5778c2ecf20Sopenharmony_ci * receiving a sufficient number of bytes. 5788c2ecf20Sopenharmony_ci * 5798c2ecf20Sopenharmony_ci * Another point: If the transfer is from/to an non-ST-RAM address, we 5808c2ecf20Sopenharmony_ci * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes. 5818c2ecf20Sopenharmony_ci */ 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (cmd->sc_data_direction == DMA_TO_DEVICE) { 5848c2ecf20Sopenharmony_ci /* Write operation can always use the DMA, but the transfer size must 5858c2ecf20Sopenharmony_ci * be rounded up to the next multiple of 512 (atari_dma_setup() does 5868c2ecf20Sopenharmony_ci * this). 5878c2ecf20Sopenharmony_ci */ 5888c2ecf20Sopenharmony_ci possible_len = wanted_len; 5898c2ecf20Sopenharmony_ci } else { 5908c2ecf20Sopenharmony_ci /* Read operations: if the wanted transfer length is not a multiple of 5918c2ecf20Sopenharmony_ci * 512, we cannot use DMA, since the ST-DMA cannot split transfers 5928c2ecf20Sopenharmony_ci * (no interrupt on DMA finished!) 5938c2ecf20Sopenharmony_ci */ 5948c2ecf20Sopenharmony_ci if (wanted_len & 0x1ff) 5958c2ecf20Sopenharmony_ci possible_len = 0; 5968c2ecf20Sopenharmony_ci else { 5978c2ecf20Sopenharmony_ci /* Now classify the command (see above) and decide whether it is 5988c2ecf20Sopenharmony_ci * allowed to do DMA at all */ 5998c2ecf20Sopenharmony_ci switch (falcon_classify_cmd(cmd)) { 6008c2ecf20Sopenharmony_ci case CMD_SURELY_BLOCK_MODE: 6018c2ecf20Sopenharmony_ci possible_len = wanted_len; 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci case CMD_SURELY_BYTE_MODE: 6048c2ecf20Sopenharmony_ci possible_len = 0; /* DMA prohibited */ 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci case CMD_MODE_UNKNOWN: 6078c2ecf20Sopenharmony_ci default: 6088c2ecf20Sopenharmony_ci /* For unknown commands assume block transfers if the transfer 6098c2ecf20Sopenharmony_ci * size/allocation length is >= 1024 */ 6108c2ecf20Sopenharmony_ci possible_len = (wanted_len < 1024) ? 0 : wanted_len; 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci /* Last step: apply the hard limit on DMA transfers */ 6178c2ecf20Sopenharmony_ci limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ? 6188c2ecf20Sopenharmony_ci STRAM_BUFFER_SIZE : 255*512; 6198c2ecf20Sopenharmony_ci if (possible_len > limit) 6208c2ecf20Sopenharmony_ci possible_len = limit; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (possible_len != wanted_len) 6238c2ecf20Sopenharmony_ci dprintk(NDEBUG_DMA, "DMA transfer now %d bytes instead of %d\n", 6248c2ecf20Sopenharmony_ci possible_len, wanted_len); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci return possible_len; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci/* NCR5380 register access functions 6318c2ecf20Sopenharmony_ci * 6328c2ecf20Sopenharmony_ci * There are separate functions for TT and Falcon, because the access 6338c2ecf20Sopenharmony_ci * methods are quite different. The calling macros NCR5380_read and 6348c2ecf20Sopenharmony_ci * NCR5380_write call these functions via function pointers. 6358c2ecf20Sopenharmony_ci */ 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic u8 atari_scsi_tt_reg_read(unsigned int reg) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci return tt_scsi_regp[reg * 2]; 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_cistatic void atari_scsi_tt_reg_write(unsigned int reg, u8 value) 6438c2ecf20Sopenharmony_ci{ 6448c2ecf20Sopenharmony_ci tt_scsi_regp[reg * 2] = value; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic u8 atari_scsi_falcon_reg_read(unsigned int reg) 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci unsigned long flags; 6508c2ecf20Sopenharmony_ci u8 result; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci reg += 0x88; 6538c2ecf20Sopenharmony_ci local_irq_save(flags); 6548c2ecf20Sopenharmony_ci dma_wd.dma_mode_status = (u_short)reg; 6558c2ecf20Sopenharmony_ci result = (u8)dma_wd.fdc_acces_seccount; 6568c2ecf20Sopenharmony_ci local_irq_restore(flags); 6578c2ecf20Sopenharmony_ci return result; 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic void atari_scsi_falcon_reg_write(unsigned int reg, u8 value) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci unsigned long flags; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci reg += 0x88; 6658c2ecf20Sopenharmony_ci local_irq_save(flags); 6668c2ecf20Sopenharmony_ci dma_wd.dma_mode_status = (u_short)reg; 6678c2ecf20Sopenharmony_ci dma_wd.fdc_acces_seccount = (u_short)value; 6688c2ecf20Sopenharmony_ci local_irq_restore(flags); 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci#include "NCR5380.c" 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_cistatic int atari_scsi_host_reset(struct scsi_cmnd *cmd) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci int rv; 6778c2ecf20Sopenharmony_ci unsigned long flags; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci local_irq_save(flags); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* Abort a maybe active DMA transfer */ 6828c2ecf20Sopenharmony_ci if (IS_A_TT()) { 6838c2ecf20Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 6848c2ecf20Sopenharmony_ci } else { 6858c2ecf20Sopenharmony_ci if (stdma_is_locked_by(scsi_falcon_intr)) 6868c2ecf20Sopenharmony_ci st_dma.dma_mode_status = 0x90; 6878c2ecf20Sopenharmony_ci atari_dma_active = 0; 6888c2ecf20Sopenharmony_ci atari_dma_orig_addr = NULL; 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci rv = NCR5380_host_reset(cmd); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* The 5380 raises its IRQ line while _RST is active but the ST DMA 6948c2ecf20Sopenharmony_ci * "lock" has been released so this interrupt may end up handled by 6958c2ecf20Sopenharmony_ci * floppy or IDE driver (if one of them holds the lock). The NCR5380 6968c2ecf20Sopenharmony_ci * interrupt flag has been cleared already. 6978c2ecf20Sopenharmony_ci */ 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci local_irq_restore(flags); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci return rv; 7028c2ecf20Sopenharmony_ci} 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci#define DRV_MODULE_NAME "atari_scsi" 7058c2ecf20Sopenharmony_ci#define PFX DRV_MODULE_NAME ": " 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cistatic struct scsi_host_template atari_scsi_template = { 7088c2ecf20Sopenharmony_ci .module = THIS_MODULE, 7098c2ecf20Sopenharmony_ci .proc_name = DRV_MODULE_NAME, 7108c2ecf20Sopenharmony_ci .name = "Atari native SCSI", 7118c2ecf20Sopenharmony_ci .info = atari_scsi_info, 7128c2ecf20Sopenharmony_ci .queuecommand = atari_scsi_queue_command, 7138c2ecf20Sopenharmony_ci .eh_abort_handler = atari_scsi_abort, 7148c2ecf20Sopenharmony_ci .eh_host_reset_handler = atari_scsi_host_reset, 7158c2ecf20Sopenharmony_ci .this_id = 7, 7168c2ecf20Sopenharmony_ci .cmd_per_lun = 2, 7178c2ecf20Sopenharmony_ci .dma_boundary = PAGE_SIZE - 1, 7188c2ecf20Sopenharmony_ci .cmd_size = NCR5380_CMD_SIZE, 7198c2ecf20Sopenharmony_ci}; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_cistatic int __init atari_scsi_probe(struct platform_device *pdev) 7228c2ecf20Sopenharmony_ci{ 7238c2ecf20Sopenharmony_ci struct Scsi_Host *instance; 7248c2ecf20Sopenharmony_ci int error; 7258c2ecf20Sopenharmony_ci struct resource *irq; 7268c2ecf20Sopenharmony_ci int host_flags = 0; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 7298c2ecf20Sopenharmony_ci if (!irq) 7308c2ecf20Sopenharmony_ci return -ENODEV; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci if (ATARIHW_PRESENT(TT_SCSI)) { 7338c2ecf20Sopenharmony_ci atari_scsi_reg_read = atari_scsi_tt_reg_read; 7348c2ecf20Sopenharmony_ci atari_scsi_reg_write = atari_scsi_tt_reg_write; 7358c2ecf20Sopenharmony_ci } else { 7368c2ecf20Sopenharmony_ci atari_scsi_reg_read = atari_scsi_falcon_reg_read; 7378c2ecf20Sopenharmony_ci atari_scsi_reg_write = atari_scsi_falcon_reg_write; 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if (ATARIHW_PRESENT(TT_SCSI)) { 7418c2ecf20Sopenharmony_ci atari_scsi_template.can_queue = 16; 7428c2ecf20Sopenharmony_ci atari_scsi_template.sg_tablesize = SG_ALL; 7438c2ecf20Sopenharmony_ci } else { 7448c2ecf20Sopenharmony_ci atari_scsi_template.can_queue = 1; 7458c2ecf20Sopenharmony_ci atari_scsi_template.sg_tablesize = 1; 7468c2ecf20Sopenharmony_ci } 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (setup_can_queue > 0) 7498c2ecf20Sopenharmony_ci atari_scsi_template.can_queue = setup_can_queue; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (setup_cmd_per_lun > 0) 7528c2ecf20Sopenharmony_ci atari_scsi_template.cmd_per_lun = setup_cmd_per_lun; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci /* Don't increase sg_tablesize on Falcon! */ 7558c2ecf20Sopenharmony_ci if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0) 7568c2ecf20Sopenharmony_ci atari_scsi_template.sg_tablesize = setup_sg_tablesize; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci if (setup_hostid >= 0) { 7598c2ecf20Sopenharmony_ci atari_scsi_template.this_id = setup_hostid & 7; 7608c2ecf20Sopenharmony_ci } else if (IS_REACHABLE(CONFIG_NVRAM)) { 7618c2ecf20Sopenharmony_ci /* Test if a host id is set in the NVRam */ 7628c2ecf20Sopenharmony_ci if (ATARIHW_PRESENT(TT_CLK)) { 7638c2ecf20Sopenharmony_ci unsigned char b; 7648c2ecf20Sopenharmony_ci loff_t offset = 16; 7658c2ecf20Sopenharmony_ci ssize_t count = nvram_read(&b, 1, &offset); 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci /* Arbitration enabled? (for TOS) 7688c2ecf20Sopenharmony_ci * If yes, use configured host ID 7698c2ecf20Sopenharmony_ci */ 7708c2ecf20Sopenharmony_ci if ((count == 1) && (b & 0x80)) 7718c2ecf20Sopenharmony_ci atari_scsi_template.this_id = b & 7; 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* If running on a Falcon and if there's TT-Ram (i.e., more than one 7768c2ecf20Sopenharmony_ci * memory block, since there's always ST-Ram in a Falcon), then 7778c2ecf20Sopenharmony_ci * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers 7788c2ecf20Sopenharmony_ci * from/to alternative Ram. 7798c2ecf20Sopenharmony_ci */ 7808c2ecf20Sopenharmony_ci if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) && 7818c2ecf20Sopenharmony_ci m68k_realnum_memory > 1) { 7828c2ecf20Sopenharmony_ci atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); 7838c2ecf20Sopenharmony_ci if (!atari_dma_buffer) { 7848c2ecf20Sopenharmony_ci pr_err(PFX "can't allocate ST-RAM double buffer\n"); 7858c2ecf20Sopenharmony_ci return -ENOMEM; 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); 7888c2ecf20Sopenharmony_ci atari_dma_orig_addr = NULL; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci instance = scsi_host_alloc(&atari_scsi_template, 7928c2ecf20Sopenharmony_ci sizeof(struct NCR5380_hostdata)); 7938c2ecf20Sopenharmony_ci if (!instance) { 7948c2ecf20Sopenharmony_ci error = -ENOMEM; 7958c2ecf20Sopenharmony_ci goto fail_alloc; 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci instance->irq = irq->start; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP; 8018c2ecf20Sopenharmony_ci host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci error = NCR5380_init(instance, host_flags); 8048c2ecf20Sopenharmony_ci if (error) 8058c2ecf20Sopenharmony_ci goto fail_init; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (IS_A_TT()) { 8088c2ecf20Sopenharmony_ci error = request_irq(instance->irq, scsi_tt_intr, 0, 8098c2ecf20Sopenharmony_ci "NCR5380", instance); 8108c2ecf20Sopenharmony_ci if (error) { 8118c2ecf20Sopenharmony_ci pr_err(PFX "request irq %d failed, aborting\n", 8128c2ecf20Sopenharmony_ci instance->irq); 8138c2ecf20Sopenharmony_ci goto fail_irq; 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */ 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci tt_scsi_dma.dma_ctrl = 0; 8188c2ecf20Sopenharmony_ci atari_dma_residual = 0; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci /* While the read overruns (described by Drew Eckhardt in 8218c2ecf20Sopenharmony_ci * NCR5380.c) never happened on TTs, they do in fact on the 8228c2ecf20Sopenharmony_ci * Medusa (This was the cause why SCSI didn't work right for 8238c2ecf20Sopenharmony_ci * so long there.) Since handling the overruns slows down 8248c2ecf20Sopenharmony_ci * a bit, I turned the #ifdef's into a runtime condition. 8258c2ecf20Sopenharmony_ci * 8268c2ecf20Sopenharmony_ci * In principle it should be sufficient to do max. 1 byte with 8278c2ecf20Sopenharmony_ci * PIO, but there is another problem on the Medusa with the DMA 8288c2ecf20Sopenharmony_ci * rest data register. So read_overruns is currently set 8298c2ecf20Sopenharmony_ci * to 4 to avoid having transfers that aren't a multiple of 4. 8308c2ecf20Sopenharmony_ci * If the rest data bug is fixed, this can be lowered to 1. 8318c2ecf20Sopenharmony_ci */ 8328c2ecf20Sopenharmony_ci if (MACH_IS_MEDUSA) { 8338c2ecf20Sopenharmony_ci struct NCR5380_hostdata *hostdata = 8348c2ecf20Sopenharmony_ci shost_priv(instance); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci hostdata->read_overruns = 4; 8378c2ecf20Sopenharmony_ci } 8388c2ecf20Sopenharmony_ci } else { 8398c2ecf20Sopenharmony_ci /* Nothing to do for the interrupt: the ST-DMA is initialized 8408c2ecf20Sopenharmony_ci * already. 8418c2ecf20Sopenharmony_ci */ 8428c2ecf20Sopenharmony_ci atari_dma_residual = 0; 8438c2ecf20Sopenharmony_ci atari_dma_active = 0; 8448c2ecf20Sopenharmony_ci atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 8458c2ecf20Sopenharmony_ci : 0xff000000); 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci NCR5380_maybe_reset_bus(instance); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci error = scsi_add_host(instance, NULL); 8518c2ecf20Sopenharmony_ci if (error) 8528c2ecf20Sopenharmony_ci goto fail_host; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, instance); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci scsi_scan_host(instance); 8578c2ecf20Sopenharmony_ci return 0; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_cifail_host: 8608c2ecf20Sopenharmony_ci if (IS_A_TT()) 8618c2ecf20Sopenharmony_ci free_irq(instance->irq, instance); 8628c2ecf20Sopenharmony_cifail_irq: 8638c2ecf20Sopenharmony_ci NCR5380_exit(instance); 8648c2ecf20Sopenharmony_cifail_init: 8658c2ecf20Sopenharmony_ci scsi_host_put(instance); 8668c2ecf20Sopenharmony_cifail_alloc: 8678c2ecf20Sopenharmony_ci if (atari_dma_buffer) 8688c2ecf20Sopenharmony_ci atari_stram_free(atari_dma_buffer); 8698c2ecf20Sopenharmony_ci return error; 8708c2ecf20Sopenharmony_ci} 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_cistatic int __exit atari_scsi_remove(struct platform_device *pdev) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci struct Scsi_Host *instance = platform_get_drvdata(pdev); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci scsi_remove_host(instance); 8778c2ecf20Sopenharmony_ci if (IS_A_TT()) 8788c2ecf20Sopenharmony_ci free_irq(instance->irq, instance); 8798c2ecf20Sopenharmony_ci NCR5380_exit(instance); 8808c2ecf20Sopenharmony_ci scsi_host_put(instance); 8818c2ecf20Sopenharmony_ci if (atari_dma_buffer) 8828c2ecf20Sopenharmony_ci atari_stram_free(atari_dma_buffer); 8838c2ecf20Sopenharmony_ci return 0; 8848c2ecf20Sopenharmony_ci} 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_cistatic struct platform_driver atari_scsi_driver = { 8878c2ecf20Sopenharmony_ci .remove = __exit_p(atari_scsi_remove), 8888c2ecf20Sopenharmony_ci .driver = { 8898c2ecf20Sopenharmony_ci .name = DRV_MODULE_NAME, 8908c2ecf20Sopenharmony_ci }, 8918c2ecf20Sopenharmony_ci}; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_cimodule_platform_driver_probe(atari_scsi_driver, atari_scsi_probe); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:" DRV_MODULE_NAME); 8968c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 897