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

嵌入式Linux

开发平台:

Unix_Linux

  1. #define AUTOSENSE
  2. /*#define PSEUDO_DMA*/
  3. /*
  4.  * Oak 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: oak.c,v $
  33.  * Revision 1.3  1998/05/03 20:45:37  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:48  davem
  39.  * Merge to 2.1.89
  40.  *
  41.  * Revision 1.1  1998/02/23 02:45:27  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/system.h>
  54. #include "../../scsi/scsi.h"
  55. #include "../../scsi/hosts.h"
  56. #include "../../scsi/constants.h"
  57. #define OAKSCSI_PUBLIC_RELEASE 1
  58. #define NCR5380_read(reg) oakscsi_read(_instance, reg)
  59. #define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value)
  60. #define do_NCR5380_intr do_oakscsi_intr
  61. #define NCR5380_queue_command oakscsi_queue_command
  62. #define NCR5380_abort oakscsi_abort
  63. #define NCR5380_reset oakscsi_reset
  64. #define NCR5380_proc_info oakscsi_proc_info
  65. int NCR5380_proc_info(char *buffer, char **start, off_t offset,
  66.       int length, int hostno, int inout);
  67. #define NCR5380_implementation_fields 
  68. int port, ctrl
  69. #define NCR5380_local_declare() 
  70.         struct Scsi_Host *_instance
  71. #define NCR5380_setup(instance) 
  72.         _instance = instance
  73. #define BOARD_NORMAL 0
  74. #define BOARD_NCR53C400 1
  75. #include "../../scsi/NCR5380.h"
  76. #undef START_DMA_INITIATOR_RECEIVE_REG
  77. #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
  78. static const card_ids oakscsi_cids[] = {
  79. { MANU_OAK, PROD_OAK_SCSI },
  80. { 0xffff, 0xffff }
  81. };
  82. #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
  83. #define OAK_IRQ(card)   (IRQ_NONE)
  84. /*
  85.  * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
  86.  *
  87.  * Purpose : initializes oak NCR5380 driver based on the
  88.  * command line / compile time port and irq definitions.
  89.  *
  90.  * Inputs : tpnt - template for this SCSI adapter.
  91.  *
  92.  * Returns : 1 if a host adapter was found, 0 if not.
  93.  *
  94.  */
  95. static struct expansion_card *ecs[4];
  96. int oakscsi_detect(Scsi_Host_Template * tpnt)
  97. {
  98.     int count = 0;
  99.     struct Scsi_Host *instance;
  100.     tpnt->proc_name = "oakscsi";
  101.     memset (ecs, 0, sizeof (ecs));
  102.     ecard_startfind ();
  103.     while(1) {
  104.         if ((ecs[count] = ecard_find(0, oakscsi_cids)) == NULL)
  105.             break;
  106.         instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
  107.         instance->io_port = OAK_ADDRESS(ecs[count]);
  108.         instance->irq = OAK_IRQ(ecs[count]);
  109. NCR5380_init(instance, 0);
  110. ecard_claim(ecs[count]);
  111. instance->n_io_port = 255;
  112. request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
  113. if (instance->irq != IRQ_NONE)
  114.     if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
  115. printk("scsi%d: IRQ%d not free, interrupts disabledn",
  116.     instance->host_no, instance->irq);
  117. instance->irq = IRQ_NONE;
  118.     }
  119. if (instance->irq != IRQ_NONE) {
  120.     printk("scsi%d: eek! Interrupts enabled, but I don't thinkn", instance->host_no);
  121.     printk("scsi%d: that the board had an interrupt!n", instance->host_no);
  122. }
  123. printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
  124. if (instance->irq == IRQ_NONE)
  125.     printk ("s disabled");
  126. else
  127.     printk (" %d", instance->irq);
  128. printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
  129.     tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
  130. printk("nscsi%d:", instance->host_no);
  131. NCR5380_print_options(instance);
  132. printk("n");
  133. ++count;
  134.     }
  135. #ifdef MODULE
  136.     if(count == 0)
  137.         printk("No oak scsi devices foundn");
  138. #endif
  139.     return count;
  140. }
  141. int oakscsi_release (struct Scsi_Host *shpnt)
  142. {
  143. int i;
  144. if (shpnt->irq != IRQ_NONE)
  145. free_irq (shpnt->irq, NULL);
  146. if (shpnt->io_port)
  147. release_region (shpnt->io_port, shpnt->n_io_port);
  148. for (i = 0; i < 4; i++)
  149. if (shpnt->io_port == OAK_ADDRESS(ecs[i]))
  150. ecard_release (ecs[i]);
  151. return 0;
  152. }
  153. const char * oakscsi_info (struct Scsi_Host *spnt) {
  154.     return "";
  155. }
  156. #define STAT(p)   inw(p + 144)
  157. extern void inswb(int from, void *to, int len);
  158. static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
  159.               int len)
  160. {
  161.   int iobase = instance->io_port;
  162. printk("writing %p len %dn",addr, len);
  163.   if(!len) return -1;
  164.   while(1)
  165.   {
  166.     int status;
  167.     while(((status = STAT(iobase)) & 0x100)==0);
  168.   }
  169. }
  170. static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
  171.               int len)
  172. {
  173.   int iobase = instance->io_port;
  174. printk("reading %p len %dn", addr, len);
  175.   while(len > 0)
  176.   {
  177.     int status, timeout;
  178.     unsigned long b;
  179.     
  180.     timeout = 0x01FFFFFF;
  181.     
  182.     while(((status = STAT(iobase)) & 0x100)==0)
  183.     {
  184.       timeout--;
  185.       if(status & 0x200 || !timeout)
  186.       {
  187.         printk("status = %08Xn",status);
  188.         return 1;
  189.       }
  190.     }
  191.     if(len >= 128)
  192.     {
  193.       inswb(iobase + 136, addr, 128);
  194.       addr += 128;
  195.       len -= 128;
  196.     }
  197.     else
  198.     {
  199.       b = (unsigned long) inw(iobase + 136);
  200.       *addr ++ = b;
  201.       len -= 1;
  202.       if(len)
  203.         *addr ++ = b>>8;
  204.       len -= 1;
  205.     }
  206.   }
  207.   return 0;
  208. }
  209. #define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg)))
  210. #define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg)))
  211. #undef STAT
  212. #include "../../scsi/NCR5380.c"
  213. static Scsi_Host_Template oakscsi_template = {
  214. module: THIS_MODULE,
  215. proc_info: oakscsi_proc_info,
  216. name: "Oak 16-bit SCSI",
  217. detect: oakscsi_detect,
  218. release: oakscsi_release,
  219. info: oakscsi_info,
  220. queuecommand: oakscsi_queue_command,
  221. abort: oakscsi_abort,
  222. reset: oakscsi_reset,
  223. can_queue: 16,
  224. this_id: 7,
  225. sg_tablesize: SG_ALL,
  226. cmd_per_lun: 2,
  227. use_clustering: DISABLE_CLUSTERING
  228. };
  229. static int __init oakscsi_init(void)
  230. {
  231. scsi_register_module(MODULE_SCSI_HA, &oakscsi_template);
  232. if (oakscsi_template.present)
  233. return 0;
  234. scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
  235. return -ENODEV;
  236. }
  237. static void __exit oakscsi_exit(void)
  238. {
  239. scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
  240. }
  241. module_init(oakscsi_init);
  242. module_exit(oakscsi_exit);
  243. MODULE_AUTHOR("Russell King");
  244. MODULE_DESCRIPTION("Oak SCSI driver");
  245. MODULE_LICENSE("GPL");
  246. EXPORT_NO_SYMBOLS;