aic79xx_inline.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /*
  2. * Inline routines shareable across OS platforms.
  3. *
  4. * Copyright (c) 1994-2001 Justin T. Gibbs.
  5. * Copyright (c) 2000-2003 Adaptec Inc.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions, and the following disclaimer,
  13. * without modification.
  14. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  15. * substantially similar to the "NO WARRANTY" disclaimer below
  16. * ("Disclaimer") and any redistribution must be conditioned upon
  17. * including a substantially similar Disclaimer requirement for further
  18. * binary redistribution.
  19. * 3. Neither the names of the above-listed copyright holders nor the names
  20. * of any contributors may be used to endorse or promote products derived
  21. * from this software without specific prior written permission.
  22. *
  23. * Alternatively, this software may be distributed under the terms of the
  24. * GNU General Public License ("GPL") version 2 as published by the Free
  25. * Software Foundation.
  26. *
  27. * NO WARRANTY
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  29. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  30. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  31. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  32. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  36. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  37. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGES.
  39. *
  40. * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#59 $
  41. *
  42. * $FreeBSD$
  43. */
  44. #ifndef _AIC79XX_INLINE_H_
  45. #define _AIC79XX_INLINE_H_
  46. /******************************** Debugging ***********************************/
  47. static __inline char *ahd_name(struct ahd_softc *ahd);
  48. static __inline char *
  49. ahd_name(struct ahd_softc *ahd)
  50. {
  51. return (ahd->name);
  52. }
  53. /************************ Sequencer Execution Control *************************/
  54. static __inline void ahd_known_modes(struct ahd_softc *ahd,
  55. ahd_mode src, ahd_mode dst);
  56. static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
  57. ahd_mode src,
  58. ahd_mode dst);
  59. static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
  60. ahd_mode_state state,
  61. ahd_mode *src, ahd_mode *dst);
  62. static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
  63. ahd_mode dst);
  64. static __inline void ahd_update_modes(struct ahd_softc *ahd);
  65. static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
  66. ahd_mode dstmode, const char *file,
  67. int line);
  68. static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
  69. static __inline void ahd_restore_modes(struct ahd_softc *ahd,
  70. ahd_mode_state state);
  71. static __inline int ahd_is_paused(struct ahd_softc *ahd);
  72. static __inline void ahd_pause(struct ahd_softc *ahd);
  73. static __inline void ahd_unpause(struct ahd_softc *ahd);
  74. static __inline void
  75. ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
  76. {
  77. ahd->src_mode = src;
  78. ahd->dst_mode = dst;
  79. ahd->saved_src_mode = src;
  80. ahd->saved_dst_mode = dst;
  81. }
  82. static __inline ahd_mode_state
  83. ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
  84. {
  85. return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT));
  86. }
  87. static __inline void
  88. ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
  89. ahd_mode *src, ahd_mode *dst)
  90. {
  91. *src = (state & SRC_MODE) >> SRC_MODE_SHIFT;
  92. *dst = (state & DST_MODE) >> DST_MODE_SHIFT;
  93. }
  94. static __inline void
  95. ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
  96. {
  97. if (ahd->src_mode == src && ahd->dst_mode == dst)
  98. return;
  99. #ifdef AHD_DEBUG
  100. if (ahd->src_mode == AHD_MODE_UNKNOWN
  101. || ahd->dst_mode == AHD_MODE_UNKNOWN)
  102. panic("Setting mode prior to saving it.\n");
  103. if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
  104. printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
  105. ahd_build_mode_state(ahd, src, dst));
  106. #endif
  107. ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
  108. ahd->src_mode = src;
  109. ahd->dst_mode = dst;
  110. }
  111. static __inline void
  112. ahd_update_modes(struct ahd_softc *ahd)
  113. {
  114. ahd_mode_state mode_ptr;
  115. ahd_mode src;
  116. ahd_mode dst;
  117. mode_ptr = ahd_inb(ahd, MODE_PTR);
  118. #ifdef AHD_DEBUG
  119. if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
  120. printf("Reading mode 0x%x\n", mode_ptr);
  121. #endif
  122. ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
  123. ahd_known_modes(ahd, src, dst);
  124. }
  125. static __inline void
  126. ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
  127. ahd_mode dstmode, const char *file, int line)
  128. {
  129. #ifdef AHD_DEBUG
  130. if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
  131. || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
  132. panic("%s:%s:%d: Mode assertion failed.\n",
  133. ahd_name(ahd), file, line);
  134. }
  135. #endif
  136. }
  137. static __inline ahd_mode_state
  138. ahd_save_modes(struct ahd_softc *ahd)
  139. {
  140. if (ahd->src_mode == AHD_MODE_UNKNOWN
  141. || ahd->dst_mode == AHD_MODE_UNKNOWN)
  142. ahd_update_modes(ahd);
  143. return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
  144. }
  145. static __inline void
  146. ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
  147. {
  148. ahd_mode src;
  149. ahd_mode dst;
  150. ahd_extract_mode_state(ahd, state, &src, &dst);
  151. ahd_set_modes(ahd, src, dst);
  152. }
  153. #define AHD_ASSERT_MODES(ahd, source, dest) \
  154. ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
  155. /*
  156. * Determine whether the sequencer has halted code execution.
  157. * Returns non-zero status if the sequencer is stopped.
  158. */
  159. static __inline int
  160. ahd_is_paused(struct ahd_softc *ahd)
  161. {
  162. return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
  163. }
  164. /*
  165. * Request that the sequencer stop and wait, indefinitely, for it
  166. * to stop. The sequencer will only acknowledge that it is paused
  167. * once it has reached an instruction boundary and PAUSEDIS is
  168. * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
  169. * for critical sections.
  170. */
  171. static __inline void
  172. ahd_pause(struct ahd_softc *ahd)
  173. {
  174. ahd_outb(ahd, HCNTRL, ahd->pause);
  175. /*
  176. * Since the sequencer can disable pausing in a critical section, we
  177. * must loop until it actually stops.
  178. */
  179. while (ahd_is_paused(ahd) == 0)
  180. ;
  181. }
  182. /*
  183. * Allow the sequencer to continue program execution.
  184. * We check here to ensure that no additional interrupt
  185. * sources that would cause the sequencer to halt have been
  186. * asserted. If, for example, a SCSI bus reset is detected
  187. * while we are fielding a different, pausing, interrupt type,
  188. * we don't want to release the sequencer before going back
  189. * into our interrupt handler and dealing with this new
  190. * condition.
  191. */
  192. static __inline void
  193. ahd_unpause(struct ahd_softc *ahd)
  194. {
  195. /*
  196. * Automatically restore our modes to those saved
  197. * prior to the first change of the mode.
  198. */
  199. if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
  200. && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
  201. if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
  202. ahd_reset_cmds_pending(ahd);
  203. ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
  204. }
  205. if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
  206. ahd_outb(ahd, HCNTRL, ahd->unpause);
  207. ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
  208. }
  209. /*********************** Scatter Gather List Handling *************************/
  210. static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
  211. void *sgptr, dma_addr_t addr,
  212. bus_size_t len, int last);
  213. static __inline void ahd_setup_scb_common(struct ahd_softc *ahd,
  214. struct scb *scb);
  215. static __inline void ahd_setup_data_scb(struct ahd_softc *ahd,
  216. struct scb *scb);
  217. static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd,
  218. struct scb *scb);
  219. static __inline void *
  220. ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
  221. void *sgptr, dma_addr_t addr, bus_size_t len, int last)
  222. {
  223. scb->sg_count++;
  224. if (sizeof(dma_addr_t) > 4
  225. && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
  226. struct ahd_dma64_seg *sg;
  227. sg = (struct ahd_dma64_seg *)sgptr;
  228. sg->addr = ahd_htole64(addr);
  229. sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
  230. return (sg + 1);
  231. } else {
  232. struct ahd_dma_seg *sg;
  233. sg = (struct ahd_dma_seg *)sgptr;
  234. sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
  235. sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
  236. | (last ? AHD_DMA_LAST_SEG : 0));
  237. return (sg + 1);
  238. }
  239. }
  240. static __inline void
  241. ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
  242. {
  243. /* XXX Handle target mode SCBs. */
  244. scb->crc_retry_count = 0;
  245. if ((scb->flags & SCB_PACKETIZED) != 0) {
  246. /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
  247. scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
  248. } else {
  249. if (ahd_get_transfer_length(scb) & 0x01)
  250. scb->hscb->task_attribute = SCB_XFERLEN_ODD;
  251. else
  252. scb->hscb->task_attribute = 0;
  253. }
  254. if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
  255. || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
  256. scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
  257. ahd_htole32(scb->sense_busaddr);
  258. }
  259. static __inline void
  260. ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
  261. {
  262. /*
  263. * Copy the first SG into the "current" data ponter area.
  264. */
  265. if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
  266. struct ahd_dma64_seg *sg;
  267. sg = (struct ahd_dma64_seg *)scb->sg_list;
  268. scb->hscb->dataptr = sg->addr;
  269. scb->hscb->datacnt = sg->len;
  270. } else {
  271. struct ahd_dma_seg *sg;
  272. uint32_t *dataptr_words;
  273. sg = (struct ahd_dma_seg *)scb->sg_list;
  274. dataptr_words = (uint32_t*)&scb->hscb->dataptr;
  275. dataptr_words[0] = sg->addr;
  276. dataptr_words[1] = 0;
  277. if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
  278. uint64_t high_addr;
  279. high_addr = ahd_le32toh(sg->len) & 0x7F000000;
  280. scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
  281. }
  282. scb->hscb->datacnt = sg->len;
  283. }
  284. /*
  285. * Note where to find the SG entries in bus space.
  286. * We also set the full residual flag which the
  287. * sequencer will clear as soon as a data transfer
  288. * occurs.
  289. */
  290. scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
  291. }
  292. static __inline void
  293. ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
  294. {
  295. scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
  296. scb->hscb->dataptr = 0;
  297. scb->hscb->datacnt = 0;
  298. }
  299. /************************** Memory mapping routines ***************************/
  300. static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
  301. static __inline void *
  302. ahd_sg_bus_to_virt(struct ahd_softc *ahd,
  303. struct scb *scb,
  304. uint32_t sg_busaddr);
  305. static __inline uint32_t
  306. ahd_sg_virt_to_bus(struct ahd_softc *ahd,
  307. struct scb *scb,
  308. void *sg);
  309. static __inline void ahd_sync_scb(struct ahd_softc *ahd,
  310. struct scb *scb, int op);
  311. static __inline void ahd_sync_sglist(struct ahd_softc *ahd,
  312. struct scb *scb, int op);
  313. static __inline void ahd_sync_sense(struct ahd_softc *ahd,
  314. struct scb *scb, int op);
  315. static __inline uint32_t
  316. ahd_targetcmd_offset(struct ahd_softc *ahd,
  317. u_int index);
  318. static __inline size_t
  319. ahd_sg_size(struct ahd_softc *ahd)
  320. {
  321. if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
  322. return (sizeof(struct ahd_dma64_seg));
  323. return (sizeof(struct ahd_dma_seg));
  324. }
  325. static __inline void *
  326. ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
  327. {
  328. dma_addr_t sg_offset;
  329. /* sg_list_phys points to entry 1, not 0 */
  330. sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
  331. return ((uint8_t *)scb->sg_list + sg_offset);
  332. }
  333. static __inline uint32_t
  334. ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
  335. {
  336. dma_addr_t sg_offset;
  337. /* sg_list_phys points to entry 1, not 0 */
  338. sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
  339. - ahd_sg_size(ahd);
  340. return (scb->sg_list_busaddr + sg_offset);
  341. }
  342. static __inline void
  343. ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
  344. {
  345. ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
  346. scb->hscb_map->dmamap,
  347. /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
  348. /*len*/sizeof(*scb->hscb), op);
  349. }
  350. static __inline void
  351. ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
  352. {
  353. if (scb->sg_count == 0)
  354. return;
  355. ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
  356. scb->sg_map->dmamap,
  357. /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
  358. /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
  359. }
  360. static __inline void
  361. ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
  362. {
  363. ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
  364. scb->sense_map->dmamap,
  365. /*offset*/scb->sense_busaddr,
  366. /*len*/AHD_SENSE_BUFSIZE, op);
  367. }
  368. static __inline uint32_t
  369. ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
  370. {
  371. return (((uint8_t *)&ahd->targetcmds[index])
  372. - (uint8_t *)ahd->qoutfifo);
  373. }
  374. /*********************** Miscelaneous Support Functions ***********************/
  375. static __inline void ahd_complete_scb(struct ahd_softc *ahd,
  376. struct scb *scb);
  377. static __inline void ahd_update_residual(struct ahd_softc *ahd,
  378. struct scb *scb);
  379. static __inline struct ahd_initiator_tinfo *
  380. ahd_fetch_transinfo(struct ahd_softc *ahd,
  381. char channel, u_int our_id,
  382. u_int remote_id,
  383. struct ahd_tmode_tstate **tstate);
  384. static __inline uint16_t
  385. ahd_inw(struct ahd_softc *ahd, u_int port);
  386. static __inline void ahd_outw(struct ahd_softc *ahd, u_int port,
  387. u_int value);
  388. static __inline uint32_t
  389. ahd_inl(struct ahd_softc *ahd, u_int port);
  390. static __inline void ahd_outl(struct ahd_softc *ahd, u_int port,
  391. uint32_t value);
  392. static __inline uint64_t
  393. ahd_inq(struct ahd_softc *ahd, u_int port);
  394. static __inline void ahd_outq(struct ahd_softc *ahd, u_int port,
  395. uint64_t value);
  396. static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd);
  397. static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
  398. static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd);
  399. static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value);
  400. static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd);
  401. static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value);
  402. static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd);
  403. static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value);
  404. static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd);
  405. static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value);
  406. static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd);
  407. static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value);
  408. static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
  409. static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
  410. static __inline uint32_t
  411. ahd_inl_scbram(struct ahd_softc *ahd, u_int offset);
  412. static __inline uint64_t
  413. ahd_inq_scbram(struct ahd_softc *ahd, u_int offset);
  414. static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd,
  415. struct scb *scb);
  416. static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
  417. static __inline uint8_t *
  418. ahd_get_sense_buf(struct ahd_softc *ahd,
  419. struct scb *scb);
  420. static __inline uint32_t
  421. ahd_get_sense_bufaddr(struct ahd_softc *ahd,
  422. struct scb *scb);
  423. static __inline void
  424. ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
  425. {
  426. uint32_t sgptr;
  427. sgptr = ahd_le32toh(scb->hscb->sgptr);
  428. if ((sgptr & SG_STATUS_VALID) != 0)
  429. ahd_handle_scb_status(ahd, scb);
  430. else
  431. ahd_done(ahd, scb);
  432. }
  433. /*
  434. * Determine whether the sequencer reported a residual
  435. * for this SCB/transaction.
  436. */
  437. static __inline void
  438. ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
  439. {
  440. uint32_t sgptr;
  441. sgptr = ahd_le32toh(scb->hscb->sgptr);
  442. if ((sgptr & SG_STATUS_VALID) != 0)
  443. ahd_calc_residual(ahd, scb);
  444. }
  445. /*
  446. * Return pointers to the transfer negotiation information
  447. * for the specified our_id/remote_id pair.
  448. */
  449. static __inline struct ahd_initiator_tinfo *
  450. ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
  451. u_int remote_id, struct ahd_tmode_tstate **tstate)
  452. {
  453. /*
  454. * Transfer data structures are stored from the perspective
  455. * of the target role. Since the parameters for a connection
  456. * in the initiator role to a given target are the same as
  457. * when the roles are reversed, we pretend we are the target.
  458. */
  459. if (channel == 'B')
  460. our_id += 8;
  461. *tstate = ahd->enabled_targets[our_id];
  462. return (&(*tstate)->transinfo[remote_id]);
  463. }
  464. #define AHD_COPY_COL_IDX(dst, src) \
  465. do { \
  466. dst->hscb->scsiid = src->hscb->scsiid; \
  467. dst->hscb->lun = src->hscb->lun; \
  468. } while (0)
  469. static __inline uint16_t
  470. ahd_inw(struct ahd_softc *ahd, u_int port)
  471. {
  472. /*
  473. * Read high byte first as some registers increment
  474. * or have other side effects when the low byte is
  475. * read.
  476. */
  477. return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
  478. }
  479. static __inline void
  480. ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
  481. {
  482. /*
  483. * Write low byte first to accomodate registers
  484. * such as PRGMCNT where the order maters.
  485. */
  486. ahd_outb(ahd, port, value & 0xFF);
  487. ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
  488. }
  489. static __inline uint32_t
  490. ahd_inl(struct ahd_softc *ahd, u_int port)
  491. {
  492. return ((ahd_inb(ahd, port))
  493. | (ahd_inb(ahd, port+1) << 8)
  494. | (ahd_inb(ahd, port+2) << 16)
  495. | (ahd_inb(ahd, port+3) << 24));
  496. }
  497. static __inline void
  498. ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
  499. {
  500. ahd_outb(ahd, port, (value) & 0xFF);
  501. ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
  502. ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
  503. ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
  504. }
  505. static __inline uint64_t
  506. ahd_inq(struct ahd_softc *ahd, u_int port)
  507. {
  508. return ((ahd_inb(ahd, port))
  509. | (ahd_inb(ahd, port+1) << 8)
  510. | (ahd_inb(ahd, port+2) << 16)
  511. | (ahd_inb(ahd, port+3) << 24)
  512. | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
  513. | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
  514. | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
  515. | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
  516. }
  517. static __inline void
  518. ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
  519. {
  520. ahd_outb(ahd, port, value & 0xFF);
  521. ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
  522. ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
  523. ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
  524. ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
  525. ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
  526. ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
  527. ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
  528. }
  529. static __inline u_int
  530. ahd_get_scbptr(struct ahd_softc *ahd)
  531. {
  532. AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
  533. ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
  534. return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
  535. }
  536. static __inline void
  537. ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
  538. {
  539. AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
  540. ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
  541. ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
  542. ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
  543. }
  544. static __inline u_int
  545. ahd_get_hnscb_qoff(struct ahd_softc *ahd)
  546. {
  547. return (ahd_inw_atomic(ahd, HNSCB_QOFF));
  548. }
  549. static __inline void
  550. ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
  551. {
  552. ahd_outw_atomic(ahd, HNSCB_QOFF, value);
  553. }
  554. static __inline u_int
  555. ahd_get_hescb_qoff(struct ahd_softc *ahd)
  556. {
  557. return (ahd_inb(ahd, HESCB_QOFF));
  558. }
  559. static __inline void
  560. ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
  561. {
  562. ahd_outb(ahd, HESCB_QOFF, value);
  563. }
  564. static __inline u_int
  565. ahd_get_snscb_qoff(struct ahd_softc *ahd)
  566. {
  567. u_int oldvalue;
  568. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  569. oldvalue = ahd_inw(ahd, SNSCB_QOFF);
  570. ahd_outw(ahd, SNSCB_QOFF, oldvalue);
  571. return (oldvalue);
  572. }
  573. static __inline void
  574. ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
  575. {
  576. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  577. ahd_outw(ahd, SNSCB_QOFF, value);
  578. }
  579. static __inline u_int
  580. ahd_get_sescb_qoff(struct ahd_softc *ahd)
  581. {
  582. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  583. return (ahd_inb(ahd, SESCB_QOFF));
  584. }
  585. static __inline void
  586. ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
  587. {
  588. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  589. ahd_outb(ahd, SESCB_QOFF, value);
  590. }
  591. static __inline u_int
  592. ahd_get_sdscb_qoff(struct ahd_softc *ahd)
  593. {
  594. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  595. return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
  596. }
  597. static __inline void
  598. ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
  599. {
  600. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  601. ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
  602. ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
  603. }
  604. static __inline u_int
  605. ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
  606. {
  607. u_int value;
  608. /*
  609. * Workaround PCI-X Rev A. hardware bug.
  610. * After a host read of SCB memory, the chip
  611. * may become confused into thinking prefetch
  612. * was required. This starts the discard timer
  613. * running and can cause an unexpected discard
  614. * timer interrupt. The work around is to read
  615. * a normal register prior to the exhaustion of
  616. * the discard timer. The mode pointer register
  617. * has no side effects and so serves well for
  618. * this purpose.
  619. *
  620. * Razor #528
  621. */
  622. value = ahd_inb(ahd, offset);
  623. if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
  624. ahd_inb(ahd, MODE_PTR);
  625. return (value);
  626. }
  627. static __inline u_int
  628. ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
  629. {
  630. return (ahd_inb_scbram(ahd, offset)
  631. | (ahd_inb_scbram(ahd, offset+1) << 8));
  632. }
  633. static __inline uint32_t
  634. ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
  635. {
  636. return (ahd_inw_scbram(ahd, offset)
  637. | (ahd_inw_scbram(ahd, offset+2) << 16));
  638. }
  639. static __inline uint64_t
  640. ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
  641. {
  642. return (ahd_inl_scbram(ahd, offset)
  643. | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
  644. }
  645. static __inline struct scb *
  646. ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
  647. {
  648. struct scb* scb;
  649. if (tag >= AHD_SCB_MAX)
  650. return (NULL);
  651. scb = ahd->scb_data.scbindex[tag];
  652. if (scb != NULL)
  653. ahd_sync_scb(ahd, scb,
  654. BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  655. return (scb);
  656. }
  657. static __inline void
  658. ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
  659. {
  660. struct hardware_scb *q_hscb;
  661. struct map_node *q_hscb_map;
  662. uint32_t saved_hscb_busaddr;
  663. /*
  664. * Our queuing method is a bit tricky. The card
  665. * knows in advance which HSCB (by address) to download,
  666. * and we can't disappoint it. To achieve this, the next
  667. * HSCB to download is saved off in ahd->next_queued_hscb.
  668. * When we are called to queue "an arbitrary scb",
  669. * we copy the contents of the incoming HSCB to the one
  670. * the sequencer knows about, swap HSCB pointers and
  671. * finally assign the SCB to the tag indexed location
  672. * in the scb_array. This makes sure that we can still
  673. * locate the correct SCB by SCB_TAG.
  674. */
  675. q_hscb = ahd->next_queued_hscb;
  676. q_hscb_map = ahd->next_queued_hscb_map;
  677. saved_hscb_busaddr = q_hscb->hscb_busaddr;
  678. memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
  679. q_hscb->hscb_busaddr = saved_hscb_busaddr;
  680. q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
  681. /* Now swap HSCB pointers. */
  682. ahd->next_queued_hscb = scb->hscb;
  683. ahd->next_queued_hscb_map = scb->hscb_map;
  684. scb->hscb = q_hscb;
  685. scb->hscb_map = q_hscb_map;
  686. /* Now define the mapping from tag to SCB in the scbindex */
  687. ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
  688. }
  689. /*
  690. * Tell the sequencer about a new transaction to execute.
  691. */
  692. static __inline void
  693. ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
  694. {
  695. ahd_swap_with_next_hscb(ahd, scb);
  696. if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
  697. panic("Attempt to queue invalid SCB tag %x\n",
  698. SCB_GET_TAG(scb));
  699. /*
  700. * Keep a history of SCBs we've downloaded in the qinfifo.
  701. */
  702. ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
  703. ahd->qinfifonext++;
  704. if (scb->sg_count != 0)
  705. ahd_setup_data_scb(ahd, scb);
  706. else
  707. ahd_setup_noxfer_scb(ahd, scb);
  708. ahd_setup_scb_common(ahd, scb);
  709. /*
  710. * Make sure our data is consistent from the
  711. * perspective of the adapter.
  712. */
  713. ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  714. #ifdef AHD_DEBUG
  715. if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
  716. uint64_t host_dataptr;
  717. host_dataptr = ahd_le64toh(scb->hscb->dataptr);
  718. printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
  719. ahd_name(ahd),
  720. SCB_GET_TAG(scb), scb->hscb->scsiid,
  721. ahd_le32toh(scb->hscb->hscb_busaddr),
  722. (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
  723. (u_int)(host_dataptr & 0xFFFFFFFF),
  724. ahd_le32toh(scb->hscb->datacnt));
  725. }
  726. #endif
  727. /* Tell the adapter about the newly queued SCB */
  728. ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
  729. }
  730. static __inline uint8_t *
  731. ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
  732. {
  733. return (scb->sense_data);
  734. }
  735. static __inline uint32_t
  736. ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
  737. {
  738. return (scb->sense_busaddr);
  739. }
  740. /************************** Interrupt Processing ******************************/
  741. static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
  742. static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
  743. static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
  744. static __inline int ahd_intr(struct ahd_softc *ahd);
  745. static __inline void
  746. ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
  747. {
  748. ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
  749. /*offset*/0,
  750. /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
  751. }
  752. static __inline void
  753. ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
  754. {
  755. #ifdef AHD_TARGET_MODE
  756. if ((ahd->flags & AHD_TARGETROLE) != 0) {
  757. ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
  758. ahd->shared_data_map.dmamap,
  759. ahd_targetcmd_offset(ahd, 0),
  760. sizeof(struct target_cmd) * AHD_TMODE_CMDS,
  761. op);
  762. }
  763. #endif
  764. }
  765. /*
  766. * See if the firmware has posted any completed commands
  767. * into our in-core command complete fifos.
  768. */
  769. #define AHD_RUN_QOUTFIFO 0x1
  770. #define AHD_RUN_TQINFIFO 0x2
  771. static __inline u_int
  772. ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
  773. {
  774. u_int retval;
  775. retval = 0;
  776. ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
  777. /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
  778. /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
  779. if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
  780. == ahd->qoutfifonext_valid_tag)
  781. retval |= AHD_RUN_QOUTFIFO;
  782. #ifdef AHD_TARGET_MODE
  783. if ((ahd->flags & AHD_TARGETROLE) != 0
  784. && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
  785. ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
  786. ahd->shared_data_map.dmamap,
  787. ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
  788. /*len*/sizeof(struct target_cmd),
  789. BUS_DMASYNC_POSTREAD);
  790. if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
  791. retval |= AHD_RUN_TQINFIFO;
  792. }
  793. #endif
  794. return (retval);
  795. }
  796. /*
  797. * Catch an interrupt from the adapter
  798. */
  799. static __inline int
  800. ahd_intr(struct ahd_softc *ahd)
  801. {
  802. u_int intstat;
  803. if ((ahd->pause & INTEN) == 0) {
  804. /*
  805. * Our interrupt is not enabled on the chip
  806. * and may be disabled for re-entrancy reasons,
  807. * so just return. This is likely just a shared
  808. * interrupt.
  809. */
  810. return (0);
  811. }
  812. /*
  813. * Instead of directly reading the interrupt status register,
  814. * infer the cause of the interrupt by checking our in-core
  815. * completion queues. This avoids a costly PCI bus read in
  816. * most cases.
  817. */
  818. if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
  819. && (ahd_check_cmdcmpltqueues(ahd) != 0))
  820. intstat = CMDCMPLT;
  821. else
  822. intstat = ahd_inb(ahd, INTSTAT);
  823. if ((intstat & INT_PEND) == 0)
  824. return (0);
  825. if (intstat & CMDCMPLT) {
  826. ahd_outb(ahd, CLRINT, CLRCMDINT);
  827. /*
  828. * Ensure that the chip sees that we've cleared
  829. * this interrupt before we walk the output fifo.
  830. * Otherwise, we may, due to posted bus writes,
  831. * clear the interrupt after we finish the scan,
  832. * and after the sequencer has added new entries
  833. * and asserted the interrupt again.
  834. */
  835. if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
  836. if (ahd_is_paused(ahd)) {
  837. /*
  838. * Potentially lost SEQINT.
  839. * If SEQINTCODE is non-zero,
  840. * simulate the SEQINT.
  841. */
  842. if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
  843. intstat |= SEQINT;
  844. }
  845. } else {
  846. ahd_flush_device_writes(ahd);
  847. }
  848. ahd_run_qoutfifo(ahd);
  849. ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
  850. ahd->cmdcmplt_total++;
  851. #ifdef AHD_TARGET_MODE
  852. if ((ahd->flags & AHD_TARGETROLE) != 0)
  853. ahd_run_tqinfifo(ahd, /*paused*/FALSE);
  854. #endif
  855. }
  856. /*
  857. * Handle statuses that may invalidate our cached
  858. * copy of INTSTAT separately.
  859. */
  860. if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
  861. /* Hot eject. Do nothing */
  862. } else if (intstat & HWERRINT) {
  863. ahd_handle_hwerrint(ahd);
  864. } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
  865. ahd->bus_intr(ahd);
  866. } else {
  867. if ((intstat & SEQINT) != 0)
  868. ahd_handle_seqint(ahd, intstat);
  869. if ((intstat & SCSIINT) != 0)
  870. ahd_handle_scsiint(ahd, intstat);
  871. }
  872. return (1);
  873. }
  874. #endif /* _AIC79XX_INLINE_H_ */