smart1,2.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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 iss_storagedev@hp.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 command_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->io_mem_addr + COMMAND_FIFO);
  141. }
  142. static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val)
  143. {
  144. outl(val, h->io_mem_addr + INTR_MASK);
  145. }
  146. static unsigned long smart2e_fifo_full(ctlr_info_t *h)
  147. {
  148. return inl(h->io_mem_addr + COMMAND_FIFO);
  149. }
  150. static unsigned long smart2e_completed(ctlr_info_t *h)
  151. {
  152. return inl(h->io_mem_addr + COMMAND_COMPLETE_FIFO);
  153. }
  154. static unsigned long smart2e_intr_pending(ctlr_info_t *h)
  155. {
  156. return inl(h->io_mem_addr + 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->io_mem_addr + SMART1_SYSTEM_DOORBELL);
  188. outl(c->busaddr, h->io_mem_addr + SMART1_LISTADDR);
  189. outw(c->size, h->io_mem_addr + SMART1_LISTLEN);
  190. outb(CHANNEL_BUSY, h->io_mem_addr + 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->io_mem_addr + SMART1_SYSTEM_DOORBELL);
  196. outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
  197. outb(0x01, h->io_mem_addr + SMART1_INTR_MASK);
  198. outb(0x01, h->io_mem_addr + SMART1_SYSTEM_MASK);
  199. } else {
  200. outb(0, h->io_mem_addr + 0xC8E);
  201. }
  202. }
  203. static unsigned long smart1_fifo_full(ctlr_info_t *h)
  204. {
  205. unsigned char chan;
  206. chan = inb(h->io_mem_addr + 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->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
  214. outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
  215. cmd = inl(h->io_mem_addr + SMART1_COMPLETE_ADDR);
  216. status = inb(h->io_mem_addr + SMART1_LISTSTATUS);
  217. outb(CHANNEL_CLEAR, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
  218. /*
  219. * this is x86 (actually compaq x86) only, so it's ok
  220. */
  221. if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
  222. } else {
  223. cmd = 0;
  224. }
  225. return cmd;
  226. }
  227. static unsigned long smart1_intr_pending(ctlr_info_t *h)
  228. {
  229. unsigned char chan;
  230. chan = inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
  231. return chan;
  232. }
  233. static struct access_method smart1_access = {
  234. smart1_submit_command,
  235. smart1_intr_mask,
  236. smart1_fifo_full,
  237. smart1_intr_pending,
  238. smart1_completed,
  239. };