sun3_scsi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl)
  3. *
  4. * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net)
  5. *
  6. * VME support added by Sam Creasey
  7. *
  8. * TODO: modify this driver to support multiple Sun3 SCSI VME boards
  9. *
  10. * Adapted from mac_scsinew.c:
  11. */
  12. /*
  13. * Generic Macintosh NCR5380 driver
  14. *
  15. * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
  16. *
  17. * derived in part from:
  18. */
  19. /*
  20. * Generic Generic NCR5380 driver
  21. *
  22. * Copyright 1995, Russell King
  23. */
  24. #include <linux/types.h>
  25. #include <linux/delay.h>
  26. #include <linux/module.h>
  27. #include <linux/ioport.h>
  28. #include <linux/init.h>
  29. #include <linux/blkdev.h>
  30. #include <linux/platform_device.h>
  31. #include <asm/io.h>
  32. #include <asm/dvma.h>
  33. #include <scsi/scsi_host.h>
  34. #include "sun3_scsi.h"
  35. /* minimum number of bytes to do dma on */
  36. #define DMA_MIN_SIZE 129
  37. /* Definitions for the core NCR5380 driver. */
  38. #define NCR5380_implementation_fields /* none */
  39. #define NCR5380_read(reg) sun3scsi_read(reg)
  40. #define NCR5380_write(reg, value) sun3scsi_write(reg, value)
  41. #define NCR5380_queue_command sun3scsi_queue_command
  42. #define NCR5380_bus_reset sun3scsi_bus_reset
  43. #define NCR5380_abort sun3scsi_abort
  44. #define NCR5380_info sun3scsi_info
  45. #define NCR5380_dma_recv_setup(instance, data, count) (count)
  46. #define NCR5380_dma_send_setup(instance, data, count) (count)
  47. #define NCR5380_dma_residual(instance) \
  48. sun3scsi_dma_residual(instance)
  49. #define NCR5380_dma_xfer_len(instance, cmd, phase) \
  50. sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd)
  51. #define NCR5380_acquire_dma_irq(instance) (1)
  52. #define NCR5380_release_dma_irq(instance)
  53. #include "NCR5380.h"
  54. extern int sun3_map_test(unsigned long, char *);
  55. static int setup_can_queue = -1;
  56. module_param(setup_can_queue, int, 0);
  57. static int setup_cmd_per_lun = -1;
  58. module_param(setup_cmd_per_lun, int, 0);
  59. static int setup_sg_tablesize = -1;
  60. module_param(setup_sg_tablesize, int, 0);
  61. static int setup_hostid = -1;
  62. module_param(setup_hostid, int, 0);
  63. /* ms to wait after hitting dma regs */
  64. #define SUN3_DMA_DELAY 10
  65. /* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
  66. #define SUN3_DVMA_BUFSIZE 0xe000
  67. static struct scsi_cmnd *sun3_dma_setup_done;
  68. static unsigned char *sun3_scsi_regp;
  69. static volatile struct sun3_dma_regs *dregs;
  70. static struct sun3_udc_regs *udc_regs;
  71. static unsigned char *sun3_dma_orig_addr;
  72. static unsigned long sun3_dma_orig_count;
  73. static int sun3_dma_active;
  74. static unsigned long last_residual;
  75. /*
  76. * NCR 5380 register access functions
  77. */
  78. static inline unsigned char sun3scsi_read(int reg)
  79. {
  80. return in_8(sun3_scsi_regp + reg);
  81. }
  82. static inline void sun3scsi_write(int reg, int value)
  83. {
  84. out_8(sun3_scsi_regp + reg, value);
  85. }
  86. #ifndef SUN3_SCSI_VME
  87. /* dma controller register access functions */
  88. static inline unsigned short sun3_udc_read(unsigned char reg)
  89. {
  90. unsigned short ret;
  91. dregs->udc_addr = UDC_CSR;
  92. udelay(SUN3_DMA_DELAY);
  93. ret = dregs->udc_data;
  94. udelay(SUN3_DMA_DELAY);
  95. return ret;
  96. }
  97. static inline void sun3_udc_write(unsigned short val, unsigned char reg)
  98. {
  99. dregs->udc_addr = reg;
  100. udelay(SUN3_DMA_DELAY);
  101. dregs->udc_data = val;
  102. udelay(SUN3_DMA_DELAY);
  103. }
  104. #endif
  105. // safe bits for the CSR
  106. #define CSR_GOOD 0x060f
  107. static irqreturn_t scsi_sun3_intr(int irq, void *dev)
  108. {
  109. struct Scsi_Host *instance = dev;
  110. unsigned short csr = dregs->csr;
  111. int handled = 0;
  112. #ifdef SUN3_SCSI_VME
  113. dregs->csr &= ~CSR_DMA_ENABLE;
  114. #endif
  115. if(csr & ~CSR_GOOD) {
  116. if (csr & CSR_DMA_BUSERR)
  117. shost_printk(KERN_ERR, instance, "bus error in DMA\n");
  118. if (csr & CSR_DMA_CONFLICT)
  119. shost_printk(KERN_ERR, instance, "DMA conflict\n");
  120. handled = 1;
  121. }
  122. if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
  123. NCR5380_intr(irq, dev);
  124. handled = 1;
  125. }
  126. return IRQ_RETVAL(handled);
  127. }
  128. /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */
  129. static unsigned long sun3scsi_dma_setup(struct Scsi_Host *instance,
  130. void *data, unsigned long count, int write_flag)
  131. {
  132. void *addr;
  133. if(sun3_dma_orig_addr != NULL)
  134. dvma_unmap(sun3_dma_orig_addr);
  135. #ifdef SUN3_SCSI_VME
  136. addr = (void *)dvma_map_vme((unsigned long) data, count);
  137. #else
  138. addr = (void *)dvma_map((unsigned long) data, count);
  139. #endif
  140. sun3_dma_orig_addr = addr;
  141. sun3_dma_orig_count = count;
  142. #ifndef SUN3_SCSI_VME
  143. dregs->fifo_count = 0;
  144. sun3_udc_write(UDC_RESET, UDC_CSR);
  145. /* reset fifo */
  146. dregs->csr &= ~CSR_FIFO;
  147. dregs->csr |= CSR_FIFO;
  148. #endif
  149. /* set direction */
  150. if(write_flag)
  151. dregs->csr |= CSR_SEND;
  152. else
  153. dregs->csr &= ~CSR_SEND;
  154. #ifdef SUN3_SCSI_VME
  155. dregs->csr |= CSR_PACK_ENABLE;
  156. dregs->dma_addr_hi = ((unsigned long)addr >> 16);
  157. dregs->dma_addr_lo = ((unsigned long)addr & 0xffff);
  158. dregs->dma_count_hi = 0;
  159. dregs->dma_count_lo = 0;
  160. dregs->fifo_count_hi = 0;
  161. dregs->fifo_count = 0;
  162. #else
  163. /* byte count for fifo */
  164. dregs->fifo_count = count;
  165. sun3_udc_write(UDC_RESET, UDC_CSR);
  166. /* reset fifo */
  167. dregs->csr &= ~CSR_FIFO;
  168. dregs->csr |= CSR_FIFO;
  169. if(dregs->fifo_count != count) {
  170. shost_printk(KERN_ERR, instance, "FIFO mismatch %04x not %04x\n",
  171. dregs->fifo_count, (unsigned int) count);
  172. NCR5380_dprint(NDEBUG_DMA, instance);
  173. }
  174. /* setup udc */
  175. udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8);
  176. udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff);
  177. udc_regs->count = count/2; /* count in words */
  178. udc_regs->mode_hi = UDC_MODE_HIWORD;
  179. if(write_flag) {
  180. if(count & 1)
  181. udc_regs->count++;
  182. udc_regs->mode_lo = UDC_MODE_LSEND;
  183. udc_regs->rsel = UDC_RSEL_SEND;
  184. } else {
  185. udc_regs->mode_lo = UDC_MODE_LRECV;
  186. udc_regs->rsel = UDC_RSEL_RECV;
  187. }
  188. /* announce location of regs block */
  189. sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8),
  190. UDC_CHN_HI);
  191. sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO);
  192. /* set dma master on */
  193. sun3_udc_write(0xd, UDC_MODE);
  194. /* interrupt enable */
  195. sun3_udc_write(UDC_INT_ENABLE, UDC_CSR);
  196. #endif
  197. return count;
  198. }
  199. static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
  200. {
  201. return last_residual;
  202. }
  203. static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted_len,
  204. struct scsi_cmnd *cmd)
  205. {
  206. if (wanted_len < DMA_MIN_SIZE || cmd->request->cmd_type != REQ_TYPE_FS)
  207. return 0;
  208. return wanted_len;
  209. }
  210. static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data)
  211. {
  212. #ifdef SUN3_SCSI_VME
  213. unsigned short csr;
  214. csr = dregs->csr;
  215. dregs->dma_count_hi = (sun3_dma_orig_count >> 16);
  216. dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff);
  217. dregs->fifo_count_hi = (sun3_dma_orig_count >> 16);
  218. dregs->fifo_count = (sun3_dma_orig_count & 0xffff);
  219. /* if(!(csr & CSR_DMA_ENABLE))
  220. * dregs->csr |= CSR_DMA_ENABLE;
  221. */
  222. #else
  223. sun3_udc_write(UDC_CHN_START, UDC_CSR);
  224. #endif
  225. return 0;
  226. }
  227. /* clean up after our dma is done */
  228. static int sun3scsi_dma_finish(int write_flag)
  229. {
  230. unsigned short __maybe_unused count;
  231. unsigned short fifo;
  232. int ret = 0;
  233. sun3_dma_active = 0;
  234. #ifdef SUN3_SCSI_VME
  235. dregs->csr &= ~CSR_DMA_ENABLE;
  236. fifo = dregs->fifo_count;
  237. if (write_flag) {
  238. if ((fifo > 0) && (fifo < sun3_dma_orig_count))
  239. fifo++;
  240. }
  241. last_residual = fifo;
  242. /* empty bytes from the fifo which didn't make it */
  243. if ((!write_flag) && (dregs->csr & CSR_LEFT)) {
  244. unsigned char *vaddr;
  245. vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr);
  246. vaddr += (sun3_dma_orig_count - fifo);
  247. vaddr--;
  248. switch (dregs->csr & CSR_LEFT) {
  249. case CSR_LEFT_3:
  250. *vaddr = (dregs->bpack_lo & 0xff00) >> 8;
  251. vaddr--;
  252. case CSR_LEFT_2:
  253. *vaddr = (dregs->bpack_hi & 0x00ff);
  254. vaddr--;
  255. case CSR_LEFT_1:
  256. *vaddr = (dregs->bpack_hi & 0xff00) >> 8;
  257. break;
  258. }
  259. }
  260. #else
  261. // check to empty the fifo on a read
  262. if(!write_flag) {
  263. int tmo = 20000; /* .2 sec */
  264. while(1) {
  265. if(dregs->csr & CSR_FIFO_EMPTY)
  266. break;
  267. if(--tmo <= 0) {
  268. printk("sun3scsi: fifo failed to empty!\n");
  269. return 1;
  270. }
  271. udelay(10);
  272. }
  273. }
  274. dregs->udc_addr = 0x32;
  275. udelay(SUN3_DMA_DELAY);
  276. count = 2 * dregs->udc_data;
  277. udelay(SUN3_DMA_DELAY);
  278. fifo = dregs->fifo_count;
  279. last_residual = fifo;
  280. /* empty bytes from the fifo which didn't make it */
  281. if((!write_flag) && (count - fifo) == 2) {
  282. unsigned short data;
  283. unsigned char *vaddr;
  284. data = dregs->fifo_data;
  285. vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr);
  286. vaddr += (sun3_dma_orig_count - fifo);
  287. vaddr[-2] = (data & 0xff00) >> 8;
  288. vaddr[-1] = (data & 0xff);
  289. }
  290. #endif
  291. dvma_unmap(sun3_dma_orig_addr);
  292. sun3_dma_orig_addr = NULL;
  293. #ifdef SUN3_SCSI_VME
  294. dregs->dma_addr_hi = 0;
  295. dregs->dma_addr_lo = 0;
  296. dregs->dma_count_hi = 0;
  297. dregs->dma_count_lo = 0;
  298. dregs->fifo_count = 0;
  299. dregs->fifo_count_hi = 0;
  300. dregs->csr &= ~CSR_SEND;
  301. /* dregs->csr |= CSR_DMA_ENABLE; */
  302. #else
  303. sun3_udc_write(UDC_RESET, UDC_CSR);
  304. dregs->fifo_count = 0;
  305. dregs->csr &= ~CSR_SEND;
  306. /* reset fifo */
  307. dregs->csr &= ~CSR_FIFO;
  308. dregs->csr |= CSR_FIFO;
  309. #endif
  310. sun3_dma_setup_done = NULL;
  311. return ret;
  312. }
  313. #include "NCR5380.c"
  314. #ifdef SUN3_SCSI_VME
  315. #define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI"
  316. #define DRV_MODULE_NAME "sun3_scsi_vme"
  317. #else
  318. #define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI"
  319. #define DRV_MODULE_NAME "sun3_scsi"
  320. #endif
  321. #define PFX DRV_MODULE_NAME ": "
  322. static struct scsi_host_template sun3_scsi_template = {
  323. .module = THIS_MODULE,
  324. .proc_name = DRV_MODULE_NAME,
  325. .name = SUN3_SCSI_NAME,
  326. .info = sun3scsi_info,
  327. .queuecommand = sun3scsi_queue_command,
  328. .eh_abort_handler = sun3scsi_abort,
  329. .eh_bus_reset_handler = sun3scsi_bus_reset,
  330. .can_queue = 16,
  331. .this_id = 7,
  332. .sg_tablesize = SG_NONE,
  333. .cmd_per_lun = 2,
  334. .use_clustering = DISABLE_CLUSTERING,
  335. .cmd_size = NCR5380_CMD_SIZE,
  336. };
  337. static int __init sun3_scsi_probe(struct platform_device *pdev)
  338. {
  339. struct Scsi_Host *instance;
  340. int error;
  341. struct resource *irq, *mem;
  342. unsigned char *ioaddr;
  343. int host_flags = 0;
  344. #ifdef SUN3_SCSI_VME
  345. int i;
  346. #endif
  347. if (setup_can_queue > 0)
  348. sun3_scsi_template.can_queue = setup_can_queue;
  349. if (setup_cmd_per_lun > 0)
  350. sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun;
  351. if (setup_sg_tablesize >= 0)
  352. sun3_scsi_template.sg_tablesize = setup_sg_tablesize;
  353. if (setup_hostid >= 0)
  354. sun3_scsi_template.this_id = setup_hostid & 7;
  355. #ifdef SUN3_SCSI_VME
  356. ioaddr = NULL;
  357. for (i = 0; i < 2; i++) {
  358. unsigned char x;
  359. irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
  360. mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
  361. if (!irq || !mem)
  362. break;
  363. ioaddr = sun3_ioremap(mem->start, resource_size(mem),
  364. SUN3_PAGE_TYPE_VME16);
  365. dregs = (struct sun3_dma_regs *)(ioaddr + 8);
  366. if (sun3_map_test((unsigned long)dregs, &x)) {
  367. unsigned short oldcsr;
  368. oldcsr = dregs->csr;
  369. dregs->csr = 0;
  370. udelay(SUN3_DMA_DELAY);
  371. if (dregs->csr == 0x1400)
  372. break;
  373. dregs->csr = oldcsr;
  374. }
  375. iounmap(ioaddr);
  376. ioaddr = NULL;
  377. }
  378. if (!ioaddr)
  379. return -ENODEV;
  380. #else
  381. irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  382. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  383. if (!irq || !mem)
  384. return -ENODEV;
  385. ioaddr = ioremap(mem->start, resource_size(mem));
  386. dregs = (struct sun3_dma_regs *)(ioaddr + 8);
  387. udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs));
  388. if (!udc_regs) {
  389. pr_err(PFX "couldn't allocate DVMA memory!\n");
  390. iounmap(ioaddr);
  391. return -ENOMEM;
  392. }
  393. #endif
  394. sun3_scsi_regp = ioaddr;
  395. instance = scsi_host_alloc(&sun3_scsi_template,
  396. sizeof(struct NCR5380_hostdata));
  397. if (!instance) {
  398. error = -ENOMEM;
  399. goto fail_alloc;
  400. }
  401. instance->io_port = (unsigned long)ioaddr;
  402. instance->irq = irq->start;
  403. error = NCR5380_init(instance, host_flags);
  404. if (error)
  405. goto fail_init;
  406. error = request_irq(instance->irq, scsi_sun3_intr, 0,
  407. "NCR5380", instance);
  408. if (error) {
  409. pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n",
  410. instance->host_no, instance->irq);
  411. goto fail_irq;
  412. }
  413. dregs->csr = 0;
  414. udelay(SUN3_DMA_DELAY);
  415. dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
  416. udelay(SUN3_DMA_DELAY);
  417. dregs->fifo_count = 0;
  418. #ifdef SUN3_SCSI_VME
  419. dregs->fifo_count_hi = 0;
  420. dregs->dma_addr_hi = 0;
  421. dregs->dma_addr_lo = 0;
  422. dregs->dma_count_hi = 0;
  423. dregs->dma_count_lo = 0;
  424. dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
  425. #endif
  426. NCR5380_maybe_reset_bus(instance);
  427. error = scsi_add_host(instance, NULL);
  428. if (error)
  429. goto fail_host;
  430. platform_set_drvdata(pdev, instance);
  431. scsi_scan_host(instance);
  432. return 0;
  433. fail_host:
  434. free_irq(instance->irq, instance);
  435. fail_irq:
  436. NCR5380_exit(instance);
  437. fail_init:
  438. scsi_host_put(instance);
  439. fail_alloc:
  440. if (udc_regs)
  441. dvma_free(udc_regs);
  442. iounmap(sun3_scsi_regp);
  443. return error;
  444. }
  445. static int __exit sun3_scsi_remove(struct platform_device *pdev)
  446. {
  447. struct Scsi_Host *instance = platform_get_drvdata(pdev);
  448. scsi_remove_host(instance);
  449. free_irq(instance->irq, instance);
  450. NCR5380_exit(instance);
  451. scsi_host_put(instance);
  452. if (udc_regs)
  453. dvma_free(udc_regs);
  454. iounmap(sun3_scsi_regp);
  455. return 0;
  456. }
  457. static struct platform_driver sun3_scsi_driver = {
  458. .remove = __exit_p(sun3_scsi_remove),
  459. .driver = {
  460. .name = DRV_MODULE_NAME,
  461. },
  462. };
  463. module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe);
  464. MODULE_ALIAS("platform:" DRV_MODULE_NAME);
  465. MODULE_LICENSE("GPL");