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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *    Disk Array driver for Compaq SMART2 Controllers
  3.  *    Copyright 1998 Compaq Computer Corporation
  4.  *
  5.  *    This program is free software; you can redistribute it and/or modify
  6.  *    it under the terms of the GNU General Public License as published by
  7.  *    the Free Software Foundation; either version 2 of the License, or
  8.  *    (at your option) any later version.
  9.  *
  10.  *    This program is distributed in the hope that it will be useful,
  11.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  13.  *    NON INFRINGEMENT.  See the GNU General Public License for more details.
  14.  *
  15.  *    You should have received a copy of the GNU General Public License
  16.  *    along with this program; if not, write to the Free Software
  17.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *    Questions/Comments/Bugfixes to arrays@compaq.com
  20.  *
  21.  *    If you want to make changes, improve or add functionality to this
  22.  *    driver, you'll probably need the Compaq Array Controller Interface
  23.  *    Specificiation (Document number ECG086/1198)
  24.  */
  25. /*
  26.  * This file contains the controller communication implementation for
  27.  * Compaq SMART-1 and SMART-2 controllers.  To the best of my knowledge,
  28.  * this should support:
  29.  *
  30.  *  PCI:
  31.  *  SMART-2/P, SMART-2DH, SMART-2SL, SMART-221, SMART-3100ES, SMART-3200
  32.  *  Integerated SMART Array Controller, SMART-4200, SMART-4250ES
  33.  *
  34.  *  EISA:
  35.  *  SMART-2/E, SMART, IAES, IDA-2, IDA
  36.  */
  37. /*
  38.  * Memory mapped FIFO interface (SMART 42xx cards)
  39.  */
  40. static void smart4_submit_command(ctlr_info_t *h, cmdlist_t *c)
  41. {
  42.         writel(c->busaddr, h->vaddr + S42XX_REQUEST_PORT_OFFSET);
  43. }
  44. /*  
  45.  *  This card is the opposite of the other cards.  
  46.  *   0 turns interrupts on... 
  47.  *   0x08 turns them off... 
  48.  */
  49. static void smart4_intr_mask(ctlr_info_t *h, unsigned long val)
  50. {
  51. if (val) 
  52. { /* Turn interrupts on */
  53. writel(0, h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
  54. } else /* Turn them off */
  55. {
  56.          writel( S42XX_INTR_OFF, 
  57. h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
  58. }
  59. }
  60. /*
  61.  *  For older cards FIFO Full = 0. 
  62.  *  On this card 0 means there is room, anything else FIFO Full. 
  63.  * 
  64.  */ 
  65. static unsigned long smart4_fifo_full(ctlr_info_t *h)
  66. {
  67.         return (!readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET));
  68. }
  69. /* This type of controller returns -1 if the fifo is empty, 
  70.  *    Not 0 like the others.
  71.  *    And we need to let it know we read a value out 
  72.  */ 
  73. static unsigned long smart4_completed(ctlr_info_t *h)
  74. {
  75. long register_value 
  76. = readl(h->vaddr + S42XX_REPLY_PORT_OFFSET);
  77. /* Fifo is empty */
  78. if( register_value == 0xffffffff)
  79. return 0; 
  80. /* Need to let it know we got the reply */
  81. /* We do this by writing a 0 to the port we just read from */
  82. writel(0, h->vaddr + S42XX_REPLY_PORT_OFFSET);
  83. return ((unsigned long) register_value); 
  84. }
  85.  /*
  86.  *  This hardware returns interrupt pending at a different place and 
  87.  *  it does not tell us if the fifo is empty, we will have check  
  88.  *  that by getting a 0 back from the comamnd_completed call. 
  89.  */
  90. static unsigned long smart4_intr_pending(ctlr_info_t *h)
  91. {
  92. unsigned long register_value  = 
  93. readl(h->vaddr + S42XX_INTR_STATUS);
  94. if( register_value &  S42XX_INTR_PENDING) 
  95. return  FIFO_NOT_EMPTY;
  96. return 0 ;
  97. }
  98. static struct access_method smart4_access = {
  99. smart4_submit_command,
  100. smart4_intr_mask,
  101. smart4_fifo_full,
  102. smart4_intr_pending,
  103. smart4_completed,
  104. };
  105. /*
  106.  * Memory mapped FIFO interface (PCI SMART2 and SMART 3xxx cards)
  107.  */
  108. static void smart2_submit_command(ctlr_info_t *h, cmdlist_t *c)
  109. {
  110. writel(c->busaddr, h->vaddr + COMMAND_FIFO);
  111. }
  112. static void smart2_intr_mask(ctlr_info_t *h, unsigned long val)
  113. {
  114. writel(val, h->vaddr + INTR_MASK);
  115. }
  116. static unsigned long smart2_fifo_full(ctlr_info_t *h)
  117. {
  118. return readl(h->vaddr + COMMAND_FIFO);
  119. }
  120. static unsigned long smart2_completed(ctlr_info_t *h)
  121. {
  122. return readl(h->vaddr + COMMAND_COMPLETE_FIFO);
  123. }
  124. static unsigned long smart2_intr_pending(ctlr_info_t *h)
  125. {
  126. return readl(h->vaddr + INTR_PENDING);
  127. }
  128. static struct access_method smart2_access = {
  129. smart2_submit_command,
  130. smart2_intr_mask,
  131. smart2_fifo_full,
  132. smart2_intr_pending,
  133. smart2_completed,
  134. };
  135. /*
  136.  *  IO access for SMART-2/E cards
  137.  */
  138. static void smart2e_submit_command(ctlr_info_t *h, cmdlist_t *c)
  139. {
  140. outl(c->busaddr, h->ioaddr + COMMAND_FIFO);
  141. }
  142. static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val)
  143. {
  144. outl(val, h->ioaddr + INTR_MASK);
  145. }
  146. static unsigned long smart2e_fifo_full(ctlr_info_t *h)
  147. {
  148. return inl(h->ioaddr + COMMAND_FIFO);
  149. }
  150. static unsigned long smart2e_completed(ctlr_info_t *h)
  151. {
  152. return inl(h->ioaddr + COMMAND_COMPLETE_FIFO);
  153. }
  154. static unsigned long smart2e_intr_pending(ctlr_info_t *h)
  155. {
  156. return inl(h->ioaddr + INTR_PENDING);
  157. }
  158. static struct access_method smart2e_access = {
  159. smart2e_submit_command,
  160. smart2e_intr_mask,
  161. smart2e_fifo_full,
  162. smart2e_intr_pending,
  163. smart2e_completed,
  164. };
  165. /*
  166.  *  IO access for older SMART-1 type cards
  167.  */
  168. #define SMART1_SYSTEM_MASK 0xC8E
  169. #define SMART1_SYSTEM_DOORBELL 0xC8F
  170. #define SMART1_LOCAL_MASK 0xC8C
  171. #define SMART1_LOCAL_DOORBELL 0xC8D
  172. #define SMART1_INTR_MASK 0xC89
  173. #define SMART1_LISTADDR 0xC90
  174. #define SMART1_LISTLEN 0xC94
  175. #define SMART1_TAG 0xC97
  176. #define SMART1_COMPLETE_ADDR 0xC98
  177. #define SMART1_LISTSTATUS 0xC9E
  178. #define CHANNEL_BUSY 0x01
  179. #define CHANNEL_CLEAR 0x02
  180. static void smart1_submit_command(ctlr_info_t *h, cmdlist_t *c)
  181. {
  182. /*
  183.  * This __u16 is actually a bunch of control flags on SMART
  184.  * and below.  We want them all to be zero.
  185.  */
  186. c->hdr.size = 0;
  187. outb(CHANNEL_CLEAR, h->ioaddr + SMART1_SYSTEM_DOORBELL);
  188. outl(c->busaddr, h->ioaddr + SMART1_LISTADDR);
  189. outw(c->size, h->ioaddr + SMART1_LISTLEN);
  190. outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
  191. }
  192. static void smart1_intr_mask(ctlr_info_t *h, unsigned long val)
  193. {
  194. if (val == 1) {
  195. outb(0xFD, h->ioaddr + SMART1_SYSTEM_DOORBELL);
  196. outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
  197. outb(0x01, h->ioaddr + SMART1_INTR_MASK);
  198. outb(0x01, h->ioaddr + SMART1_SYSTEM_MASK);
  199. } else {
  200. outb(0, h->ioaddr + 0xC8E);
  201. }
  202. }
  203. static unsigned long smart1_fifo_full(ctlr_info_t *h)
  204. {
  205. unsigned char chan;
  206. chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR;
  207. return chan;
  208. }
  209. static unsigned long smart1_completed(ctlr_info_t *h)
  210. {
  211. unsigned char status;
  212. unsigned long cmd;
  213. if (inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
  214. outb(CHANNEL_BUSY, h->ioaddr + SMART1_SYSTEM_DOORBELL);
  215. cmd = inl(h->ioaddr + SMART1_COMPLETE_ADDR);
  216. status = inb(h->ioaddr + SMART1_LISTSTATUS);
  217. outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL);
  218. if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
  219. } else {
  220. cmd = 0;
  221. }
  222. return cmd;
  223. }
  224. static unsigned long smart1_intr_pending(ctlr_info_t *h)
  225. {
  226. unsigned char chan;
  227. chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
  228. return chan;
  229. }
  230. static struct access_method smart1_access = {
  231. smart1_submit_command,
  232. smart1_intr_mask,
  233. smart1_fifo_full,
  234. smart1_intr_pending,
  235. smart1_completed,
  236. };