1/* 2 * sgiwd93.c: SGI WD93 scsi driver. 3 * 4 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 * 1999 Andrew R. Baker (andrewb@uab.edu) 6 * - Support for 2nd SCSI controller on Indigo2 7 * 2001 Florian Lohoff (flo@rfc822.org) 8 * - Delete HPC scatter gather (Read corruption on 9 * multiple disks) 10 * - Cleanup wback cache handling 11 * 12 * (In all truth, Jed Schimmel wrote all this code.) 13 * 14 */ 15#include <linux/init.h> 16#include <linux/types.h> 17#include <linux/mm.h> 18#include <linux/blk.h> 19#include <linux/version.h> 20#include <linux/delay.h> 21#include <linux/spinlock.h> 22 23#include <asm/page.h> 24#include <asm/pgtable.h> 25#include <asm/sgialib.h> 26#include <asm/sgi/sgi.h> 27#include <asm/sgi/sgimc.h> 28#include <asm/sgi/sgihpc.h> 29#include <asm/sgi/sgint23.h> 30#include <asm/irq.h> 31#include <asm/io.h> 32 33#include "scsi.h" 34#include "hosts.h" 35#include "wd33c93.h" 36#include "sgiwd93.h" 37 38#include <linux/stat.h> 39 40struct hpc_chunk { 41 struct hpc_dma_desc desc; 42 u32 _padding; /* align to quadword boundary */ 43}; 44 45struct Scsi_Host *sgiwd93_host = NULL; 46struct Scsi_Host *sgiwd93_host1 = NULL; 47 48/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ 49static inline void write_wd33c93_count(const wd33c93_regs regs, 50 unsigned long value) 51{ 52 *regs.SASR = WD_TRANSFER_COUNT_MSB; 53 mb(); 54 *regs.SCMD = ((value >> 16) & 0xff); 55 *regs.SCMD = ((value >> 8) & 0xff); 56 *regs.SCMD = ((value >> 0) & 0xff); 57 mb(); 58} 59 60static inline unsigned long read_wd33c93_count(const wd33c93_regs regs) 61{ 62 unsigned long value; 63 64 *regs.SASR = WD_TRANSFER_COUNT_MSB; 65 mb(); 66 value = ((*regs.SCMD & 0xff) << 16); 67 value |= ((*regs.SCMD & 0xff) << 8); 68 value |= ((*regs.SCMD & 0xff) << 0); 69 mb(); 70 return value; 71} 72 73static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs) 74{ 75 unsigned long flags; 76 77 spin_lock_irqsave(&io_request_lock, flags); 78 wd33c93_intr((struct Scsi_Host *) dev_id); 79 spin_unlock_irqrestore(&io_request_lock, flags); 80} 81 82#undef DEBUG_DMA 83 84static inline 85void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len) 86{ 87 unsigned long physaddr; 88 unsigned long count; 89 90 physaddr = PHYSADDR(addr); 91 while (len) { 92 /* 93 * even cntinfo could be up to 16383, without 94 * magic only 8192 works correctly 95 */ 96 count = len > 8192 ? 8192 : len; 97 (*hcp)->desc.pbuf = physaddr; 98 (*hcp)->desc.cntinfo = count; 99 (*hcp)++; 100 len -= count; 101 physaddr += count; 102 } 103} 104 105static int dma_setup(Scsi_Cmnd *cmd, int datainp) 106{ 107 struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)cmd->host->hostdata; 108 struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base; 109 struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer; 110 111#ifdef DEBUG_DMA 112 printk("dma_setup: datainp<%d> hcp<%p> ", 113 datainp, hcp); 114#endif 115 116 hdata->dma_dir = datainp; 117 118 /* 119 * wd33c93 shouldn't pass us bogus dma_setups, but 120 * it does:-( The other wd33c93 drivers deal with 121 * it the same way (which isn't that obvious). 122 * IMHO a better fix would be, not to do these 123 * dma setups in the first place 124 */ 125 if (cmd->SCp.ptr == NULL) 126 return 1; 127 128 fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual); 129 130 /* To make sure, if we trip an HPC bug, that we transfer 131 * every single byte, we tag on an extra zero length dma 132 * descriptor at the end of the chain. 133 */ 134 hcp->desc.pbuf = 0; 135 hcp->desc.cntinfo = (HPCDMA_EOX); 136 137#ifdef DEBUG_DMA 138 printk(" HPCGO\n"); 139#endif 140 141 /* Start up the HPC. */ 142 hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer); 143 if(datainp) { 144 dma_cache_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual); 145 hregs->ctrl = (HPC3_SCTRL_ACTIVE); 146 } else { 147 dma_cache_wback_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual); 148 hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR); 149 } 150 151 return 0; 152} 153 154static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, 155 int status) 156{ 157 struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)instance->hostdata; 158 struct hpc3_scsiregs *hregs; 159 160 if (!SCpnt) 161 return; 162 163 hregs = (struct hpc3_scsiregs *) SCpnt->host->base; 164 165#ifdef DEBUG_DMA 166 printk("dma_stop: status<%d> ", status); 167#endif 168 169 /* First stop the HPC and flush it's FIFO. */ 170 if(hdata->dma_dir) { 171 hregs->ctrl |= HPC3_SCTRL_FLUSH; 172 while(hregs->ctrl & HPC3_SCTRL_ACTIVE) 173 barrier(); 174 } 175 hregs->ctrl = 0; 176 177#ifdef DEBUG_DMA 178 printk("\n"); 179#endif 180} 181 182void sgiwd93_reset(unsigned long base) 183{ 184 struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) base; 185 186 hregs->ctrl = HPC3_SCTRL_CRESET; 187 udelay (50); 188 hregs->ctrl = 0; 189} 190 191static inline void init_hpc_chain(uchar *buf) 192{ 193 struct hpc_chunk *hcp = (struct hpc_chunk *) buf; 194 unsigned long start, end; 195 196 start = (unsigned long) buf; 197 end = start + PAGE_SIZE; 198 while(start < end) { 199 hcp->desc.pnext = PHYSADDR((hcp + 1)); 200 hcp->desc.cntinfo = HPCDMA_EOX; 201 hcp++; 202 start += sizeof(struct hpc_chunk); 203 }; 204 hcp--; 205 hcp->desc.pnext = PHYSADDR(buf); 206 207 /* Force flush to memory */ 208 dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); 209} 210 211int __init sgiwd93_detect(Scsi_Host_Template *SGIblows) 212{ 213 static unsigned char called = 0; 214 struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0; 215 struct hpc3_scsiregs *hregs1 = &hpc3c0->scsi_chan1; 216 struct WD33C93_hostdata *hdata; 217 struct WD33C93_hostdata *hdata1; 218 wd33c93_regs regs; 219 uchar *buf; 220 221 if(called) 222 return 0; /* Should bitch on the console about this... */ 223 224 SGIblows->proc_name = "SGIWD93"; 225 226 sgiwd93_host = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); 227 if(sgiwd93_host == NULL) 228 return 0; 229 sgiwd93_host->base = (unsigned long) hregs; 230 sgiwd93_host->irq = SGI_WD93_0_IRQ; 231 232 buf = (uchar *) get_free_page(GFP_KERNEL); 233 if (!buf) { 234 printk(KERN_WARNING "sgiwd93: Could not allocate memory for host0 buffer.\n"); 235 scsi_unregister(sgiwd93_host); 236 return 0; 237 } 238 init_hpc_chain(buf); 239 240 /* HPC_SCSI_REG0 | 0x03 | KSEG1 */ 241 regs.SASR = (unsigned char*) KSEG1ADDR (0x1fbc0003); 242 regs.SCMD = (unsigned char*) KSEG1ADDR (0x1fbc0007); 243 wd33c93_init(sgiwd93_host, regs, dma_setup, dma_stop, WD33C93_FS_16_20); 244 245 hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata; 246 hdata->no_sync = 0; 247 hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); 248 249 if (request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host)) { 250 printk(KERN_WARNING "sgiwd93: Could not register IRQ %d (for host 0).\n", SGI_WD93_0_IRQ); 251#ifdef MODULE 252 wd33c93_release(); 253#endif 254 free_page((unsigned long)buf); 255 scsi_unregister(sgiwd93_host); 256 return 0; 257 } 258 /* set up second controller on the Indigo2 */ 259 if(!sgi_guiness) { 260 sgiwd93_host1 = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); 261 if(sgiwd93_host1 != NULL) 262 { 263 sgiwd93_host1->base = (unsigned long) hregs1; 264 sgiwd93_host1->irq = SGI_WD93_1_IRQ; 265 266 buf = (uchar *) get_free_page(GFP_KERNEL); 267 if (!buf) { 268 printk(KERN_WARNING "sgiwd93: Could not allocate memory for host1 buffer.\n"); 269 scsi_unregister(sgiwd93_host1); 270 called = 1; 271 return 1; /* We registered host0 so return success*/ 272 } 273 init_hpc_chain(buf); 274 275 /* HPC_SCSI_REG1 | 0x03 | KSEG1 */ 276 regs.SASR = (unsigned char*) KSEG1ADDR(0x1fbc8003); 277 regs.SCMD = (unsigned char*) KSEG1ADDR(0x1fbc8007); 278 wd33c93_init(sgiwd93_host1, regs, dma_setup, dma_stop, 279 WD33C93_FS_16_20); 280 281 hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata; 282 hdata1->no_sync = 0; 283 hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); 284 285 if (request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1)) { 286 printk(KERN_WARNING "sgiwd93: Could not allocate irq %d (for host1).\n", SGI_WD93_1_IRQ); 287#ifdef MODULE 288 wd33c93_release(); 289#endif 290 free_page((unsigned long)buf); 291 scsi_unregister(sgiwd93_host1); 292 /* Fall through since host0 registered OK */ 293 } 294 } 295 } 296 297 called = 1; 298 299 return 1; /* Found one. */ 300} 301 302#define HOSTS_C 303 304#include "sgiwd93.h" 305 306static Scsi_Host_Template driver_template = SGIWD93_SCSI; 307 308#include "scsi_module.c" 309 310int sgiwd93_release(struct Scsi_Host *instance) 311{ 312#ifdef MODULE 313 free_irq(SGI_WD93_0_IRQ, sgiwd93_intr); 314 free_page(KSEG0ADDR(hdata->dma_bounce_buffer)); 315 wd33c93_release(); 316 if(!sgi_guiness) { 317 free_irq(SGI_WD93_1_IRQ, sgiwd93_intr); 318 free_page(KSEG0ADDR(hdata1->dma_bounce_buffer)); 319 wd33c93_release(); 320 } 321#endif 322 return 1; 323} 324