sgiwd93.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2
1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 7 * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) 8 * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org) 9 * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) 10 * 11 * (In all truth, Jed Schimmel wrote all this code.) 12 */ 13#include <linux/init.h> 14#include <linux/interrupt.h> 15#include <linux/types.h> 16#include <linux/mm.h> 17#include <linux/blkdev.h> 18#include <linux/version.h> 19#include <linux/delay.h> 20#include <linux/dma-mapping.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/mc.h> 28#include <asm/sgi/hpc3.h> 29#include <asm/sgi/ip22.h> 30#include <asm/irq.h> 31#include <asm/io.h> 32 33#include "scsi.h" 34#include <scsi/scsi_host.h> 35#include "wd33c93.h" 36#include "sgiwd93.h" 37 38#include <linux/stat.h> 39 40#if 0 41#define DPRINTK(args...) printk(args) 42#else 43#define DPRINTK(args...) 44#endif 45 46#define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata)) 47 48struct ip22_hostdata { 49 struct WD33C93_hostdata wh; 50 struct hpc_data { 51 dma_addr_t dma; 52 void * cpu; 53 } hd; 54}; 55 56struct hpc_chunk { 57 struct hpc_dma_desc desc; 58 u32 _padding; /* align to quadword boundary */ 59}; 60 61struct Scsi_Host *sgiwd93_host; 62struct Scsi_Host *sgiwd93_host1; 63 64/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ 65static inline void write_wd33c93_count(const wd33c93_regs regs, 66 unsigned long value) 67{ 68 *regs.SASR = WD_TRANSFER_COUNT_MSB; 69 mb(); 70 *regs.SCMD = ((value >> 16) & 0xff); 71 *regs.SCMD = ((value >> 8) & 0xff); 72 *regs.SCMD = ((value >> 0) & 0xff); 73 mb(); 74} 75 76static inline unsigned long read_wd33c93_count(const wd33c93_regs regs) 77{ 78 unsigned long value; 79 80 *regs.SASR = WD_TRANSFER_COUNT_MSB; 81 mb(); 82 value = ((*regs.SCMD & 0xff) << 16); 83 value |= ((*regs.SCMD & 0xff) << 8); 84 value |= ((*regs.SCMD & 0xff) << 0); 85 mb(); 86 return value; 87} 88 89static irqreturn_t sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs) 90{ 91 struct Scsi_Host * host = (struct Scsi_Host *) dev_id; 92 unsigned long flags; 93 94 spin_lock_irqsave(host->host_lock, flags); 95 wd33c93_intr(host); 96 spin_unlock_irqrestore(host->host_lock, flags); 97 98 return IRQ_HANDLED; 99} 100 101static inline 102void fill_hpc_entries(struct hpc_chunk *hcp, Scsi_Cmnd *cmd, int datainp) 103{ 104 unsigned long len = cmd->SCp.this_residual; 105 void *addr = cmd->SCp.ptr; 106 dma_addr_t physaddr; 107 unsigned long count; 108 109 physaddr = dma_map_single(NULL, addr, len, cmd->sc_data_direction); 110 cmd->SCp.dma_handle = physaddr; 111 112 while (len) { 113 /* 114 * even cntinfo could be up to 16383, without 115 * magic only 8192 works correctly 116 */ 117 count = len > 8192 ? 8192 : len; 118 hcp->desc.pbuf = physaddr; 119 hcp->desc.cntinfo = count; 120 hcp++; 121 len -= count; 122 physaddr += count; 123 } 124 125 /* 126 * To make sure, if we trip an HPC bug, that we transfer every single 127 * byte, we tag on an extra zero length dma descriptor at the end of 128 * the chain. 129 */ 130 hcp->desc.pbuf = 0; 131 hcp->desc.cntinfo = HPCDMA_EOX; 132} 133 134static int dma_setup(Scsi_Cmnd *cmd, int datainp) 135{ 136 struct ip22_hostdata *hdata = HDATA(cmd->device->host); 137 struct hpc3_scsiregs *hregs = 138 (struct hpc3_scsiregs *) cmd->device->host->base; 139 struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu; 140 141 DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp); 142 143 hdata->wh.dma_dir = datainp; 144 145 /* 146 * wd33c93 shouldn't pass us bogus dma_setups, but it does:-( The 147 * other wd33c93 drivers deal with it the same way (which isn't that 148 * obvious). IMHO a better fix would be, not to do these dma setups 149 * in the first place. 150 */ 151 if (cmd->SCp.ptr == NULL || cmd->SCp.this_residual == 0) 152 return 1; 153 154 fill_hpc_entries(hcp, cmd, datainp); 155 156 DPRINTK(" HPCGO\n"); 157 158 /* Start up the HPC. */ 159 hregs->ndptr = hdata->hd.dma; 160 if (datainp) 161 hregs->ctrl = HPC3_SCTRL_ACTIVE; 162 else 163 hregs->ctrl = HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR; 164 165 return 0; 166} 167 168static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, 169 int status) 170{ 171 struct ip22_hostdata *hdata = HDATA(instance); 172 struct hpc3_scsiregs *hregs; 173 174 if (!SCpnt) 175 return; 176 177 hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base; 178 179 DPRINTK("dma_stop: status<%d> ", status); 180 181 /* First stop the HPC and flush it's FIFO. */ 182 if (hdata->wh.dma_dir) { 183 hregs->ctrl |= HPC3_SCTRL_FLUSH; 184 while (hregs->ctrl & HPC3_SCTRL_ACTIVE) 185 barrier(); 186 } 187 hregs->ctrl = 0; 188 dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual, 189 SCpnt->sc_data_direction); 190 191 DPRINTK("\n"); 192} 193 194void sgiwd93_reset(unsigned long base) 195{ 196 struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) base; 197 198 hregs->ctrl = HPC3_SCTRL_CRESET; 199 udelay(50); 200 hregs->ctrl = 0; 201} 202 203static inline void init_hpc_chain(struct hpc_data *hd) 204{ 205 struct hpc_chunk *hcp = (struct hpc_chunk *) hd->cpu; 206 struct hpc_chunk *dma = (struct hpc_chunk *) hd->dma; 207 unsigned long start, end; 208 209 start = (unsigned long) hcp; 210 end = start + PAGE_SIZE; 211 while (start < end) { 212 hcp->desc.pnext = (u32) (dma + 1); 213 hcp->desc.cntinfo = HPCDMA_EOX; 214 hcp++; dma++; 215 start += sizeof(struct hpc_chunk); 216 }; 217 hcp--; 218 hcp->desc.pnext = hd->dma; 219} 220 221static struct Scsi_Host * __init sgiwd93_setup_scsi( 222 Scsi_Host_Template *SGIblows, int unit, int irq, 223 struct hpc3_scsiregs *hregs, unsigned char *wdregs) 224{ 225 struct ip22_hostdata *hdata; 226 struct Scsi_Host *host; 227 wd33c93_regs regs; 228 229 host = scsi_register(SGIblows, sizeof(struct ip22_hostdata)); 230 if (!host) 231 return NULL; 232 233 host->base = (unsigned long) hregs; 234 host->irq = irq; 235 236 hdata = HDATA(host); 237 hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma, 238 GFP_KERNEL); 239 if (!hdata->hd.cpu) { 240 printk(KERN_WARNING "sgiwd93: Could not allocate memory for " 241 "host %d buffer.\n", unit); 242 goto out_unregister; 243 } 244 init_hpc_chain(&hdata->hd); 245 246 regs.SASR = wdregs + 3; 247 regs.SCMD = wdregs + 7; 248 249 wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_16_20); 250 251 hdata->wh.no_sync = 0; 252 253 if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) { 254 printk(KERN_WARNING "sgiwd93: Could not register irq %d " 255 "for host %d.\n", irq, unit); 256 goto out_free; 257 } 258 return host; 259 260out_free: 261 dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); 262 wd33c93_release(); 263 264out_unregister: 265 scsi_unregister(host); 266 267 return NULL; 268} 269 270int __init sgiwd93_detect(Scsi_Host_Template *SGIblows) 271{ 272 int found = 0; 273 274 SGIblows->proc_name = "SGIWD93"; 275 sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ, 276 &hpc3c0->scsi_chan0, 277 (unsigned char *)hpc3c0->scsi0_ext); 278 if (sgiwd93_host) 279 found++; 280 281 /* Set up second controller on the Indigo2 */ 282 if (ip22_is_fullhouse()) { 283 sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ, 284 &hpc3c0->scsi_chan1, 285 (unsigned char *)hpc3c0->scsi1_ext); 286 if (sgiwd93_host1) 287 found++; 288 } 289 290 return found; 291} 292 293int sgiwd93_release(struct Scsi_Host *instance) 294{ 295 struct ip22_hostdata *hdata = HDATA(instance); 296 int irq = 0; 297 298 if (sgiwd93_host && sgiwd93_host == instance) 299 irq = SGI_WD93_0_IRQ; 300 else if (sgiwd93_host1 && sgiwd93_host1 == instance) 301 irq = SGI_WD93_1_IRQ; 302 303 free_irq(irq, sgiwd93_intr); 304 dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma); 305 wd33c93_release(); 306 307 return 1; 308} 309 310static int sgiwd93_bus_reset(Scsi_Cmnd *cmd) 311{ 312 /* FIXME perform bus-specific reset */ 313 wd33c93_host_reset(cmd); 314 return SUCCESS; 315} 316 317/* 318 * Kludge alert - the SCSI code calls the abort and reset method with int 319 * arguments not with pointers. So this is going to blow up beautyfully 320 * on 64-bit systems with memory outside the compat address spaces. 321 */ 322static Scsi_Host_Template driver_template = { 323 .proc_name = "SGIWD93", 324 .name = "SGI WD93", 325 .detect = sgiwd93_detect, 326 .release = sgiwd93_release, 327 .queuecommand = wd33c93_queuecommand, 328 .eh_abort_handler = wd33c93_abort, 329 .eh_bus_reset_handler = sgiwd93_bus_reset, 330 .eh_host_reset_handler = wd33c93_host_reset, 331 .can_queue = CAN_QUEUE, 332 .this_id = 7, 333 .sg_tablesize = SG_ALL, 334 .cmd_per_lun = CMD_PER_LUN, 335 .use_clustering = DISABLE_CLUSTERING, 336}; 337#include "scsi_module.c" 338