sun3x_esp.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* sun3x_esp.c:  EnhancedScsiProcessor Sun3x SCSI driver code.
  2.  *
  3.  * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  4.  *
  5.  * Based on David S. Miller's esp driver
  6.  */
  7. #include <linux/kernel.h>
  8. #include <linux/types.h>
  9. #include <linux/string.h>
  10. #include <linux/slab.h>
  11. #include <linux/blk.h>
  12. #include <linux/proc_fs.h>
  13. #include <linux/stat.h>
  14. #include <linux/delay.h>
  15. #include "scsi.h"
  16. #include "hosts.h"
  17. #include "NCR53C9x.h"
  18. #include "sun3x_esp.h"
  19. #include <asm/sun3x.h>
  20. #include <asm/dvma.h>
  21. #include <asm/irq.h>
  22. extern struct NCR_ESP *espchain;
  23. static void dma_barrier(struct NCR_ESP *esp);
  24. static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
  25. static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
  26. static void dma_drain(struct NCR_ESP *esp);
  27. static void dma_invalidate(struct NCR_ESP *esp);
  28. static void dma_dump_state(struct NCR_ESP *esp);
  29. static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
  30. static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
  31. static void dma_ints_off(struct NCR_ESP *esp);
  32. static void dma_ints_on(struct NCR_ESP *esp);
  33. static int  dma_irq_p(struct NCR_ESP *esp);
  34. static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr);
  35. static int  dma_ports_p(struct NCR_ESP *esp);
  36. static void dma_reset(struct NCR_ESP *esp);
  37. static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
  38. static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
  39. static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
  40. static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp);
  41. static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp);
  42. static void dma_advance_sg (Scsi_Cmnd *sp);
  43. #if 0
  44. /* This is where all commands are put before they are trasfered to the ESP chip
  45.  * via PIO.
  46.  */
  47. static volatile unsigned char cmd_buffer[16];
  48. #endif
  49. /* Detecting ESP chips on the machine.  This is the simple and easy
  50.  * version.
  51.  */
  52. int sun3x_esp_detect(Scsi_Host_Template *tpnt)
  53. {
  54. struct NCR_ESP *esp;
  55. struct ConfigDev *esp_dev;
  56. esp_dev = 0;
  57. esp = esp_allocate(tpnt, (void *) esp_dev);
  58. /* Do command transfer with DMA */
  59. esp->do_pio_cmds = 0;
  60. /* Required functions */
  61. esp->dma_bytes_sent = &dma_bytes_sent;
  62. esp->dma_can_transfer = &dma_can_transfer;
  63. esp->dma_dump_state = &dma_dump_state;
  64. esp->dma_init_read = &dma_init_read;
  65. esp->dma_init_write = &dma_init_write;
  66. esp->dma_ints_off = &dma_ints_off;
  67. esp->dma_ints_on = &dma_ints_on;
  68. esp->dma_irq_p = &dma_irq_p;
  69. esp->dma_ports_p = &dma_ports_p;
  70. esp->dma_setup = &dma_setup;
  71. /* Optional functions */
  72. esp->dma_barrier = &dma_barrier;
  73. esp->dma_invalidate = &dma_invalidate;
  74. esp->dma_drain = &dma_drain;
  75. esp->dma_irq_entry = 0;
  76. esp->dma_irq_exit = 0;
  77. esp->dma_led_on = 0;
  78. esp->dma_led_off = 0;
  79. esp->dma_poll = &dma_poll;
  80. esp->dma_reset = &dma_reset;
  81.         /* virtual DMA functions */
  82.         esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
  83.         esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
  84.         esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
  85.         esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
  86.         esp->dma_advance_sg = &dma_advance_sg;
  87.     
  88. /* SCSI chip speed */
  89. esp->cfreq = 20000000;
  90. esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE);
  91. esp->dregs = (void *)SUN3X_ESP_DMA;
  92. #if 0
  93.    esp->esp_command = (volatile unsigned char *)cmd_buffer;
  94.   esp->esp_command_dvma = dvma_map((unsigned long)cmd_buffer,
  95.    sizeof (cmd_buffer));
  96. #else
  97. esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE);
  98. esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command);
  99. #endif
  100. esp->irq = 2;
  101. if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, 
  102. "SUN3X SCSI", NULL)) {
  103. esp_deallocate(esp);
  104. return 0;
  105. }
  106. esp->scsi_id = 7;
  107. esp->diff = 0;
  108. esp_initialize(esp);
  109.   /* for reasons beyond my knowledge (and which should likely be fixed)
  110.      sync mode doesn't work on a 3/80 at 5mhz.  but it does at 4. */
  111.   esp->sync_defp = 0x3f;
  112. printk("ESP: Total of %d ESP hosts found, %d actually in use.n", nesps,
  113.        esps_in_use);
  114. esps_running = esps_in_use;
  115. return esps_in_use;
  116. }
  117. static void dma_do_drain(struct NCR_ESP *esp)
  118. {
  119.   struct sparc_dma_registers *dregs =
  120.   (struct sparc_dma_registers *) esp->dregs;
  121.  
  122.   int count = 500000;
  123.  
  124.   while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0)) 
  125.   udelay(1);
  126.  
  127.   if(!count) {
  128.   printk("%s:%d timeout CSR %08lxn", __FILE__, __LINE__, dregs->cond_reg);
  129.   }
  130.  
  131.   dregs->cond_reg |= DMA_FIFO_STDRAIN;
  132.  
  133.   count = 500000;
  134.  
  135.   while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0)) 
  136.   udelay(1);
  137.  
  138.   if(!count) {
  139.   printk("%s:%d timeout CSR %08lxn", __FILE__, __LINE__, dregs->cond_reg);
  140.   }
  141.  
  142. }
  143.  
  144. static void dma_barrier(struct NCR_ESP *esp)
  145. {
  146.    struct sparc_dma_registers *dregs =
  147.    (struct sparc_dma_registers *) esp->dregs;
  148.   int count = 500000;
  149.   
  150.   while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0))
  151.    udelay(1);
  152.  
  153.   if(!count) {
  154.   printk("%s:%d timeout CSR %08lxn", __FILE__, __LINE__, dregs->cond_reg);
  155.   }
  156.  
  157.    dregs->cond_reg &= ~(DMA_ENABLE);
  158. }
  159. /* This uses various DMA csr fields and the fifo flags count value to
  160.  * determine how many bytes were successfully sent/received by the ESP.
  161.  */
  162. static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
  163. {
  164. struct sparc_dma_registers *dregs = 
  165. (struct sparc_dma_registers *) esp->dregs;
  166. int rval = dregs->st_addr - esp->esp_command_dvma;
  167. return rval - fifo_count;
  168. }
  169. static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
  170. {
  171. return sp->SCp.this_residual;
  172. }
  173. static void dma_drain(struct NCR_ESP *esp)
  174. {
  175. struct sparc_dma_registers *dregs =
  176. (struct sparc_dma_registers *) esp->dregs;
  177. int count = 500000;
  178. if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
  179. dregs->cond_reg |= DMA_FIFO_STDRAIN;
  180. while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0))
  181. udelay(1);
  182. if(!count) {
  183. printk("%s:%d timeout CSR %08lxn", __FILE__, __LINE__, dregs->cond_reg);
  184. }
  185. }
  186. }
  187. static void dma_invalidate(struct NCR_ESP *esp)
  188. {
  189. struct sparc_dma_registers *dregs =
  190. (struct sparc_dma_registers *) esp->dregs;
  191. __u32 tmp;
  192. int count = 500000;
  193. while(((tmp = dregs->cond_reg) & DMA_PEND_READ) && (--count > 0)) 
  194. udelay(1);
  195. if(!count) {
  196. printk("%s:%d timeout CSR %08lxn", __FILE__, __LINE__, dregs->cond_reg);
  197. }
  198. dregs->cond_reg = tmp | DMA_FIFO_INV;
  199. dregs->cond_reg &= ~DMA_FIFO_INV;
  200. }
  201. static void dma_dump_state(struct NCR_ESP *esp)
  202. {
  203. struct sparc_dma_registers *dregs =
  204. (struct sparc_dma_registers *) esp->dregs;
  205. ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%08lx>n",
  206. esp->esp_id, dregs->cond_reg, dregs->st_addr));
  207. }
  208. static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
  209. {
  210. struct sparc_dma_registers *dregs = 
  211. (struct sparc_dma_registers *) esp->dregs;
  212. dregs->st_addr = vaddress;
  213. dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
  214. }
  215. static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
  216. {
  217. struct sparc_dma_registers *dregs = 
  218. (struct sparc_dma_registers *) esp->dregs;
  219. /* Set up the DMA counters */
  220. dregs->st_addr = vaddress;
  221. dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
  222. }
  223. static void dma_ints_off(struct NCR_ESP *esp)
  224. {
  225. DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs);
  226. }
  227. static void dma_ints_on(struct NCR_ESP *esp)
  228. {
  229. DMA_INTSON((struct sparc_dma_registers *) esp->dregs);
  230. }
  231. static int dma_irq_p(struct NCR_ESP *esp)
  232. {
  233. return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs);
  234. }
  235. static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr)
  236. {
  237. int count = 50;
  238. dma_do_drain(esp);
  239. /* Wait till the first bits settle. */
  240. while((*(volatile unsigned char *)vaddr == 0xff) && (--count > 0))
  241. udelay(1);
  242. if(!count) {
  243. // printk("%s:%d timeout expire (data %02x)n", __FILE__, __LINE__,
  244. //        esp_read(esp->eregs->esp_fdata));
  245. //mach_halt();
  246. vaddr[0] = esp_read(esp->eregs->esp_fdata);
  247. vaddr[1] = esp_read(esp->eregs->esp_fdata);
  248. }
  249. }
  250. static int dma_ports_p(struct NCR_ESP *esp)
  251. {
  252. return (((struct sparc_dma_registers *) esp->dregs)->cond_reg 
  253. & DMA_INT_ENAB);
  254. }
  255. /* Resetting various pieces of the ESP scsi driver chipset/buses. */
  256. static void dma_reset(struct NCR_ESP *esp)
  257. {
  258. struct sparc_dma_registers *dregs =
  259. (struct sparc_dma_registers *)esp->dregs;
  260. /* Punt the DVMA into a known state. */
  261. dregs->cond_reg |= DMA_RST_SCSI;
  262. dregs->cond_reg &= ~(DMA_RST_SCSI);
  263. DMA_INTSON(dregs);
  264. }
  265. static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
  266. {
  267. struct sparc_dma_registers *dregs = 
  268. (struct sparc_dma_registers *) esp->dregs;
  269. unsigned long nreg = dregs->cond_reg;
  270. // printk("dma_setup %c addr %08x cnt %08xn",
  271. //        write ? 'W' : 'R', addr, count);
  272. dma_do_drain(esp);
  273. if(write)
  274. nreg |= DMA_ST_WRITE;
  275. else {
  276. nreg &= ~(DMA_ST_WRITE);
  277. }
  278. nreg |= DMA_ENABLE;
  279. dregs->cond_reg = nreg;
  280. dregs->st_addr = addr;
  281. }
  282. static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
  283. {
  284.     sp->SCp.have_data_in = dvma_map((unsigned long)sp->SCp.buffer,
  285.        sp->SCp.this_residual);
  286.     sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
  287. }
  288. static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
  289. {
  290.     int sz = sp->SCp.buffers_residual;
  291.     struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
  292.     while (sz >= 0) {
  293.         sg[sz].dvma_addr = dvma_map((unsigned long)sg[sz].addr, sg[sz].len);
  294.         sz--;
  295.     }
  296.     sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address);
  297. }
  298. static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
  299. {
  300.     dvma_unmap((char *)sp->SCp.have_data_in);
  301. }
  302. static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
  303. {
  304.     int sz = sp->use_sg - 1;
  305.     struct mmu_sglist *sg = (struct mmu_sglist *)sp->buffer;
  306.                         
  307.     while(sz >= 0) {
  308.         dvma_unmap((char *)sg[sz].dvma_addr);
  309.         sz--;
  310.     }
  311. }
  312. static void dma_advance_sg (Scsi_Cmnd *sp)
  313. {
  314.     sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
  315. }
  316. static Scsi_Host_Template driver_template = SCSI_SUN3X_ESP;
  317. #include "scsi_module.c"
  318. MODULE_LICENSE("GPL");