aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx/aic79xx_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_core.c')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c771
1 files changed, 766 insertions, 5 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index ade0fb8fbdb..336f4bea251 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -266,8 +266,752 @@ static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
266 int target, char channel, int lun, 266 int target, char channel, int lun,
267 u_int tag, role_t role); 267 u_int tag, role_t role);
268 268
269/******************************** Private Inlines *****************************/ 269/************************ Sequencer Execution Control *************************/
270void
271ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
272{
273 if (ahd->src_mode == src && ahd->dst_mode == dst)
274 return;
275#ifdef AHD_DEBUG
276 if (ahd->src_mode == AHD_MODE_UNKNOWN
277 || ahd->dst_mode == AHD_MODE_UNKNOWN)
278 panic("Setting mode prior to saving it.\n");
279 if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
280 printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
281 ahd_build_mode_state(ahd, src, dst));
282#endif
283 ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
284 ahd->src_mode = src;
285 ahd->dst_mode = dst;
286}
287
288void
289ahd_update_modes(struct ahd_softc *ahd)
290{
291 ahd_mode_state mode_ptr;
292 ahd_mode src;
293 ahd_mode dst;
294
295 mode_ptr = ahd_inb(ahd, MODE_PTR);
296#ifdef AHD_DEBUG
297 if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
298 printf("Reading mode 0x%x\n", mode_ptr);
299#endif
300 ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
301 ahd_known_modes(ahd, src, dst);
302}
303
304void
305ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
306 ahd_mode dstmode, const char *file, int line)
307{
308#ifdef AHD_DEBUG
309 if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
310 || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
311 panic("%s:%s:%d: Mode assertion failed.\n",
312 ahd_name(ahd), file, line);
313 }
314#endif
315}
316
317#define AHD_ASSERT_MODES(ahd, source, dest) \
318 ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
319
320ahd_mode_state
321ahd_save_modes(struct ahd_softc *ahd)
322{
323 if (ahd->src_mode == AHD_MODE_UNKNOWN
324 || ahd->dst_mode == AHD_MODE_UNKNOWN)
325 ahd_update_modes(ahd);
326
327 return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
328}
329
330void
331ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
332{
333 ahd_mode src;
334 ahd_mode dst;
335
336 ahd_extract_mode_state(ahd, state, &src, &dst);
337 ahd_set_modes(ahd, src, dst);
338}
339
340/*
341 * Determine whether the sequencer has halted code execution.
342 * Returns non-zero status if the sequencer is stopped.
343 */
344int
345ahd_is_paused(struct ahd_softc *ahd)
346{
347 return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
348}
349
350/*
351 * Request that the sequencer stop and wait, indefinitely, for it
352 * to stop. The sequencer will only acknowledge that it is paused
353 * once it has reached an instruction boundary and PAUSEDIS is
354 * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
355 * for critical sections.
356 */
357void
358ahd_pause(struct ahd_softc *ahd)
359{
360 ahd_outb(ahd, HCNTRL, ahd->pause);
361
362 /*
363 * Since the sequencer can disable pausing in a critical section, we
364 * must loop until it actually stops.
365 */
366 while (ahd_is_paused(ahd) == 0)
367 ;
368}
369
370/*
371 * Allow the sequencer to continue program execution.
372 * We check here to ensure that no additional interrupt
373 * sources that would cause the sequencer to halt have been
374 * asserted. If, for example, a SCSI bus reset is detected
375 * while we are fielding a different, pausing, interrupt type,
376 * we don't want to release the sequencer before going back
377 * into our interrupt handler and dealing with this new
378 * condition.
379 */
380void
381ahd_unpause(struct ahd_softc *ahd)
382{
383 /*
384 * Automatically restore our modes to those saved
385 * prior to the first change of the mode.
386 */
387 if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
388 && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
389 if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
390 ahd_reset_cmds_pending(ahd);
391 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
392 }
393
394 if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
395 ahd_outb(ahd, HCNTRL, ahd->unpause);
396
397 ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
398}
399
400/*********************** Scatter Gather List Handling *************************/
401void *
402ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
403 void *sgptr, dma_addr_t addr, bus_size_t len, int last)
404{
405 scb->sg_count++;
406 if (sizeof(dma_addr_t) > 4
407 && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
408 struct ahd_dma64_seg *sg;
409
410 sg = (struct ahd_dma64_seg *)sgptr;
411 sg->addr = ahd_htole64(addr);
412 sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
413 return (sg + 1);
414 } else {
415 struct ahd_dma_seg *sg;
416
417 sg = (struct ahd_dma_seg *)sgptr;
418 sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
419 sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
420 | (last ? AHD_DMA_LAST_SEG : 0));
421 return (sg + 1);
422 }
423}
424
425void
426ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
427{
428 /* XXX Handle target mode SCBs. */
429 scb->crc_retry_count = 0;
430 if ((scb->flags & SCB_PACKETIZED) != 0) {
431 /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
432 scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
433 } else {
434 if (ahd_get_transfer_length(scb) & 0x01)
435 scb->hscb->task_attribute = SCB_XFERLEN_ODD;
436 else
437 scb->hscb->task_attribute = 0;
438 }
439
440 if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
441 || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
442 scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
443 ahd_htole32(scb->sense_busaddr);
444}
445
446void
447ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
448{
449 /*
450 * Copy the first SG into the "current" data ponter area.
451 */
452 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
453 struct ahd_dma64_seg *sg;
454
455 sg = (struct ahd_dma64_seg *)scb->sg_list;
456 scb->hscb->dataptr = sg->addr;
457 scb->hscb->datacnt = sg->len;
458 } else {
459 struct ahd_dma_seg *sg;
460 uint32_t *dataptr_words;
461
462 sg = (struct ahd_dma_seg *)scb->sg_list;
463 dataptr_words = (uint32_t*)&scb->hscb->dataptr;
464 dataptr_words[0] = sg->addr;
465 dataptr_words[1] = 0;
466 if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
467 uint64_t high_addr;
468
469 high_addr = ahd_le32toh(sg->len) & 0x7F000000;
470 scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
471 }
472 scb->hscb->datacnt = sg->len;
473 }
474 /*
475 * Note where to find the SG entries in bus space.
476 * We also set the full residual flag which the
477 * sequencer will clear as soon as a data transfer
478 * occurs.
479 */
480 scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
481}
482
483void
484ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
485{
486 scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
487 scb->hscb->dataptr = 0;
488 scb->hscb->datacnt = 0;
489}
490
491/************************** Memory mapping routines ***************************/
492void *
493ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
494{
495 dma_addr_t sg_offset;
496
497 /* sg_list_phys points to entry 1, not 0 */
498 sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
499 return ((uint8_t *)scb->sg_list + sg_offset);
500}
501
502uint32_t
503ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
504{
505 dma_addr_t sg_offset;
506
507 /* sg_list_phys points to entry 1, not 0 */
508 sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
509 - ahd_sg_size(ahd);
510
511 return (scb->sg_list_busaddr + sg_offset);
512}
513
514void
515ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
516{
517 ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
518 scb->hscb_map->dmamap,
519 /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
520 /*len*/sizeof(*scb->hscb), op);
521}
522
523void
524ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
525{
526 if (scb->sg_count == 0)
527 return;
528
529 ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
530 scb->sg_map->dmamap,
531 /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
532 /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
533}
534
535void
536ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
537{
538 ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
539 scb->sense_map->dmamap,
540 /*offset*/scb->sense_busaddr,
541 /*len*/AHD_SENSE_BUFSIZE, op);
542}
543
544uint32_t
545ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
546{
547 return (((uint8_t *)&ahd->targetcmds[index])
548 - (uint8_t *)ahd->qoutfifo);
549}
550
551/*********************** Miscelaneous Support Functions ***********************/
552/*
553 * Return pointers to the transfer negotiation information
554 * for the specified our_id/remote_id pair.
555 */
556struct ahd_initiator_tinfo *
557ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
558 u_int remote_id, struct ahd_tmode_tstate **tstate)
559{
560 /*
561 * Transfer data structures are stored from the perspective
562 * of the target role. Since the parameters for a connection
563 * in the initiator role to a given target are the same as
564 * when the roles are reversed, we pretend we are the target.
565 */
566 if (channel == 'B')
567 our_id += 8;
568 *tstate = ahd->enabled_targets[our_id];
569 return (&(*tstate)->transinfo[remote_id]);
570}
571
572uint16_t
573ahd_inw(struct ahd_softc *ahd, u_int port)
574{
575 /*
576 * Read high byte first as some registers increment
577 * or have other side effects when the low byte is
578 * read.
579 */
580 uint16_t r = ahd_inb(ahd, port+1) << 8;
581 return r | ahd_inb(ahd, port);
582}
583
584void
585ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
586{
587 /*
588 * Write low byte first to accomodate registers
589 * such as PRGMCNT where the order maters.
590 */
591 ahd_outb(ahd, port, value & 0xFF);
592 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
593}
594
595uint32_t
596ahd_inl(struct ahd_softc *ahd, u_int port)
597{
598 return ((ahd_inb(ahd, port))
599 | (ahd_inb(ahd, port+1) << 8)
600 | (ahd_inb(ahd, port+2) << 16)
601 | (ahd_inb(ahd, port+3) << 24));
602}
603
604void
605ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
606{
607 ahd_outb(ahd, port, (value) & 0xFF);
608 ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
609 ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
610 ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
611}
612
613uint64_t
614ahd_inq(struct ahd_softc *ahd, u_int port)
615{
616 return ((ahd_inb(ahd, port))
617 | (ahd_inb(ahd, port+1) << 8)
618 | (ahd_inb(ahd, port+2) << 16)
619 | (ahd_inb(ahd, port+3) << 24)
620 | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
621 | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
622 | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
623 | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
624}
625
626void
627ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
628{
629 ahd_outb(ahd, port, value & 0xFF);
630 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
631 ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
632 ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
633 ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
634 ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
635 ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
636 ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
637}
638
639u_int
640ahd_get_scbptr(struct ahd_softc *ahd)
641{
642 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
643 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
644 return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
645}
646
647void
648ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
649{
650 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
651 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
652 ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
653 ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
654}
655
656u_int
657ahd_get_hnscb_qoff(struct ahd_softc *ahd)
658{
659 return (ahd_inw_atomic(ahd, HNSCB_QOFF));
660}
270 661
662void
663ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
664{
665 ahd_outw_atomic(ahd, HNSCB_QOFF, value);
666}
667
668u_int
669ahd_get_hescb_qoff(struct ahd_softc *ahd)
670{
671 return (ahd_inb(ahd, HESCB_QOFF));
672}
673
674void
675ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
676{
677 ahd_outb(ahd, HESCB_QOFF, value);
678}
679
680u_int
681ahd_get_snscb_qoff(struct ahd_softc *ahd)
682{
683 u_int oldvalue;
684
685 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
686 oldvalue = ahd_inw(ahd, SNSCB_QOFF);
687 ahd_outw(ahd, SNSCB_QOFF, oldvalue);
688 return (oldvalue);
689}
690
691void
692ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
693{
694 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
695 ahd_outw(ahd, SNSCB_QOFF, value);
696}
697
698u_int
699ahd_get_sescb_qoff(struct ahd_softc *ahd)
700{
701 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
702 return (ahd_inb(ahd, SESCB_QOFF));
703}
704
705void
706ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
707{
708 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
709 ahd_outb(ahd, SESCB_QOFF, value);
710}
711
712u_int
713ahd_get_sdscb_qoff(struct ahd_softc *ahd)
714{
715 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
716 return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
717}
718
719void
720ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
721{
722 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
723 ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
724 ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
725}
726
727u_int
728ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
729{
730 u_int value;
731
732 /*
733 * Workaround PCI-X Rev A. hardware bug.
734 * After a host read of SCB memory, the chip
735 * may become confused into thinking prefetch
736 * was required. This starts the discard timer
737 * running and can cause an unexpected discard
738 * timer interrupt. The work around is to read
739 * a normal register prior to the exhaustion of
740 * the discard timer. The mode pointer register
741 * has no side effects and so serves well for
742 * this purpose.
743 *
744 * Razor #528
745 */
746 value = ahd_inb(ahd, offset);
747 if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
748 ahd_inb(ahd, MODE_PTR);
749 return (value);
750}
751
752u_int
753ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
754{
755 return (ahd_inb_scbram(ahd, offset)
756 | (ahd_inb_scbram(ahd, offset+1) << 8));
757}
758
759uint32_t
760ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
761{
762 return (ahd_inw_scbram(ahd, offset)
763 | (ahd_inw_scbram(ahd, offset+2) << 16));
764}
765
766uint64_t
767ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
768{
769 return (ahd_inl_scbram(ahd, offset)
770 | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
771}
772
773struct scb *
774ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
775{
776 struct scb* scb;
777
778 if (tag >= AHD_SCB_MAX)
779 return (NULL);
780 scb = ahd->scb_data.scbindex[tag];
781 if (scb != NULL)
782 ahd_sync_scb(ahd, scb,
783 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
784 return (scb);
785}
786
787void
788ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
789{
790 struct hardware_scb *q_hscb;
791 struct map_node *q_hscb_map;
792 uint32_t saved_hscb_busaddr;
793
794 /*
795 * Our queuing method is a bit tricky. The card
796 * knows in advance which HSCB (by address) to download,
797 * and we can't disappoint it. To achieve this, the next
798 * HSCB to download is saved off in ahd->next_queued_hscb.
799 * When we are called to queue "an arbitrary scb",
800 * we copy the contents of the incoming HSCB to the one
801 * the sequencer knows about, swap HSCB pointers and
802 * finally assign the SCB to the tag indexed location
803 * in the scb_array. This makes sure that we can still
804 * locate the correct SCB by SCB_TAG.
805 */
806 q_hscb = ahd->next_queued_hscb;
807 q_hscb_map = ahd->next_queued_hscb_map;
808 saved_hscb_busaddr = q_hscb->hscb_busaddr;
809 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
810 q_hscb->hscb_busaddr = saved_hscb_busaddr;
811 q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
812
813 /* Now swap HSCB pointers. */
814 ahd->next_queued_hscb = scb->hscb;
815 ahd->next_queued_hscb_map = scb->hscb_map;
816 scb->hscb = q_hscb;
817 scb->hscb_map = q_hscb_map;
818
819 /* Now define the mapping from tag to SCB in the scbindex */
820 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
821}
822
823/*
824 * Tell the sequencer about a new transaction to execute.
825 */
826void
827ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
828{
829 ahd_swap_with_next_hscb(ahd, scb);
830
831 if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
832 panic("Attempt to queue invalid SCB tag %x\n",
833 SCB_GET_TAG(scb));
834
835 /*
836 * Keep a history of SCBs we've downloaded in the qinfifo.
837 */
838 ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
839 ahd->qinfifonext++;
840
841 if (scb->sg_count != 0)
842 ahd_setup_data_scb(ahd, scb);
843 else
844 ahd_setup_noxfer_scb(ahd, scb);
845 ahd_setup_scb_common(ahd, scb);
846
847 /*
848 * Make sure our data is consistent from the
849 * perspective of the adapter.
850 */
851 ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
852
853#ifdef AHD_DEBUG
854 if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
855 uint64_t host_dataptr;
856
857 host_dataptr = ahd_le64toh(scb->hscb->dataptr);
858 printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
859 ahd_name(ahd),
860 SCB_GET_TAG(scb), scb->hscb->scsiid,
861 ahd_le32toh(scb->hscb->hscb_busaddr),
862 (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
863 (u_int)(host_dataptr & 0xFFFFFFFF),
864 ahd_le32toh(scb->hscb->datacnt));
865 }
866#endif
867 /* Tell the adapter about the newly queued SCB */
868 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
869}
870
871/************************** Interrupt Processing ******************************/
872void
873ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
874{
875 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
876 /*offset*/0,
877 /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
878}
879
880void
881ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
882{
883#ifdef AHD_TARGET_MODE
884 if ((ahd->flags & AHD_TARGETROLE) != 0) {
885 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
886 ahd->shared_data_map.dmamap,
887 ahd_targetcmd_offset(ahd, 0),
888 sizeof(struct target_cmd) * AHD_TMODE_CMDS,
889 op);
890 }
891#endif
892}
893
894/*
895 * See if the firmware has posted any completed commands
896 * into our in-core command complete fifos.
897 */
898#define AHD_RUN_QOUTFIFO 0x1
899#define AHD_RUN_TQINFIFO 0x2
900u_int
901ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
902{
903 u_int retval;
904
905 retval = 0;
906 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
907 /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
908 /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
909 if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
910 == ahd->qoutfifonext_valid_tag)
911 retval |= AHD_RUN_QOUTFIFO;
912#ifdef AHD_TARGET_MODE
913 if ((ahd->flags & AHD_TARGETROLE) != 0
914 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
915 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
916 ahd->shared_data_map.dmamap,
917 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
918 /*len*/sizeof(struct target_cmd),
919 BUS_DMASYNC_POSTREAD);
920 if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
921 retval |= AHD_RUN_TQINFIFO;
922 }
923#endif
924 return (retval);
925}
926
927/*
928 * Catch an interrupt from the adapter
929 */
930int
931ahd_intr(struct ahd_softc *ahd)
932{
933 u_int intstat;
934
935 if ((ahd->pause & INTEN) == 0) {
936 /*
937 * Our interrupt is not enabled on the chip
938 * and may be disabled for re-entrancy reasons,
939 * so just return. This is likely just a shared
940 * interrupt.
941 */
942 return (0);
943 }
944
945 /*
946 * Instead of directly reading the interrupt status register,
947 * infer the cause of the interrupt by checking our in-core
948 * completion queues. This avoids a costly PCI bus read in
949 * most cases.
950 */
951 if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
952 && (ahd_check_cmdcmpltqueues(ahd) != 0))
953 intstat = CMDCMPLT;
954 else
955 intstat = ahd_inb(ahd, INTSTAT);
956
957 if ((intstat & INT_PEND) == 0)
958 return (0);
959
960 if (intstat & CMDCMPLT) {
961 ahd_outb(ahd, CLRINT, CLRCMDINT);
962
963 /*
964 * Ensure that the chip sees that we've cleared
965 * this interrupt before we walk the output fifo.
966 * Otherwise, we may, due to posted bus writes,
967 * clear the interrupt after we finish the scan,
968 * and after the sequencer has added new entries
969 * and asserted the interrupt again.
970 */
971 if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
972 if (ahd_is_paused(ahd)) {
973 /*
974 * Potentially lost SEQINT.
975 * If SEQINTCODE is non-zero,
976 * simulate the SEQINT.
977 */
978 if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
979 intstat |= SEQINT;
980 }
981 } else {
982 ahd_flush_device_writes(ahd);
983 }
984 ahd_run_qoutfifo(ahd);
985 ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
986 ahd->cmdcmplt_total++;
987#ifdef AHD_TARGET_MODE
988 if ((ahd->flags & AHD_TARGETROLE) != 0)
989 ahd_run_tqinfifo(ahd, /*paused*/FALSE);
990#endif
991 }
992
993 /*
994 * Handle statuses that may invalidate our cached
995 * copy of INTSTAT separately.
996 */
997 if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
998 /* Hot eject. Do nothing */
999 } else if (intstat & HWERRINT) {
1000 ahd_handle_hwerrint(ahd);
1001 } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
1002 ahd->bus_intr(ahd);
1003 } else {
1004
1005 if ((intstat & SEQINT) != 0)
1006 ahd_handle_seqint(ahd, intstat);
1007
1008 if ((intstat & SCSIINT) != 0)
1009 ahd_handle_scsiint(ahd, intstat);
1010 }
1011 return (1);
1012}
1013
1014/******************************** Private Inlines *****************************/
271static __inline void 1015static __inline void
272ahd_assert_atn(struct ahd_softc *ahd) 1016ahd_assert_atn(struct ahd_softc *ahd)
273{ 1017{
@@ -280,7 +1024,7 @@ ahd_assert_atn(struct ahd_softc *ahd)
280 * are currently in a packetized transfer. We could 1024 * are currently in a packetized transfer. We could
281 * just as easily be sending or receiving a message. 1025 * just as easily be sending or receiving a message.
282 */ 1026 */
283static __inline int 1027static int
284ahd_currently_packetized(struct ahd_softc *ahd) 1028ahd_currently_packetized(struct ahd_softc *ahd)
285{ 1029{
286 ahd_mode_state saved_modes; 1030 ahd_mode_state saved_modes;
@@ -3941,7 +4685,7 @@ ahd_clear_msg_state(struct ahd_softc *ahd)
3941 */ 4685 */
3942static void 4686static void
3943ahd_handle_message_phase(struct ahd_softc *ahd) 4687ahd_handle_message_phase(struct ahd_softc *ahd)
3944{ 4688{
3945 struct ahd_devinfo devinfo; 4689 struct ahd_devinfo devinfo;
3946 u_int bus_phase; 4690 u_int bus_phase;
3947 int end_session; 4691 int end_session;
@@ -5983,8 +6727,7 @@ found:
5983 */ 6727 */
5984void 6728void
5985ahd_free_scb(struct ahd_softc *ahd, struct scb *scb) 6729ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
5986{ 6730{
5987
5988 /* Clean up for the next user */ 6731 /* Clean up for the next user */
5989 scb->flags = SCB_FLAG_NONE; 6732 scb->flags = SCB_FLAG_NONE;
5990 scb->hscb->control = 0; 6733 scb->hscb->control = 0;
@@ -6272,6 +7015,24 @@ static const char *termstat_strings[] = {
6272 "Not Configured" 7015 "Not Configured"
6273}; 7016};
6274 7017
7018/***************************** Timer Facilities *******************************/
7019#define ahd_timer_init init_timer
7020#define ahd_timer_stop del_timer_sync
7021typedef void ahd_linux_callback_t (u_long);
7022
7023static void
7024ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
7025{
7026 struct ahd_softc *ahd;
7027
7028 ahd = (struct ahd_softc *)arg;
7029 del_timer(timer);
7030 timer->data = (u_long)arg;
7031 timer->expires = jiffies + (usec * HZ)/1000000;
7032 timer->function = (ahd_linux_callback_t*)func;
7033 add_timer(timer);
7034}
7035
6275/* 7036/*
6276 * Start the board, ready for normal operation 7037 * Start the board, ready for normal operation
6277 */ 7038 */