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

嵌入式Linux

开发平台:

Unix_Linux

  1. #define AUTOSENSE
  2. #define PSEUDO_DMA
  3. /*
  4.  * Generic Generic NCR5380 driver
  5.  *
  6.  * Copyright 1995, Russell King
  7.  *
  8.  * ALPHA RELEASE 1.
  9.  *
  10.  * For more information, please consult
  11.  *
  12.  * NCR 5380 Family
  13.  * SCSI Protocol Controller
  14.  * Databook
  15.  *
  16.  * NCR Microelectronics
  17.  * 1635 Aeroplaza Drive
  18.  * Colorado Springs, CO 80916
  19.  * 1+ (719) 578-3400
  20.  * 1+ (800) 334-5454
  21.  */
  22. /*
  23.  * Options :
  24.  *
  25.  * PARITY - enable parity checking.  Not supported.
  26.  *
  27.  * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
  28.  *
  29.  * USLEEP - enable support for devices that don't disconnect.  Untested.
  30.  */
  31. /*
  32.  * $Log: cumana_1.c,v $
  33.  * Revision 1.3  1998/05/03 20:45:32  alan
  34.  * ARM SCSI update. This adds the eesox driver and massively updates the
  35.  * Cumana driver. The folks who bought cumana arent anal retentive all
  36.  * docs are secret weenies so now there are docs ..
  37.  *
  38.  * Revision 1.2  1998/03/08 05:49:46  davem
  39.  * Merge to 2.1.89
  40.  *
  41.  * Revision 1.1  1998/02/23 02:45:22  davem
  42.  * Merge to 2.1.88
  43.  *
  44.  */
  45. #include <linux/module.h>
  46. #include <linux/signal.h>
  47. #include <linux/sched.h>
  48. #include <linux/ioport.h>
  49. #include <linux/blk.h>
  50. #include <linux/init.h>
  51. #include <asm/ecard.h>
  52. #include <asm/io.h>
  53. #include <asm/irq.h>
  54. #include <asm/system.h>
  55. #include "../../scsi/scsi.h"
  56. #include "../../scsi/hosts.h"
  57. #include "../../scsi/constants.h"
  58. #include <scsi/scsicam.h>
  59. #define CUMANASCSI_PUBLIC_RELEASE 1
  60. static const card_ids cumanascsi_cids[] = {
  61. { MANU_CUMANA, PROD_CUMANA_SCSI_1 },
  62. { 0xffff, 0xffff }
  63. };
  64. #define NCR5380_implementation_fields 
  65.     int port, ctrl
  66. #define NCR5380_local_declare() 
  67.         struct Scsi_Host *_instance
  68. #define NCR5380_setup(instance) 
  69.         _instance = instance
  70. #define NCR5380_read(reg) cumanascsi_read(_instance, reg)
  71. #define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
  72. #define do_NCR5380_intr do_cumanascsi_intr
  73. #define NCR5380_queue_command cumanascsi_queue_command
  74. #define NCR5380_abort cumanascsi_abort
  75. #define NCR5380_reset cumanascsi_reset
  76. #define NCR5380_proc_info cumanascsi_proc_info
  77. int NCR5380_proc_info(char *buffer, char **start, off_t offset,
  78.       int length, int hostno, int inout);
  79. #define BOARD_NORMAL 0
  80. #define BOARD_NCR53C400 1
  81. #include "../../scsi/NCR5380.h"
  82. /*
  83.  * Function : cumanascsi_setup(char *str, int *ints)
  84.  *
  85.  * Purpose : LILO command line initialization of the overrides array,
  86.  *
  87.  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  88.  * equal to the number of ints.
  89.  *
  90.  */
  91. void cumanascsi_setup(char *str, int *ints)
  92. {
  93. }
  94. #define CUMANA_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
  95. #define CUMANA_IRQ(card)     ((card)->irq)
  96. /*
  97.  * Function : int cumanascsi_detect(Scsi_Host_Template * tpnt)
  98.  *
  99.  * Purpose : initializes cumana NCR5380 driver based on the
  100.  * command line / compile time port and irq definitions.
  101.  *
  102.  * Inputs : tpnt - template for this SCSI adapter.
  103.  *
  104.  * Returns : 1 if a host adapter was found, 0 if not.
  105.  *
  106.  */
  107. static struct expansion_card *ecs[4];
  108.  
  109. int cumanascsi_detect(Scsi_Host_Template * tpnt)
  110. {
  111.     int count = 0;
  112.     struct Scsi_Host *instance;
  113.     tpnt->proc_name = "CumanaSCSI-1";
  114.     memset (ecs, 0, sizeof (ecs));
  115.     while(1) {
  116.      if((ecs[count] = ecard_find(0, cumanascsi_cids)) == NULL)
  117.      break;
  118.         instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
  119.         instance->io_port = CUMANA_ADDRESS(ecs[count]);
  120. instance->irq = CUMANA_IRQ(ecs[count]);
  121. NCR5380_init(instance, 0);
  122. ecard_claim(ecs[count]);
  123. instance->n_io_port = 255;
  124. request_region (instance->io_port, instance->n_io_port, "CumanaSCSI-1");
  125.         ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
  126.         outb(0x00, instance->io_port - 577);
  127. if (instance->irq != IRQ_NONE)
  128.     if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
  129. printk("scsi%d: IRQ%d not free, interrupts disabledn",
  130.     instance->host_no, instance->irq);
  131. instance->irq = IRQ_NONE;
  132.     }
  133. if (instance->irq == IRQ_NONE) {
  134.     printk("scsi%d: interrupts not enabled. for better interactive performance,n", instance->host_no);
  135.     printk("scsi%d: please jumper the board for a free IRQ.n", instance->host_no);
  136. }
  137. printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
  138. if (instance->irq == IRQ_NONE)
  139.     printk ("s disabled");
  140. else
  141.     printk (" %d", instance->irq);
  142. printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
  143.     tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
  144. printk("nscsi%d:", instance->host_no);
  145. NCR5380_print_options(instance);
  146. printk("n");
  147. ++count;
  148.     }
  149.     return count;
  150. }
  151. int cumanascsi_release (struct Scsi_Host *shpnt)
  152. {
  153. int i;
  154. if (shpnt->irq != IRQ_NONE)
  155. free_irq (shpnt->irq, NULL);
  156. if (shpnt->io_port)
  157. release_region (shpnt->io_port, shpnt->n_io_port);
  158. for (i = 0; i < 4; i++)
  159. if (shpnt->io_port == CUMANA_ADDRESS(ecs[i]))
  160. ecard_release (ecs[i]);
  161. return 0;
  162. }
  163. const char * cumanascsi_info (struct Scsi_Host *spnt) {
  164.     return "";
  165. }
  166. #ifdef NOT_EFFICIENT
  167. #define CTRL(p,v)     outb(*ctrl = (v), (p) - 577)
  168. #define STAT(p)       inb((p)+1)
  169. #define IN(p)         inb((p))
  170. #define OUT(v,p)      outb((v), (p))
  171. #else
  172. #define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
  173. #define STAT(p) (p[4])
  174. #define IN(p) (*(p))
  175. #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
  176. #define OUT(v,p) (*(p) = (v))
  177. #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
  178. #endif
  179. #define L(v) (((v)<<16)|((v) & 0x0000ffff))
  180. #define H(v) (((v)>>16)|((v) & 0xffff0000))
  181. static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
  182.               int len)
  183. {
  184.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  185.   int oldctrl = *ctrl;
  186.   unsigned long *laddr;
  187. #ifdef NOT_EFFICIENT
  188.   int iobase = instance->io_port;
  189.   int dma_io = iobase & ~(0x3C0000>>2);
  190. #else
  191.   volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
  192.   volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
  193. #endif
  194.   if(!len) return 0;
  195.   CTRL(iobase, 0x02);
  196.   laddr = (unsigned long *)addr;
  197.   while(len >= 32)
  198.   {
  199.     int status;
  200.     unsigned long v;
  201.     status = STAT(iobase);
  202.     if(status & 0x80)
  203.       goto end;
  204.     if(!(status & 0x40))
  205.       continue;
  206.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  207.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  208.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  209.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  210.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  211.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  212.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  213.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  214.     len -= 32;
  215.     if(len == 0)
  216.       break;
  217.   }
  218.   addr = (unsigned char *)laddr;
  219.   CTRL(iobase, 0x12);
  220.   while(len > 0)
  221.   {
  222.     int status;
  223.     status = STAT(iobase);
  224.     if(status & 0x80)
  225.       goto end;
  226.     if(status & 0x40)
  227.     {
  228.       OUT(*addr++, dma_io);
  229.       if(--len == 0)
  230.         break;
  231.     }
  232.     status = STAT(iobase);
  233.     if(status & 0x80)
  234.       goto end;
  235.     if(status & 0x40)
  236.     {
  237.       OUT(*addr++, dma_io);
  238.       if(--len == 0)
  239.         break;
  240.     }
  241.   }
  242. end:
  243.   CTRL(iobase, oldctrl|0x40);
  244.   return len;
  245. }
  246. static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
  247.               int len)
  248. {
  249.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  250.   int oldctrl = *ctrl;
  251.   unsigned long *laddr;
  252. #ifdef NOT_EFFICIENT
  253.   int iobase = instance->io_port;
  254.   int dma_io = iobase & ~(0x3C0000>>2);
  255. #else
  256.   volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
  257.   volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
  258. #endif
  259.   if(!len) return 0;
  260.   CTRL(iobase, 0x00);
  261.   laddr = (unsigned long *)addr;
  262.   while(len >= 32)
  263.   {
  264.     int status;
  265.     status = STAT(iobase);
  266.     if(status & 0x80)
  267.       goto end;
  268.     if(!(status & 0x40))
  269.       continue;
  270.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  271.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  272.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  273.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  274.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  275.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  276.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  277.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  278.     len -= 32;
  279.     if(len == 0)
  280.       break;
  281.   }
  282.   addr = (unsigned char *)laddr;
  283.   CTRL(iobase, 0x10);
  284.   while(len > 0)
  285.   {
  286.     int status;
  287.     status = STAT(iobase);
  288.     if(status & 0x80)
  289.       goto end;
  290.     if(status & 0x40)
  291.     {
  292.       *addr++ = IN(dma_io);
  293.       if(--len == 0)
  294.         break;
  295.     }
  296.     status = STAT(iobase);
  297.     if(status & 0x80)
  298.       goto end;
  299.     if(status & 0x40)
  300.     {
  301.       *addr++ = IN(dma_io);
  302.       if(--len == 0)
  303.         break;
  304.     }
  305.   }
  306. end:
  307.   CTRL(iobase, oldctrl|0x40);
  308.   return len;
  309. }
  310. #undef STAT
  311. #undef CTRL
  312. #undef IN
  313. #undef OUT
  314. #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
  315. static char cumanascsi_read(struct Scsi_Host *instance, int reg)
  316. {
  317.   int iobase = instance->io_port;
  318.   int i;
  319.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  320.   CTRL(iobase, 0);
  321.   i = inb(iobase + 64 + reg);
  322.   CTRL(iobase, 0x40);
  323.   return i;
  324. }
  325. static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
  326. {
  327.   int iobase = instance->io_port;
  328.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  329.   CTRL(iobase, 0);
  330.   outb(value, iobase + 64 + reg);
  331.   CTRL(iobase, 0x40);
  332. }
  333. #undef CTRL
  334. #include "../../scsi/NCR5380.c"
  335. static Scsi_Host_Template cumanascsi_template = {
  336. module: THIS_MODULE,
  337. name: "Cumana 16-bit SCSI",
  338. detect: cumanascsi_detect,
  339. release: cumanascsi_release,
  340. info: cumanascsi_info,
  341. queuecommand: cumanascsi_queue_command,
  342. abort: cumanascsi_abort,
  343. reset: cumanascsi_reset,
  344. bios_param: scsicam_bios_param,
  345. can_queue: 16,
  346. this_id: 7,
  347. sg_tablesize: SG_ALL,
  348. cmd_per_lun: 2,
  349. unchecked_isa_dma: 0,
  350. use_clustering: DISABLE_CLUSTERING
  351. };
  352. static int __init cumanascsi_init(void)
  353. {
  354. scsi_register_module(MODULE_SCSI_HA, &cumanascsi_template);
  355. if (cumanascsi_template.present)
  356. return 0;
  357. scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
  358. return -ENODEV;
  359. }
  360. static void __exit cumanascsi_exit(void)
  361. {
  362. scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
  363. }
  364. module_init(cumanascsi_init);
  365. module_exit(cumanascsi_exit);
  366. MODULE_LICENSE("GPL");
  367. EXPORT_NO_SYMBOLS;