aic79xx_inline.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  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#51 $
  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. return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
  473. }
  474. static __inline void
  475. ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
  476. {
  477. ahd_outb(ahd, port, value & 0xFF);
  478. ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
  479. }
  480. static __inline uint32_t
  481. ahd_inl(struct ahd_softc *ahd, u_int port)
  482. {
  483. return ((ahd_inb(ahd, port))
  484. | (ahd_inb(ahd, port+1) << 8)
  485. | (ahd_inb(ahd, port+2) << 16)
  486. | (ahd_inb(ahd, port+3) << 24));
  487. }
  488. static __inline void
  489. ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
  490. {
  491. ahd_outb(ahd, port, (value) & 0xFF);
  492. ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
  493. ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
  494. ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
  495. }
  496. static __inline uint64_t
  497. ahd_inq(struct ahd_softc *ahd, u_int port)
  498. {
  499. return ((ahd_inb(ahd, port))
  500. | (ahd_inb(ahd, port+1) << 8)
  501. | (ahd_inb(ahd, port+2) << 16)
  502. | (ahd_inb(ahd, port+3) << 24)
  503. | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
  504. | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
  505. | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
  506. | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
  507. }
  508. static __inline void
  509. ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
  510. {
  511. ahd_outb(ahd, port, value & 0xFF);
  512. ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
  513. ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
  514. ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
  515. ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
  516. ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
  517. ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
  518. ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
  519. }
  520. static __inline u_int
  521. ahd_get_scbptr(struct ahd_softc *ahd)
  522. {
  523. AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
  524. ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
  525. return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
  526. }
  527. static __inline void
  528. ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
  529. {
  530. AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
  531. ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
  532. ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
  533. ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
  534. }
  535. static __inline u_int
  536. ahd_get_hnscb_qoff(struct ahd_softc *ahd)
  537. {
  538. return (ahd_inw_atomic(ahd, HNSCB_QOFF));
  539. }
  540. static __inline void
  541. ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
  542. {
  543. ahd_outw_atomic(ahd, HNSCB_QOFF, value);
  544. }
  545. static __inline u_int
  546. ahd_get_hescb_qoff(struct ahd_softc *ahd)
  547. {
  548. return (ahd_inb(ahd, HESCB_QOFF));
  549. }
  550. static __inline void
  551. ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
  552. {
  553. ahd_outb(ahd, HESCB_QOFF, value);
  554. }
  555. static __inline u_int
  556. ahd_get_snscb_qoff(struct ahd_softc *ahd)
  557. {
  558. u_int oldvalue;
  559. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  560. oldvalue = ahd_inw(ahd, SNSCB_QOFF);
  561. ahd_outw(ahd, SNSCB_QOFF, oldvalue);
  562. return (oldvalue);
  563. }
  564. static __inline void
  565. ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
  566. {
  567. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  568. ahd_outw(ahd, SNSCB_QOFF, value);
  569. }
  570. static __inline u_int
  571. ahd_get_sescb_qoff(struct ahd_softc *ahd)
  572. {
  573. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  574. return (ahd_inb(ahd, SESCB_QOFF));
  575. }
  576. static __inline void
  577. ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
  578. {
  579. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  580. ahd_outb(ahd, SESCB_QOFF, value);
  581. }
  582. static __inline u_int
  583. ahd_get_sdscb_qoff(struct ahd_softc *ahd)
  584. {
  585. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  586. return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
  587. }
  588. static __inline void
  589. ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
  590. {
  591. AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
  592. ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
  593. ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
  594. }
  595. static __inline u_int
  596. ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
  597. {
  598. u_int value;
  599. /*
  600. * Workaround PCI-X Rev A. hardware bug.
  601. * After a host read of SCB memory, the chip
  602. * may become confused into thinking prefetch
  603. * was required. This starts the discard timer
  604. * running and can cause an unexpected discard
  605. * timer interrupt. The work around is to read
  606. * a normal register prior to the exhaustion of
  607. * the discard timer. The mode pointer register
  608. * has no side effects and so serves well for
  609. * this purpose.
  610. *
  611. * Razor #528
  612. */
  613. value = ahd_inb(ahd, offset);
  614. if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)
  615. ahd_inb(ahd, MODE_PTR);
  616. return (value);
  617. }
  618. static __inline u_int
  619. ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
  620. {
  621. return (ahd_inb_scbram(ahd, offset)
  622. | (ahd_inb_scbram(ahd, offset+1) << 8));
  623. }
  624. static __inline uint32_t
  625. ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
  626. {
  627. return (ahd_inw_scbram(ahd, offset)
  628. | (ahd_inw_scbram(ahd, offset+2) << 16));
  629. }
  630. static __inline uint64_t
  631. ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
  632. {
  633. return (ahd_inl_scbram(ahd, offset)
  634. | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
  635. }
  636. static __inline struct scb *
  637. ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
  638. {
  639. struct scb* scb;
  640. if (tag >= AHD_SCB_MAX)
  641. return (NULL);
  642. scb = ahd->scb_data.scbindex[tag];
  643. if (scb != NULL)
  644. ahd_sync_scb(ahd, scb,
  645. BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  646. return (scb);
  647. }
  648. static __inline void
  649. ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
  650. {
  651. struct hardware_scb *q_hscb;
  652. uint32_t saved_hscb_busaddr;
  653. /*
  654. * Our queuing method is a bit tricky. The card
  655. * knows in advance which HSCB (by address) to download,
  656. * and we can't disappoint it. To achieve this, the next
  657. * HSCB to download is saved off in ahd->next_queued_hscb.
  658. * When we are called to queue "an arbitrary scb",
  659. * we copy the contents of the incoming HSCB to the one
  660. * the sequencer knows about, swap HSCB pointers and
  661. * finally assign the SCB to the tag indexed location
  662. * in the scb_array. This makes sure that we can still
  663. * locate the correct SCB by SCB_TAG.
  664. */
  665. q_hscb = ahd->next_queued_hscb;
  666. saved_hscb_busaddr = q_hscb->hscb_busaddr;
  667. memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
  668. q_hscb->hscb_busaddr = saved_hscb_busaddr;
  669. q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
  670. /* Now swap HSCB pointers. */
  671. ahd->next_queued_hscb = scb->hscb;
  672. scb->hscb = q_hscb;
  673. /* Now define the mapping from tag to SCB in the scbindex */
  674. ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
  675. }
  676. /*
  677. * Tell the sequencer about a new transaction to execute.
  678. */
  679. static __inline void
  680. ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
  681. {
  682. ahd_swap_with_next_hscb(ahd, scb);
  683. if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
  684. panic("Attempt to queue invalid SCB tag %x\n",
  685. SCB_GET_TAG(scb));
  686. /*
  687. * Keep a history of SCBs we've downloaded in the qinfifo.
  688. */
  689. ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
  690. ahd->qinfifonext++;
  691. if (scb->sg_count != 0)
  692. ahd_setup_data_scb(ahd, scb);
  693. else
  694. ahd_setup_noxfer_scb(ahd, scb);
  695. ahd_setup_scb_common(ahd, scb);
  696. /*
  697. * Make sure our data is consistent from the
  698. * perspective of the adapter.
  699. */
  700. ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  701. #ifdef AHD_DEBUG
  702. if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
  703. uint64_t host_dataptr;
  704. host_dataptr = ahd_le64toh(scb->hscb->dataptr);
  705. printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
  706. ahd_name(ahd),
  707. SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
  708. (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
  709. (u_int)(host_dataptr & 0xFFFFFFFF),
  710. ahd_le32toh(scb->hscb->datacnt));
  711. }
  712. #endif
  713. /* Tell the adapter about the newly queued SCB */
  714. ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
  715. }
  716. static __inline uint8_t *
  717. ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
  718. {
  719. return (scb->sense_data);
  720. }
  721. static __inline uint32_t
  722. ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
  723. {
  724. return (scb->sense_busaddr);
  725. }
  726. /************************** Interrupt Processing ******************************/
  727. static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
  728. static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
  729. static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
  730. static __inline int ahd_intr(struct ahd_softc *ahd);
  731. static __inline void
  732. ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
  733. {
  734. ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
  735. /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op);
  736. }
  737. static __inline void
  738. ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
  739. {
  740. #ifdef AHD_TARGET_MODE
  741. if ((ahd->flags & AHD_TARGETROLE) != 0) {
  742. ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
  743. ahd->shared_data_dmamap,
  744. ahd_targetcmd_offset(ahd, 0),
  745. sizeof(struct target_cmd) * AHD_TMODE_CMDS,
  746. op);
  747. }
  748. #endif
  749. }
  750. /*
  751. * See if the firmware has posted any completed commands
  752. * into our in-core command complete fifos.
  753. */
  754. #define AHD_RUN_QOUTFIFO 0x1
  755. #define AHD_RUN_TQINFIFO 0x2
  756. static __inline u_int
  757. ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
  758. {
  759. u_int retval;
  760. retval = 0;
  761. ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
  762. /*offset*/ahd->qoutfifonext, /*len*/2,
  763. BUS_DMASYNC_POSTREAD);
  764. if ((ahd->qoutfifo[ahd->qoutfifonext]
  765. & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)
  766. retval |= AHD_RUN_QOUTFIFO;
  767. #ifdef AHD_TARGET_MODE
  768. if ((ahd->flags & AHD_TARGETROLE) != 0
  769. && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
  770. ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
  771. ahd->shared_data_dmamap,
  772. ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
  773. /*len*/sizeof(struct target_cmd),
  774. BUS_DMASYNC_POSTREAD);
  775. if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
  776. retval |= AHD_RUN_TQINFIFO;
  777. }
  778. #endif
  779. return (retval);
  780. }
  781. /*
  782. * Catch an interrupt from the adapter
  783. */
  784. static __inline int
  785. ahd_intr(struct ahd_softc *ahd)
  786. {
  787. u_int intstat;
  788. if ((ahd->pause & INTEN) == 0) {
  789. /*
  790. * Our interrupt is not enabled on the chip
  791. * and may be disabled for re-entrancy reasons,
  792. * so just return. This is likely just a shared
  793. * interrupt.
  794. */
  795. return (0);
  796. }
  797. /*
  798. * Instead of directly reading the interrupt status register,
  799. * infer the cause of the interrupt by checking our in-core
  800. * completion queues. This avoids a costly PCI bus read in
  801. * most cases.
  802. */
  803. if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
  804. && (ahd_check_cmdcmpltqueues(ahd) != 0))
  805. intstat = CMDCMPLT;
  806. else
  807. intstat = ahd_inb(ahd, INTSTAT);
  808. if ((intstat & INT_PEND) == 0)
  809. return (0);
  810. if (intstat & CMDCMPLT) {
  811. ahd_outb(ahd, CLRINT, CLRCMDINT);
  812. /*
  813. * Ensure that the chip sees that we've cleared
  814. * this interrupt before we walk the output fifo.
  815. * Otherwise, we may, due to posted bus writes,
  816. * clear the interrupt after we finish the scan,
  817. * and after the sequencer has added new entries
  818. * and asserted the interrupt again.
  819. */
  820. if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
  821. if (ahd_is_paused(ahd)) {
  822. /*
  823. * Potentially lost SEQINT.
  824. * If SEQINTCODE is non-zero,
  825. * simulate the SEQINT.
  826. */
  827. if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
  828. intstat |= SEQINT;
  829. }
  830. } else {
  831. ahd_flush_device_writes(ahd);
  832. }
  833. ahd_run_qoutfifo(ahd);
  834. ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
  835. ahd->cmdcmplt_total++;
  836. #ifdef AHD_TARGET_MODE
  837. if ((ahd->flags & AHD_TARGETROLE) != 0)
  838. ahd_run_tqinfifo(ahd, /*paused*/FALSE);
  839. #endif
  840. }
  841. /*
  842. * Handle statuses that may invalidate our cached
  843. * copy of INTSTAT separately.
  844. */
  845. if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
  846. /* Hot eject. Do nothing */
  847. } else if (intstat & HWERRINT) {
  848. ahd_handle_hwerrint(ahd);
  849. } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
  850. ahd->bus_intr(ahd);
  851. } else {
  852. if ((intstat & SEQINT) != 0)
  853. ahd_handle_seqint(ahd, intstat);
  854. if ((intstat & SCSIINT) != 0)
  855. ahd_handle_scsiint(ahd, intstat);
  856. }
  857. return (1);
  858. }
  859. #endif /* _AIC79XX_INLINE_H_ */