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

嵌入式Linux

开发平台:

Unix_Linux

  1. #define AUTOSENSE
  2. #define PSEUDO_DMA
  3. /*
  4.  * Trantor T128/T128F/T228 driver
  5.  * Note : architecturally, the T100 and T130 are different and won't 
  6.  *  work
  7.  *
  8.  * Copyright 1993, Drew Eckhardt
  9.  * Visionary Computing
  10.  * (Unix and Linux consulting and custom programming)
  11.  * drew@colorado.edu
  12.  *      +1 (303) 440-4894
  13.  *
  14.  * DISTRIBUTION RELEASE 3.
  15.  *
  16.  * For more information, please consult 
  17.  *
  18.  * Trantor Systems, Ltd.
  19.  * T128/T128F/T228 SCSI Host Adapter
  20.  * Hardware Specifications
  21.  * 
  22.  * Trantor Systems, Ltd. 
  23.  * 5415 Randall Place
  24.  * Fremont, CA 94538
  25.  * 1+ (415) 770-1400, FAX 1+ (415) 770-9910
  26.  * 
  27.  * and 
  28.  *
  29.  * NCR 5380 Family
  30.  * SCSI Protocol Controller
  31.  * Databook
  32.  *
  33.  * NCR Microelectronics
  34.  * 1635 Aeroplaza Drive
  35.  * Colorado Springs, CO 80916
  36.  * 1+ (719) 578-3400
  37.  * 1+ (800) 334-5454
  38.  */
  39. /*
  40.  * Options : 
  41.  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
  42.  *      for commands that return with a CHECK CONDITION status. 
  43.  *
  44.  * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
  45.  * increase compared to polled I/O.
  46.  *
  47.  * PARITY - enable parity checking.  Not supported.
  48.  *
  49.  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  You
  50.  *          only really want to use this if you're having a problem with
  51.  *          dropped characters during high speed communications, and even
  52.  *          then, you're going to be better off twiddling with transfersize.
  53.  *
  54.  * The card is detected and initialized in one of several ways : 
  55.  * 1.  Autoprobe (default) - since the board is memory mapped, 
  56.  *     a BIOS signature is scanned for to locate the registers.
  57.  *     An interrupt is triggered to autoprobe for the interrupt
  58.  *     line.
  59.  *
  60.  * 2.  With command line overrides - t128=address,irq may be 
  61.  *     used on the LILO command line to override the defaults.
  62.  *
  63.  * 3.  With the T128_OVERRIDE compile time define.  This is 
  64.  *     specified as an array of address, irq tuples.  Ie, for
  65.  *     one board at the default 0xcc000 address, IRQ5, I could say 
  66.  *     -DT128_OVERRIDE={{0xcc000, 5}}
  67.  *
  68.  *     Note that if the override methods are used, place holders must
  69.  *     be specified for other boards in the system.
  70.  * 
  71.  * T128/T128F jumper/dipswitch settings (note : on my sample, the switches 
  72.  * were epoxy'd shut, meaning I couldn't change the 0xcc000 base address) :
  73.  *
  74.  * T128    Sw7 Sw8 Sw6 = 0ws Sw5 = boot 
  75.  * T128F   Sw6 Sw7 Sw5 = 0ws Sw4 = boot Sw8 = floppy disable
  76.  * cc000   off off      
  77.  * c8000   off on
  78.  * dc000   on  off
  79.  * d8000   on  on
  80.  *
  81.  * 
  82.  * Interrupts 
  83.  * There is a 12 pin jumper block, jp1, numbered as follows : 
  84.  *   T128 (JP1)    T128F (J5)
  85.  * 2 4 6 8 10 12 11 9  7 5 3 1
  86.  * 1 3 5 7 9  11 12 10 8 6 4 2
  87.  *
  88.  * 3   2-4
  89.  * 5   1-3
  90.  * 7   3-5
  91.  * T128F only 
  92.  * 10 8-10
  93.  * 12 7-9
  94.  * 14 10-12
  95.  * 15 9-11
  96.  */
  97. #include <asm/system.h>
  98. #include <linux/signal.h>
  99. #include <linux/sched.h>
  100. #include <asm/io.h>
  101. #include <linux/blk.h>
  102. #include "scsi.h"
  103. #include "hosts.h"
  104. #include "t128.h"
  105. #define AUTOPROBE_IRQ
  106. #include "NCR5380.h"
  107. #include "constants.h"
  108. #include "sd.h"
  109. #include <linux/stat.h>
  110. #include <linux/init.h>
  111. #include <linux/module.h>
  112. static struct override {
  113. unsigned long address;
  114. int irq;
  115. } overrides
  116. #ifdef T128_OVERRIDE
  117. [] __initdata = T128_OVERRIDE;
  118. #else
  119. [4] __initdata = { 
  120. { 0, IRQ_AUTO},
  121. { 0, IRQ_AUTO},
  122. { 0, IRQ_AUTO},
  123. { 0, IRQ_AUTO}
  124. };
  125. #endif
  126. #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
  127. static struct base {
  128. unsigned int address;
  129. int noauto;
  130. } bases[] __initdata = {
  131. {0xcc000, 0},
  132. {0xc8000, 0},
  133. {0xdc000, 0},
  134. {0xd8000, 0}
  135. };
  136. #define NO_BASES (sizeof (bases) / sizeof (struct base))
  137. static const struct signature {
  138. const char *string;
  139. int offset;
  140. } signatures[] __initdata = {
  141. {"TSROM: SCSI BIOS, Version 1.12", 0x36},
  142. };
  143. #define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
  144. /**
  145.  * t128_setup
  146.  * @str: command line 
  147.  *
  148.  * LILO command line initialization of the overrides array,
  149.  */
  150. int __init t128_setup(char *str)
  151. {
  152. static int commandline_current = 0;
  153. int ints[10];
  154. int i;
  155. get_options(str, sizeof(ints) / sizeof(int), ints);
  156. if (ints[0] != 2)
  157. printk(KERN_ERR "t128_setup : usage t128=address,irqn");
  158. else if (commandline_current < NO_OVERRIDES) {
  159. overrides[commandline_current].address = ints[1];
  160. overrides[commandline_current].irq = ints[2];
  161. for (i = 0; i < NO_BASES; ++i)
  162. if (bases[i].address == ints[1]) {
  163. bases[i].noauto = 1;
  164. break;
  165. }
  166. ++commandline_current;
  167. }
  168. return 1;
  169. }
  170. __setup("t128=", t128_setup);
  171. /**
  172.  * t128_detect - detect controllers
  173.  * @tpnt: SCSI template
  174.  *
  175.  * Detects and initializes T128,T128F, or T228 controllers
  176.  * that were autoprobed, overridden on the LILO command line, 
  177.  * or specified at compile time.
  178.  */
  179. int __init t128_detect(Scsi_Host_Template * tpnt)
  180. {
  181. static int current_override = 0, current_base = 0;
  182. struct Scsi_Host *instance;
  183. unsigned long base;
  184. int sig, count;
  185. tpnt->proc_name = "t128";
  186. tpnt->proc_info = &t128_proc_info;
  187. for (count = 0; current_override < NO_OVERRIDES; ++current_override) 
  188. {
  189. base = 0;
  190. if (overrides[current_override].address)
  191. base = overrides[current_override].address;
  192. else
  193. for (; !base && (current_base < NO_BASES); ++current_base) {
  194. for (sig = 0; sig < NO_SIGNATURES; ++sig)
  195. if (!bases[current_base].noauto &&
  196.     isa_check_signature(bases[current_base].address + signatures[sig].offset,
  197. signatures[sig].string,
  198. strlen(signatures[sig].string)))
  199. {
  200. base = bases[current_base].address;
  201. break;
  202. }
  203. }
  204. if (!base)
  205. break;
  206. instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
  207. if (instance == NULL)
  208. break;
  209. instance->base = base;
  210. NCR5380_init(instance, 0);
  211. if (overrides[current_override].irq != IRQ_AUTO)
  212. instance->irq = overrides[current_override].irq;
  213. else
  214. instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
  215. if (instance->irq != IRQ_NONE)
  216. if (request_irq(instance->irq, do_t128_intr, SA_INTERRUPT, "t128", NULL)) 
  217. {
  218. printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabledn", instance->host_no, instance->irq);
  219. instance->irq = IRQ_NONE;
  220. }
  221. if (instance->irq == IRQ_NONE) {
  222. printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,n", instance->host_no);
  223. printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.n", instance->host_no);
  224. }
  225. printk(KERN_INFO "scsi%d : at 0x%08lx", instance->host_no,instance->base);
  226. if (instance->irq == IRQ_NONE)
  227. printk(" interrupts disabled");
  228. else
  229. printk(" irq %d", instance->irq);
  230. printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE);
  231. NCR5380_print_options(instance);
  232. printk("n");
  233. ++current_override;
  234. ++count;
  235. }
  236. return count;
  237. }
  238. /**
  239.  * t128_biosparam - disk geometry
  240.  * @disk: device 
  241.  * @dev: device major/minor
  242.  * @ip: array to return results
  243.  *
  244.  * Generates a BIOS / DOS compatible H-C-S mapping for 
  245.  * the specified device / size.
  246.  * 
  247.  * Most SCSI boards use this mapping, I could be incorrect.  Some one
  248.  * using hard disks on a trantor should verify that this mapping
  249.  * corresponds to that used by the BIOS / ASPI driver by running the
  250.  * linux fdisk program and matching the H_C_S coordinates to those
  251.  * that DOS uses.
  252.  */
  253. int t128_biosparam(Disk * disk, kdev_t dev, int *ip)
  254. {
  255. int size = disk->capacity;
  256. ip[0] = 64;
  257. ip[1] = 32;
  258. ip[2] = size >> 11;
  259. return 0;
  260. }
  261. /**
  262.  * NCR5380_pread - pseudo DMA read
  263.  * @instance: controller
  264.  * @dst: buffer to write to
  265.  * @len: expect/max length
  266.  *
  267.  * Fast 5380 pseudo-dma read function, transfers len bytes to 
  268.  * dst from the controller.
  269.  */
  270. static inline int NCR5380_pread(struct Scsi_Host *instance,
  271. unsigned char *dst, int len)
  272. {
  273. unsigned long reg = instance->base + T_DATA_REG_OFFSET;
  274. unsigned char *d = dst;
  275. int i = len;
  276. while (!(isa_readb(instance->base + T_STATUS_REG_OFFSET) & T_ST_RDY))
  277.         barrier();
  278. for (; i; --i) {
  279. *d++ = isa_readb(reg);
  280. }
  281. if (isa_readb(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
  282. unsigned char tmp;
  283. unsigned long foo;
  284. foo = instance->base + T_CONTROL_REG_OFFSET;
  285. tmp = isa_readb(foo);
  286. isa_writeb(tmp | T_CR_CT, foo);
  287. isa_writeb(tmp, foo);
  288. printk(KERN_ERR "scsi%d : watchdog timer fired in t128 NCR5380_pread.n", instance->host_no);
  289. return -1;
  290. } else
  291. return 0;
  292. }
  293. /**
  294.  * NCR5380_pwrite - pseudo DMA write
  295.  * @instance: controller
  296.  * @dst: buffer to write to
  297.  * @len: expect/max length
  298.  *
  299.  * Fast 5380 pseudo-dma write function, transfers len bytes from
  300.  * dst to the controller.
  301.  */
  302. static inline int NCR5380_pwrite(struct Scsi_Host *instance,
  303.  unsigned char *src, int len)
  304. {
  305. unsigned long reg = instance->base + T_DATA_REG_OFFSET;
  306. unsigned char *s = src;
  307. int i = len;
  308. while (!(isa_readb(instance->base + T_STATUS_REG_OFFSET) & T_ST_RDY))
  309. barrier();
  310. for (; i; --i) {
  311. isa_writeb(*s++, reg);
  312. }
  313. if (isa_readb(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
  314. unsigned char tmp;
  315. unsigned long foo;
  316. foo = instance->base + T_CONTROL_REG_OFFSET;
  317. tmp = isa_readb(foo);
  318. isa_writeb(tmp | T_CR_CT, foo);
  319. isa_writeb(tmp, foo);
  320. printk(KERN_ERR "scsi%d : watchdog timer fired in t128 NCR5380_pwrite()n", instance->host_no);
  321. return -1;
  322. } else
  323. return 0;
  324. }
  325. MODULE_LICENSE("GPL");
  326. #include "NCR5380.c"
  327. /* Eventually this will go into an include file, but this will be later */
  328. static Scsi_Host_Template driver_template = TRANTOR_T128;
  329. #include "scsi_module.c"