sun3x_esp.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

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