aic79xx_inline.h 29 KB

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