sgiwd93.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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/delay.h>
  19. #include <linux/dma-mapping.h>
  20. #include <linux/spinlock.h>
  21. #include <asm/page.h>
  22. #include <asm/pgtable.h>
  23. #include <asm/sgialib.h>
  24. #include <asm/sgi/sgi.h>
  25. #include <asm/sgi/mc.h>
  26. #include <asm/sgi/hpc3.h>
  27. #include <asm/sgi/ip22.h>
  28. #include <asm/irq.h>
  29. #include <asm/io.h>
  30. #include "scsi.h"
  31. #include <scsi/scsi_host.h>
  32. #include "wd33c93.h"
  33. #include <linux/stat.h>
  34. #if 0
  35. #define DPRINTK(args...) printk(args)
  36. #else
  37. #define DPRINTK(args...)
  38. #endif
  39. #define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata))
  40. struct ip22_hostdata {
  41. struct WD33C93_hostdata wh;
  42. struct hpc_data {
  43. dma_addr_t dma;
  44. void * cpu;
  45. } hd;
  46. };
  47. struct hpc_chunk {
  48. struct hpc_dma_desc desc;
  49. u32 _padding; /* align to quadword boundary */
  50. };
  51. struct Scsi_Host *sgiwd93_host;
  52. struct Scsi_Host *sgiwd93_host1;
  53. /* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
  54. static inline void write_wd33c93_count(const wd33c93_regs regs,
  55. unsigned long value)
  56. {
  57. *regs.SASR = WD_TRANSFER_COUNT_MSB;
  58. mb();
  59. *regs.SCMD = ((value >> 16) & 0xff);
  60. *regs.SCMD = ((value >> 8) & 0xff);
  61. *regs.SCMD = ((value >> 0) & 0xff);
  62. mb();
  63. }
  64. static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
  65. {
  66. unsigned long value;
  67. *regs.SASR = WD_TRANSFER_COUNT_MSB;
  68. mb();
  69. value = ((*regs.SCMD & 0xff) << 16);
  70. value |= ((*regs.SCMD & 0xff) << 8);
  71. value |= ((*regs.SCMD & 0xff) << 0);
  72. mb();
  73. return value;
  74. }
  75. static irqreturn_t sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
  76. {
  77. struct Scsi_Host * host = (struct Scsi_Host *) dev_id;
  78. unsigned long flags;
  79. spin_lock_irqsave(host->host_lock, flags);
  80. wd33c93_intr(host);
  81. spin_unlock_irqrestore(host->host_lock, flags);
  82. return IRQ_HANDLED;
  83. }
  84. static inline
  85. void fill_hpc_entries(struct hpc_chunk *hcp, Scsi_Cmnd *cmd, int datainp)
  86. {
  87. unsigned long len = cmd->SCp.this_residual;
  88. void *addr = cmd->SCp.ptr;
  89. dma_addr_t physaddr;
  90. unsigned long count;
  91. physaddr = dma_map_single(NULL, addr, len, cmd->sc_data_direction);
  92. cmd->SCp.dma_handle = physaddr;
  93. while (len) {
  94. /*
  95. * even cntinfo could be up to 16383, without
  96. * magic only 8192 works correctly
  97. */
  98. count = len > 8192 ? 8192 : len;
  99. hcp->desc.pbuf = physaddr;
  100. hcp->desc.cntinfo = count;
  101. hcp++;
  102. len -= count;
  103. physaddr += count;
  104. }
  105. /*
  106. * To make sure, if we trip an HPC bug, that we transfer every single
  107. * byte, we tag on an extra zero length dma descriptor at the end of
  108. * the chain.
  109. */
  110. hcp->desc.pbuf = 0;
  111. hcp->desc.cntinfo = HPCDMA_EOX;
  112. }
  113. static int dma_setup(Scsi_Cmnd *cmd, int datainp)
  114. {
  115. struct ip22_hostdata *hdata = HDATA(cmd->device->host);
  116. struct hpc3_scsiregs *hregs =
  117. (struct hpc3_scsiregs *) cmd->device->host->base;
  118. struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu;
  119. DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp);
  120. hdata->wh.dma_dir = datainp;
  121. /*
  122. * wd33c93 shouldn't pass us bogus dma_setups, but it does:-( The
  123. * other wd33c93 drivers deal with it the same way (which isn't that
  124. * obvious). IMHO a better fix would be, not to do these dma setups
  125. * in the first place.
  126. */
  127. if (cmd->SCp.ptr == NULL || cmd->SCp.this_residual == 0)
  128. return 1;
  129. fill_hpc_entries(hcp, cmd, datainp);
  130. DPRINTK(" HPCGO\n");
  131. /* Start up the HPC. */
  132. hregs->ndptr = hdata->hd.dma;
  133. if (datainp)
  134. hregs->ctrl = HPC3_SCTRL_ACTIVE;
  135. else
  136. hregs->ctrl = HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR;
  137. return 0;
  138. }
  139. static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
  140. int status)
  141. {
  142. struct ip22_hostdata *hdata = HDATA(instance);
  143. struct hpc3_scsiregs *hregs;
  144. if (!SCpnt)
  145. return;
  146. hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base;
  147. DPRINTK("dma_stop: status<%d> ", status);
  148. /* First stop the HPC and flush it's FIFO. */
  149. if (hdata->wh.dma_dir) {
  150. hregs->ctrl |= HPC3_SCTRL_FLUSH;
  151. while (hregs->ctrl & HPC3_SCTRL_ACTIVE)
  152. barrier();
  153. }
  154. hregs->ctrl = 0;
  155. dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual,
  156. SCpnt->sc_data_direction);
  157. DPRINTK("\n");
  158. }
  159. void sgiwd93_reset(unsigned long base)
  160. {
  161. struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) base;
  162. hregs->ctrl = HPC3_SCTRL_CRESET;
  163. udelay(50);
  164. hregs->ctrl = 0;
  165. }
  166. static inline void init_hpc_chain(struct hpc_data *hd)
  167. {
  168. struct hpc_chunk *hcp = (struct hpc_chunk *) hd->cpu;
  169. struct hpc_chunk *dma = (struct hpc_chunk *) hd->dma;
  170. unsigned long start, end;
  171. start = (unsigned long) hcp;
  172. end = start + PAGE_SIZE;
  173. while (start < end) {
  174. hcp->desc.pnext = (u32) (dma + 1);
  175. hcp->desc.cntinfo = HPCDMA_EOX;
  176. hcp++; dma++;
  177. start += sizeof(struct hpc_chunk);
  178. };
  179. hcp--;
  180. hcp->desc.pnext = hd->dma;
  181. }
  182. static struct Scsi_Host * __init sgiwd93_setup_scsi(
  183. struct scsi_host_template *SGIblows, int unit, int irq,
  184. struct hpc3_scsiregs *hregs, unsigned char *wdregs)
  185. {
  186. struct ip22_hostdata *hdata;
  187. struct Scsi_Host *host;
  188. wd33c93_regs regs;
  189. host = scsi_register(SGIblows, sizeof(struct ip22_hostdata));
  190. if (!host)
  191. return NULL;
  192. host->base = (unsigned long) hregs;
  193. host->irq = irq;
  194. hdata = HDATA(host);
  195. hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma,
  196. GFP_KERNEL);
  197. if (!hdata->hd.cpu) {
  198. printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
  199. "host %d buffer.\n", unit);
  200. goto out_unregister;
  201. }
  202. init_hpc_chain(&hdata->hd);
  203. regs.SASR = wdregs + 3;
  204. regs.SCMD = wdregs + 7;
  205. wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_16_20);
  206. hdata->wh.no_sync = 0;
  207. if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) {
  208. printk(KERN_WARNING "sgiwd93: Could not register irq %d "
  209. "for host %d.\n", irq, unit);
  210. goto out_free;
  211. }
  212. return host;
  213. out_free:
  214. dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
  215. wd33c93_release();
  216. out_unregister:
  217. scsi_unregister(host);
  218. return NULL;
  219. }
  220. static int __init sgiwd93_detect(struct scsi_host_template *SGIblows)
  221. {
  222. int found = 0;
  223. SGIblows->proc_name = "SGIWD93";
  224. sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ,
  225. &hpc3c0->scsi_chan0,
  226. (unsigned char *)hpc3c0->scsi0_ext);
  227. if (sgiwd93_host)
  228. found++;
  229. /* Set up second controller on the Indigo2 */
  230. if (ip22_is_fullhouse()) {
  231. sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ,
  232. &hpc3c0->scsi_chan1,
  233. (unsigned char *)hpc3c0->scsi1_ext);
  234. if (sgiwd93_host1)
  235. found++;
  236. }
  237. return found;
  238. }
  239. static int sgiwd93_release(struct Scsi_Host *instance)
  240. {
  241. struct ip22_hostdata *hdata = HDATA(instance);
  242. int irq = 0;
  243. if (sgiwd93_host && sgiwd93_host == instance)
  244. irq = SGI_WD93_0_IRQ;
  245. else if (sgiwd93_host1 && sgiwd93_host1 == instance)
  246. irq = SGI_WD93_1_IRQ;
  247. free_irq(irq, sgiwd93_intr);
  248. dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
  249. wd33c93_release();
  250. return 1;
  251. }
  252. static int sgiwd93_bus_reset(Scsi_Cmnd *cmd)
  253. {
  254. /* FIXME perform bus-specific reset */
  255. /* FIXME 2: kill this function, and let midlayer fallback
  256. to the same result, calling wd33c93_host_reset() */
  257. spin_lock_irq(cmd->device->host->host_lock);
  258. wd33c93_host_reset(cmd);
  259. spin_unlock_irq(cmd->device->host->host_lock);
  260. return SUCCESS;
  261. }
  262. /*
  263. * Kludge alert - the SCSI code calls the abort and reset method with int
  264. * arguments not with pointers. So this is going to blow up beautyfully
  265. * on 64-bit systems with memory outside the compat address spaces.
  266. */
  267. static struct scsi_host_template driver_template = {
  268. .proc_name = "SGIWD93",
  269. .name = "SGI WD93",
  270. .detect = sgiwd93_detect,
  271. .release = sgiwd93_release,
  272. .queuecommand = wd33c93_queuecommand,
  273. .eh_abort_handler = wd33c93_abort,
  274. .eh_bus_reset_handler = sgiwd93_bus_reset,
  275. .eh_host_reset_handler = wd33c93_host_reset,
  276. .can_queue = 16,
  277. .this_id = 7,
  278. .sg_tablesize = SG_ALL,
  279. .cmd_per_lun = 8,
  280. .use_clustering = DISABLE_CLUSTERING,
  281. };
  282. #include "scsi_module.c"