aic79xx_inline.h 28 KB

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