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

嵌入式Linux

开发平台:

Unix_Linux

  1. #define AUTOSENSE
  2. #define PSEUDO_DMA
  3. #define DONT_USE_INTR
  4. #define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */
  5. #define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+
  6.  NDEBUG_SELECTION+NDEBUG_ARBITRATION)
  7. #define DMA_WORKS_RIGHT
  8. /*
  9.  * DTC 3180/3280 driver, by
  10.  * Ray Van Tassle rayvt@comm.mot.com
  11.  *
  12.  * taken from ...
  13.  * Trantor T128/T128F/T228 driver by...
  14.  *
  15.  *  Drew Eckhardt
  16.  * Visionary Computing
  17.  * (Unix and Linux consulting and custom programming)
  18.  * drew@colorado.edu
  19.  *      +1 (303) 440-4894
  20.  *
  21.  * DISTRIBUTION RELEASE 1.
  22.  *
  23.  * For more information, please consult 
  24.  *
  25.  * NCR 5380 Family
  26.  * SCSI Protocol Controller
  27.  * Databook
  28. */
  29. /*
  30.  * Options : 
  31.  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
  32.  *      for commands that return with a CHECK CONDITION status. 
  33.  *
  34.  * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
  35.  * increase compared to polled I/O.
  36.  *
  37.  * PARITY - enable parity checking.  Not supported.
  38.  *
  39.  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. 
  40.  * You probably want this.
  41.  *
  42.  * The card is detected and initialized in one of several ways : 
  43.  * 1.  Autoprobe (default) - since the board is memory mapped, 
  44.  *     a BIOS signature is scanned for to locate the registers.
  45.  *     An interrupt is triggered to autoprobe for the interrupt
  46.  *     line.
  47.  *
  48.  * 2.  With command line overrides - dtc=address,irq may be 
  49.  *     used on the LILO command line to override the defaults.
  50.  * 
  51. */
  52. /*----------------------------------------------------------------*/
  53. /* the following will set the monitor border color (useful to find
  54.  where something crashed or gets stuck at */
  55. /* 1 = blue
  56.  2 = green
  57.  3 = cyan
  58.  4 = red
  59.  5 = magenta
  60.  6 = yellow
  61.  7 = white
  62. */
  63. #if 0
  64. #define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
  65. #else
  66. #define rtrc(i) {}
  67. #endif
  68. #include <asm/system.h>
  69. #include <linux/module.h>
  70. #include <linux/signal.h>
  71. #include <linux/sched.h>
  72. #include <linux/blk.h>
  73. #include <asm/io.h>
  74. #include "scsi.h"
  75. #include "hosts.h"
  76. #include "dtc.h"
  77. #define AUTOPROBE_IRQ
  78. #include "NCR5380.h"
  79. #include "constants.h"
  80. #include "sd.h"
  81. #include <linux/stat.h>
  82. #include <linux/string.h>
  83. #include <linux/init.h>
  84. #define DTC_PUBLIC_RELEASE 2
  85. /*#define DTCDEBUG 0x1*/
  86. #define DTCDEBUG_INIT 0x1
  87. #define DTCDEBUG_TRANSFER 0x2
  88. /*
  89.  * The DTC3180 & 3280 boards are memory mapped.
  90.  * 
  91.  */
  92. /*
  93.  */
  94. /* Offset from DTC_5380_OFFSET */
  95. #define DTC_CONTROL_REG 0x100 /* rw */
  96. #define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */
  97. #define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */
  98. #define CSR_RESET              0x80 /* wo  Resets 53c400 */
  99. #define CSR_5380_REG           0x80 /* ro  5380 registers can be accessed */
  100. #define CSR_TRANS_DIR          0x40 /* rw  Data transfer direction */
  101. #define CSR_SCSI_BUFF_INTR     0x20 /* rw  Enable int on transfer ready */
  102. #define CSR_5380_INTR          0x10 /* rw  Enable 5380 interrupts */
  103. #define CSR_SHARED_INTR        0x08 /* rw  Interrupt sharing */
  104. #define CSR_HOST_BUF_NOT_RDY   0x04 /* ro  Host buffer not ready */
  105. #define CSR_SCSI_BUF_RDY       0x02 /* ro  SCSI buffer ready */
  106. #define CSR_GATED_5380_IRQ     0x01 /* ro  Last block xferred */
  107. #define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
  108. #define DTC_BLK_CNT 0x101 /* rw 
  109.  * # of 128-byte blocks to transfer */
  110. #define D_CR_ACCESS             0x80 /* ro set=can access 3280 registers */
  111. #define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */
  112. #define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer 
  113.    * after disconnect/reconnect */
  114. #define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */
  115. /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
  116. #define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */
  117. static struct override {
  118. unsigned int address;
  119. int irq;
  120. } overrides
  121. #ifdef OVERRIDE
  122. [] __initdata = OVERRIDE;
  123. #else
  124. [4] __initdata = { 
  125. {0, IRQ_AUTO},
  126. {0, IRQ_AUTO},
  127. {0, IRQ_AUTO},
  128. {0, IRQ_AUTO}
  129. };
  130. #endif
  131. #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
  132. static struct base {
  133. unsigned long address;
  134. int noauto;
  135. } bases[] __initdata = {
  136. {0xcc000, 0},
  137. {0xc8000, 0},
  138. {0xdc000, 0},
  139. {0xd8000, 0}
  140. };
  141. #define NO_BASES (sizeof (bases) / sizeof (struct base))
  142. static const struct signature {
  143. const char *string;
  144. int offset;
  145. } signatures[] = { 
  146. {"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
  147. };
  148. #define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
  149. /**
  150.  * dtc_setup - option setup for dtc3x80
  151.  *
  152.  * LILO command line initialization of the overrides array,
  153.  */
  154. static int __init dtc_setup(char *str)
  155. {
  156. static int commandline_current = 0;
  157. int i;
  158. int ints[10];
  159. get_options(str, sizeof(ints) / sizeof(int), ints);
  160. if (ints[0] != 2)
  161. printk(KERN_ERR "dtc_setup: usage dtc=address,irqn");
  162. else if (commandline_current < NO_OVERRIDES) {
  163. overrides[commandline_current].address = ints[1];
  164. overrides[commandline_current].irq = ints[2];
  165. for (i = 0; i < NO_BASES; ++i)
  166. if (bases[i].address == ints[1]) {
  167. bases[i].noauto = 1;
  168. break;
  169. }
  170. ++commandline_current;
  171. }
  172. return 1;
  173. }
  174. __setup("dtc=", dtc_setup);
  175. /**
  176.  * dtc_detect - detect DTC 3x80 controllers
  177.  * @tpnt: controller template
  178.  *
  179.  * Detects and initializes DTC 3180/3280 controllers
  180.  * that were autoprobed, overridden on the LILO command line, 
  181.  * or specified at compile time.
  182.  */
  183. int __init dtc_detect(Scsi_Host_Template * tpnt)
  184. {
  185. static int current_override = 0, current_base = 0;
  186. struct Scsi_Host *instance;
  187. unsigned int base;
  188. int sig, count;
  189. tpnt->proc_name = "dtc3x80";
  190. tpnt->proc_info = &dtc_proc_info;
  191. for (count = 0; current_override < NO_OVERRIDES; ++current_override) 
  192. {
  193. base = 0;
  194. if (overrides[current_override].address)
  195. base = overrides[current_override].address;
  196. else
  197. {
  198. for (; !base && (current_base < NO_BASES); ++current_base) {
  199. for (sig = 0; sig < NO_SIGNATURES; ++sig)
  200. {
  201. if (!bases[current_base].noauto && isa_check_signature(bases[current_base].address + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
  202. base = bases[current_base].address;
  203. break;
  204. }
  205. }
  206. }
  207. }
  208. if (!base)
  209. break;
  210. instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
  211. if (instance == NULL)
  212. break;
  213. instance->base = base;
  214. NCR5380_init(instance, 0);
  215. NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
  216. if (overrides[current_override].irq != IRQ_AUTO)
  217. instance->irq = overrides[current_override].irq;
  218. else
  219. instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
  220. #ifndef DONT_USE_INTR
  221. /* With interrupts enabled, it will sometimes hang when doing heavy
  222.  * reads. So better not enable them until I figure it out. */
  223. if (instance->irq != IRQ_NONE)
  224. if (request_irq(instance->irq, do_dtc_intr, SA_INTERRUPT, "dtc")) 
  225. {
  226. printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabledn", instance->host_no, instance->irq);
  227. instance->irq = IRQ_NONE;
  228. }
  229. if (instance->irq == IRQ_NONE) {
  230. printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,n", instance->host_no);
  231. printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.n", instance->host_no);
  232. }
  233. #else
  234. if (instance->irq != IRQ_NONE)
  235. printk(KERN_INFO "scsi%d : interrupts not used. Might as well not jumper it.n", instance->host_no);
  236. instance->irq = IRQ_NONE;
  237. #endif
  238. printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
  239. if (instance->irq == IRQ_NONE)
  240. printk(" interrupts disabled");
  241. else
  242. printk(" irq %d", instance->irq);
  243. printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
  244. NCR5380_print_options(instance);
  245. printk("n");
  246. ++current_override;
  247. ++count;
  248. }
  249. return count;
  250. }
  251. /**
  252.  * dtc_biosparam - compute disk geometry
  253.  * @disk: disk to generate for
  254.  * @dev: major/minor of device
  255.  * @ip: returned geometry
  256.  *
  257.  *  Generates a BIOS / DOS compatible H-C-S mapping for 
  258.  * the specified device / size.
  259.  */
  260. int dtc_biosparam(Disk * disk, kdev_t dev, int *ip)
  261. {
  262. int size = disk->capacity;
  263. ip[0] = 64;
  264. ip[1] = 32;
  265. ip[2] = size >> 11;
  266. return 0;
  267. }
  268. static int dtc_maxi = 0;
  269. static int dtc_wmaxi = 0;
  270. /**
  271.  * NCR5380_pread  - fast pseudo DMA read
  272.  * @instance: controller
  273.  * @dst: destination buffer
  274.  * @len: expected/max size
  275.  *
  276.  * Fast 5380 pseudo-dma read function, reads len bytes from the controller
  277.  * mmio area into dst.
  278.  */
  279. static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
  280. {
  281. unsigned char *d = dst;
  282. int i; /* For counting time spent in the poll-loop */
  283. NCR5380_local_declare();
  284. NCR5380_setup(instance);
  285. i = 0;
  286. NCR5380_read(RESET_PARITY_INTERRUPT_REG);
  287. NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
  288. if (instance->irq == IRQ_NONE)
  289. NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
  290. else
  291. NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
  292. NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
  293. rtrc(1);
  294. while (len > 0) {
  295. rtrc(2);
  296. while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
  297. ++i;
  298. rtrc(3);
  299. isa_memcpy_fromio(d, base + DTC_DATA_BUF, 128);
  300. d += 128;
  301. len -= 128;
  302. rtrc(7);
  303. /*** with int's on, it sometimes hangs after here.
  304.  * Looks like something makes HBNR go away. */
  305. }
  306. rtrc(4);
  307. while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
  308. ++i;
  309. NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
  310. rtrc(0);
  311. NCR5380_read(RESET_PARITY_INTERRUPT_REG);
  312. if (i > dtc_maxi)
  313. dtc_maxi = i;
  314. return (0);
  315. }
  316. /**
  317.  * NCR5380_pwrite  - fast pseudo DMA write
  318.  * @instance: controller
  319.  * @dst: destination buffer
  320.  * @len: expected/max size
  321.  *
  322.  * Fast 5380 pseudo-dma write function, writes len bytes to the
  323.  * controller mmio area from src.
  324.  */
  325. static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
  326. {
  327. int i;
  328. NCR5380_local_declare();
  329. NCR5380_setup(instance);
  330. NCR5380_read(RESET_PARITY_INTERRUPT_REG);
  331. NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
  332. /* set direction (write) */
  333. if (instance->irq == IRQ_NONE)
  334. NCR5380_write(DTC_CONTROL_REG, 0);
  335. else
  336. NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
  337. NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
  338. for (i = 0; len > 0; ++i) {
  339. rtrc(5);
  340. /* Poll until the host buffer can accept data. */
  341. while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
  342. ++i;
  343. rtrc(3);
  344. isa_memcpy_toio(base + DTC_DATA_BUF, src, 128);
  345. src += 128;
  346. len -= 128;
  347. }
  348. rtrc(4);
  349. while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
  350. ++i;
  351. rtrc(6);
  352. /* Wait until the last byte has been sent to the disk */
  353. while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
  354. ++i;
  355. rtrc(7);
  356. /* Check for parity error here. fixme. */
  357. NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
  358. rtrc(0);
  359. if (i > dtc_wmaxi)
  360. dtc_wmaxi = i;
  361. return (0);
  362. }
  363. MODULE_LICENSE("GPL");
  364. #include "NCR5380.c"
  365. /* Eventually this will go into an include file, but this will be later */
  366. static Scsi_Host_Template driver_template = DTC3x80;
  367. #include "scsi_module.c"