aic7xxx_inline.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /*
  2. * Inline routines shareable across OS platforms.
  3. *
  4. * Copyright (c) 1994-2001 Justin T. Gibbs.
  5. * Copyright (c) 2000-2001 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/aic7xxx_inline.h#43 $
  41. *
  42. * $FreeBSD$
  43. */
  44. #ifndef _AIC7XXX_INLINE_H_
  45. #define _AIC7XXX_INLINE_H_
  46. /************************* Sequencer Execution Control ************************/
  47. static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
  48. static __inline int ahc_is_paused(struct ahc_softc *ahc);
  49. static __inline void ahc_pause(struct ahc_softc *ahc);
  50. static __inline void ahc_unpause(struct ahc_softc *ahc);
  51. /*
  52. * Work around any chip bugs related to halting sequencer execution.
  53. * On Ultra2 controllers, we must clear the CIOBUS stretch signal by
  54. * reading a register that will set this signal and deassert it.
  55. * Without this workaround, if the chip is paused, by an interrupt or
  56. * manual pause while accessing scb ram, accesses to certain registers
  57. * will hang the system (infinite pci retries).
  58. */
  59. static __inline void
  60. ahc_pause_bug_fix(struct ahc_softc *ahc)
  61. {
  62. if ((ahc->features & AHC_ULTRA2) != 0)
  63. (void)ahc_inb(ahc, CCSCBCTL);
  64. }
  65. /*
  66. * Determine whether the sequencer has halted code execution.
  67. * Returns non-zero status if the sequencer is stopped.
  68. */
  69. static __inline int
  70. ahc_is_paused(struct ahc_softc *ahc)
  71. {
  72. return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
  73. }
  74. /*
  75. * Request that the sequencer stop and wait, indefinitely, for it
  76. * to stop. The sequencer will only acknowledge that it is paused
  77. * once it has reached an instruction boundary and PAUSEDIS is
  78. * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
  79. * for critical sections.
  80. */
  81. static __inline void
  82. ahc_pause(struct ahc_softc *ahc)
  83. {
  84. ahc_outb(ahc, HCNTRL, ahc->pause);
  85. /*
  86. * Since the sequencer can disable pausing in a critical section, we
  87. * must loop until it actually stops.
  88. */
  89. while (ahc_is_paused(ahc) == 0)
  90. ;
  91. ahc_pause_bug_fix(ahc);
  92. }
  93. /*
  94. * Allow the sequencer to continue program execution.
  95. * We check here to ensure that no additional interrupt
  96. * sources that would cause the sequencer to halt have been
  97. * asserted. If, for example, a SCSI bus reset is detected
  98. * while we are fielding a different, pausing, interrupt type,
  99. * we don't want to release the sequencer before going back
  100. * into our interrupt handler and dealing with this new
  101. * condition.
  102. */
  103. static __inline void
  104. ahc_unpause(struct ahc_softc *ahc)
  105. {
  106. if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
  107. ahc_outb(ahc, HCNTRL, ahc->unpause);
  108. }
  109. /*********************** Untagged Transaction Routines ************************/
  110. static __inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc);
  111. static __inline void ahc_release_untagged_queues(struct ahc_softc *ahc);
  112. /*
  113. * Block our completion routine from starting the next untagged
  114. * transaction for this target or target lun.
  115. */
  116. static __inline void
  117. ahc_freeze_untagged_queues(struct ahc_softc *ahc)
  118. {
  119. if ((ahc->flags & AHC_SCB_BTT) == 0)
  120. ahc->untagged_queue_lock++;
  121. }
  122. /*
  123. * Allow the next untagged transaction for this target or target lun
  124. * to be executed. We use a counting semaphore to allow the lock
  125. * to be acquired recursively. Once the count drops to zero, the
  126. * transaction queues will be run.
  127. */
  128. static __inline void
  129. ahc_release_untagged_queues(struct ahc_softc *ahc)
  130. {
  131. if ((ahc->flags & AHC_SCB_BTT) == 0) {
  132. ahc->untagged_queue_lock--;
  133. if (ahc->untagged_queue_lock == 0)
  134. ahc_run_untagged_queues(ahc);
  135. }
  136. }
  137. /************************** Memory mapping routines ***************************/
  138. static __inline struct ahc_dma_seg *
  139. ahc_sg_bus_to_virt(struct scb *scb,
  140. uint32_t sg_busaddr);
  141. static __inline uint32_t
  142. ahc_sg_virt_to_bus(struct scb *scb,
  143. struct ahc_dma_seg *sg);
  144. static __inline uint32_t
  145. ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index);
  146. static __inline void ahc_sync_scb(struct ahc_softc *ahc,
  147. struct scb *scb, int op);
  148. static __inline void ahc_sync_sglist(struct ahc_softc *ahc,
  149. struct scb *scb, int op);
  150. static __inline uint32_t
  151. ahc_targetcmd_offset(struct ahc_softc *ahc,
  152. u_int index);
  153. static __inline struct ahc_dma_seg *
  154. ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
  155. {
  156. int sg_index;
  157. sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
  158. /* sg_list_phys points to entry 1, not 0 */
  159. sg_index++;
  160. return (&scb->sg_list[sg_index]);
  161. }
  162. static __inline uint32_t
  163. ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
  164. {
  165. int sg_index;
  166. /* sg_list_phys points to entry 1, not 0 */
  167. sg_index = sg - &scb->sg_list[1];
  168. return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
  169. }
  170. static __inline uint32_t
  171. ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
  172. {
  173. return (ahc->scb_data->hscb_busaddr
  174. + (sizeof(struct hardware_scb) * index));
  175. }
  176. static __inline void
  177. ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
  178. {
  179. ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
  180. ahc->scb_data->hscb_dmamap,
  181. /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
  182. /*len*/sizeof(*scb->hscb), op);
  183. }
  184. static __inline void
  185. ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
  186. {
  187. if (scb->sg_count == 0)
  188. return;
  189. ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
  190. /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
  191. * sizeof(struct ahc_dma_seg),
  192. /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
  193. }
  194. static __inline uint32_t
  195. ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
  196. {
  197. return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
  198. }
  199. /******************************** Debugging ***********************************/
  200. static __inline char *ahc_name(struct ahc_softc *ahc);
  201. static __inline char *
  202. ahc_name(struct ahc_softc *ahc)
  203. {
  204. return (ahc->name);
  205. }
  206. /*********************** Miscelaneous Support Functions ***********************/
  207. static __inline void ahc_update_residual(struct ahc_softc *ahc,
  208. struct scb *scb);
  209. static __inline struct ahc_initiator_tinfo *
  210. ahc_fetch_transinfo(struct ahc_softc *ahc,
  211. char channel, u_int our_id,
  212. u_int remote_id,
  213. struct ahc_tmode_tstate **tstate);
  214. static __inline uint16_t
  215. ahc_inw(struct ahc_softc *ahc, u_int port);
  216. static __inline void ahc_outw(struct ahc_softc *ahc, u_int port,
  217. u_int value);
  218. static __inline uint32_t
  219. ahc_inl(struct ahc_softc *ahc, u_int port);
  220. static __inline void ahc_outl(struct ahc_softc *ahc, u_int port,
  221. uint32_t value);
  222. static __inline uint64_t
  223. ahc_inq(struct ahc_softc *ahc, u_int port);
  224. static __inline void ahc_outq(struct ahc_softc *ahc, u_int port,
  225. uint64_t value);
  226. static __inline struct scb*
  227. ahc_get_scb(struct ahc_softc *ahc);
  228. static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
  229. static __inline void ahc_swap_with_next_hscb(struct ahc_softc *ahc,
  230. struct scb *scb);
  231. static __inline void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
  232. static __inline struct scsi_sense_data *
  233. ahc_get_sense_buf(struct ahc_softc *ahc,
  234. struct scb *scb);
  235. static __inline uint32_t
  236. ahc_get_sense_bufaddr(struct ahc_softc *ahc,
  237. struct scb *scb);
  238. /*
  239. * Determine whether the sequencer reported a residual
  240. * for this SCB/transaction.
  241. */
  242. static __inline void
  243. ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
  244. {
  245. uint32_t sgptr;
  246. sgptr = ahc_le32toh(scb->hscb->sgptr);
  247. if ((sgptr & SG_RESID_VALID) != 0)
  248. ahc_calc_residual(ahc, scb);
  249. }
  250. /*
  251. * Return pointers to the transfer negotiation information
  252. * for the specified our_id/remote_id pair.
  253. */
  254. static __inline struct ahc_initiator_tinfo *
  255. ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
  256. u_int remote_id, struct ahc_tmode_tstate **tstate)
  257. {
  258. /*
  259. * Transfer data structures are stored from the perspective
  260. * of the target role. Since the parameters for a connection
  261. * in the initiator role to a given target are the same as
  262. * when the roles are reversed, we pretend we are the target.
  263. */
  264. if (channel == 'B')
  265. our_id += 8;
  266. *tstate = ahc->enabled_targets[our_id];
  267. return (&(*tstate)->transinfo[remote_id]);
  268. }
  269. static __inline uint16_t
  270. ahc_inw(struct ahc_softc *ahc, u_int port)
  271. {
  272. return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port));
  273. }
  274. static __inline void
  275. ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
  276. {
  277. ahc_outb(ahc, port, value & 0xFF);
  278. ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
  279. }
  280. static __inline uint32_t
  281. ahc_inl(struct ahc_softc *ahc, u_int port)
  282. {
  283. return ((ahc_inb(ahc, port))
  284. | (ahc_inb(ahc, port+1) << 8)
  285. | (ahc_inb(ahc, port+2) << 16)
  286. | (ahc_inb(ahc, port+3) << 24));
  287. }
  288. static __inline void
  289. ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
  290. {
  291. ahc_outb(ahc, port, (value) & 0xFF);
  292. ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
  293. ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
  294. ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
  295. }
  296. static __inline uint64_t
  297. ahc_inq(struct ahc_softc *ahc, u_int port)
  298. {
  299. return ((ahc_inb(ahc, port))
  300. | (ahc_inb(ahc, port+1) << 8)
  301. | (ahc_inb(ahc, port+2) << 16)
  302. | (ahc_inb(ahc, port+3) << 24)
  303. | (((uint64_t)ahc_inb(ahc, port+4)) << 32)
  304. | (((uint64_t)ahc_inb(ahc, port+5)) << 40)
  305. | (((uint64_t)ahc_inb(ahc, port+6)) << 48)
  306. | (((uint64_t)ahc_inb(ahc, port+7)) << 56));
  307. }
  308. static __inline void
  309. ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
  310. {
  311. ahc_outb(ahc, port, value & 0xFF);
  312. ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
  313. ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
  314. ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
  315. ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
  316. ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
  317. ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
  318. ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
  319. }
  320. /*
  321. * Get a free scb. If there are none, see if we can allocate a new SCB.
  322. */
  323. static __inline struct scb *
  324. ahc_get_scb(struct ahc_softc *ahc)
  325. {
  326. struct scb *scb;
  327. if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
  328. ahc_alloc_scbs(ahc);
  329. scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
  330. if (scb == NULL)
  331. return (NULL);
  332. }
  333. SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
  334. return (scb);
  335. }
  336. /*
  337. * Return an SCB resource to the free list.
  338. */
  339. static __inline void
  340. ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
  341. {
  342. struct hardware_scb *hscb;
  343. hscb = scb->hscb;
  344. /* Clean up for the next user */
  345. ahc->scb_data->scbindex[hscb->tag] = NULL;
  346. scb->flags = SCB_FREE;
  347. hscb->control = 0;
  348. SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
  349. /* Notify the OSM that a resource is now available. */
  350. ahc_platform_scb_free(ahc, scb);
  351. }
  352. static __inline struct scb *
  353. ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
  354. {
  355. struct scb* scb;
  356. scb = ahc->scb_data->scbindex[tag];
  357. if (scb != NULL)
  358. ahc_sync_scb(ahc, scb,
  359. BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  360. return (scb);
  361. }
  362. static __inline void
  363. ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
  364. {
  365. struct hardware_scb *q_hscb;
  366. u_int saved_tag;
  367. /*
  368. * Our queuing method is a bit tricky. The card
  369. * knows in advance which HSCB to download, and we
  370. * can't disappoint it. To achieve this, the next
  371. * SCB to download is saved off in ahc->next_queued_scb.
  372. * When we are called to queue "an arbitrary scb",
  373. * we copy the contents of the incoming HSCB to the one
  374. * the sequencer knows about, swap HSCB pointers and
  375. * finally assign the SCB to the tag indexed location
  376. * in the scb_array. This makes sure that we can still
  377. * locate the correct SCB by SCB_TAG.
  378. */
  379. q_hscb = ahc->next_queued_scb->hscb;
  380. saved_tag = q_hscb->tag;
  381. memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
  382. if ((scb->flags & SCB_CDB32_PTR) != 0) {
  383. q_hscb->shared_data.cdb_ptr =
  384. ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
  385. + offsetof(struct hardware_scb, cdb32));
  386. }
  387. q_hscb->tag = saved_tag;
  388. q_hscb->next = scb->hscb->tag;
  389. /* Now swap HSCB pointers. */
  390. ahc->next_queued_scb->hscb = scb->hscb;
  391. scb->hscb = q_hscb;
  392. /* Now define the mapping from tag to SCB in the scbindex */
  393. ahc->scb_data->scbindex[scb->hscb->tag] = scb;
  394. }
  395. /*
  396. * Tell the sequencer about a new transaction to execute.
  397. */
  398. static __inline void
  399. ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
  400. {
  401. ahc_swap_with_next_hscb(ahc, scb);
  402. if (scb->hscb->tag == SCB_LIST_NULL
  403. || scb->hscb->next == SCB_LIST_NULL)
  404. panic("Attempt to queue invalid SCB tag %x:%x\n",
  405. scb->hscb->tag, scb->hscb->next);
  406. /*
  407. * Setup data "oddness".
  408. */
  409. scb->hscb->lun &= LID;
  410. if (ahc_get_transfer_length(scb) & 0x1)
  411. scb->hscb->lun |= SCB_XFERLEN_ODD;
  412. /*
  413. * Keep a history of SCBs we've downloaded in the qinfifo.
  414. */
  415. ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
  416. /*
  417. * Make sure our data is consistent from the
  418. * perspective of the adapter.
  419. */
  420. ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  421. /* Tell the adapter about the newly queued SCB */
  422. if ((ahc->features & AHC_QUEUE_REGS) != 0) {
  423. ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
  424. } else {
  425. if ((ahc->features & AHC_AUTOPAUSE) == 0)
  426. ahc_pause(ahc);
  427. ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
  428. if ((ahc->features & AHC_AUTOPAUSE) == 0)
  429. ahc_unpause(ahc);
  430. }
  431. }
  432. static __inline struct scsi_sense_data *
  433. ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
  434. {
  435. int offset;
  436. offset = scb - ahc->scb_data->scbarray;
  437. return (&ahc->scb_data->sense[offset]);
  438. }
  439. static __inline uint32_t
  440. ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
  441. {
  442. int offset;
  443. offset = scb - ahc->scb_data->scbarray;
  444. return (ahc->scb_data->sense_busaddr
  445. + (offset * sizeof(struct scsi_sense_data)));
  446. }
  447. /************************** Interrupt Processing ******************************/
  448. static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
  449. static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
  450. static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
  451. static __inline int ahc_intr(struct ahc_softc *ahc);
  452. static __inline void
  453. ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
  454. {
  455. ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
  456. /*offset*/0, /*len*/256, op);
  457. }
  458. static __inline void
  459. ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
  460. {
  461. #ifdef AHC_TARGET_MODE
  462. if ((ahc->flags & AHC_TARGETROLE) != 0) {
  463. ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
  464. ahc->shared_data_dmamap,
  465. ahc_targetcmd_offset(ahc, 0),
  466. sizeof(struct target_cmd) * AHC_TMODE_CMDS,
  467. op);
  468. }
  469. #endif
  470. }
  471. /*
  472. * See if the firmware has posted any completed commands
  473. * into our in-core command complete fifos.
  474. */
  475. #define AHC_RUN_QOUTFIFO 0x1
  476. #define AHC_RUN_TQINFIFO 0x2
  477. static __inline u_int
  478. ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
  479. {
  480. u_int retval;
  481. retval = 0;
  482. ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
  483. /*offset*/ahc->qoutfifonext, /*len*/1,
  484. BUS_DMASYNC_POSTREAD);
  485. if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
  486. retval |= AHC_RUN_QOUTFIFO;
  487. #ifdef AHC_TARGET_MODE
  488. if ((ahc->flags & AHC_TARGETROLE) != 0
  489. && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
  490. ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
  491. ahc->shared_data_dmamap,
  492. ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
  493. /*len*/sizeof(struct target_cmd),
  494. BUS_DMASYNC_POSTREAD);
  495. if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
  496. retval |= AHC_RUN_TQINFIFO;
  497. }
  498. #endif
  499. return (retval);
  500. }
  501. /*
  502. * Catch an interrupt from the adapter
  503. */
  504. static __inline int
  505. ahc_intr(struct ahc_softc *ahc)
  506. {
  507. u_int intstat;
  508. if ((ahc->pause & INTEN) == 0) {
  509. /*
  510. * Our interrupt is not enabled on the chip
  511. * and may be disabled for re-entrancy reasons,
  512. * so just return. This is likely just a shared
  513. * interrupt.
  514. */
  515. return (0);
  516. }
  517. /*
  518. * Instead of directly reading the interrupt status register,
  519. * infer the cause of the interrupt by checking our in-core
  520. * completion queues. This avoids a costly PCI bus read in
  521. * most cases.
  522. */
  523. if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
  524. && (ahc_check_cmdcmpltqueues(ahc) != 0))
  525. intstat = CMDCMPLT;
  526. else {
  527. intstat = ahc_inb(ahc, INTSTAT);
  528. }
  529. if ((intstat & INT_PEND) == 0) {
  530. #if AHC_PCI_CONFIG > 0
  531. if (ahc->unsolicited_ints > 500) {
  532. ahc->unsolicited_ints = 0;
  533. if ((ahc->chip & AHC_PCI) != 0
  534. && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
  535. ahc->bus_intr(ahc);
  536. }
  537. #endif
  538. ahc->unsolicited_ints++;
  539. return (0);
  540. }
  541. ahc->unsolicited_ints = 0;
  542. if (intstat & CMDCMPLT) {
  543. ahc_outb(ahc, CLRINT, CLRCMDINT);
  544. /*
  545. * Ensure that the chip sees that we've cleared
  546. * this interrupt before we walk the output fifo.
  547. * Otherwise, we may, due to posted bus writes,
  548. * clear the interrupt after we finish the scan,
  549. * and after the sequencer has added new entries
  550. * and asserted the interrupt again.
  551. */
  552. ahc_flush_device_writes(ahc);
  553. ahc_run_qoutfifo(ahc);
  554. #ifdef AHC_TARGET_MODE
  555. if ((ahc->flags & AHC_TARGETROLE) != 0)
  556. ahc_run_tqinfifo(ahc, /*paused*/FALSE);
  557. #endif
  558. }
  559. /*
  560. * Handle statuses that may invalidate our cached
  561. * copy of INTSTAT separately.
  562. */
  563. if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
  564. /* Hot eject. Do nothing */
  565. } else if (intstat & BRKADRINT) {
  566. ahc_handle_brkadrint(ahc);
  567. } else if ((intstat & (SEQINT|SCSIINT)) != 0) {
  568. ahc_pause_bug_fix(ahc);
  569. if ((intstat & SEQINT) != 0)
  570. ahc_handle_seqint(ahc, intstat);
  571. if ((intstat & SCSIINT) != 0)
  572. ahc_handle_scsiint(ahc, intstat);
  573. }
  574. return (1);
  575. }
  576. #endif /* _AIC7XXX_INLINE_H_ */