📄 aic7xxx.seq
字号:
* the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR * is set to the proper SCB. */findSCB: mov SCBPTR,SINDEX; /* Initialize SCBPTR */ cmp ARG_1, SCB_LIST_NULL jne findSCB_by_SCBID; mov A, SAVED_TCL; mvi SCB_TCL jmp findSCB_loop; /* &SCB_TCL -> SINDEX */findSCB_by_SCBID: mov A, ARG_1; /* Tag passed in ARG_1 */ mvi SCB_TAG jmp findSCB_loop; /* &SCB_TAG -> SINDEX */findSCB_next: mov ARG_2, SCBPTR; cmp SCB_NEXT, SCB_LIST_NULL je notFound; mov SCBPTR,SCB_NEXT; dec SINDEX; /* Last comparison moved us too far */findSCB_loop: cmp SINDIR, A jne findSCB_next; mov SINDEX, SCBPTR ret;notFound: mvi SINDEX, SCB_LIST_NULL ret;/* * Retrieve an SCB by SCBID first searching the disconnected list falling * back to DMA'ing the SCB down from the host. This routine assumes that * ARG_1 is the SCBID of interrest and that SINDEX is the position in the * disconnected list to start the search from. If SINDEX is SCB_LIST_NULL, * we go directly to the host for the SCB. */retrieveSCB: test SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host; mov SCBPTR call findSCB; /* Continue the search */ cmp SINDEX, SCB_LIST_NULL je retrieve_from_host;/* * This routine expects SINDEX to contain the index of the SCB to be * removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the * SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL * if it is at the head. */rem_scb_from_disc_list:/* Remove this SCB from the disconnection list */ cmp ARG_2, SCB_LIST_NULL je rHead; mov DINDEX, SCB_NEXT; mov SCBPTR, ARG_2; mov SCB_NEXT, DINDEX; mov SCBPTR, SINDEX ret;rHead: mov DISCONNECTED_SCBH,SCB_NEXT ret;retrieve_from_host:/* * We didn't find it. Pull an SCB and DMA down the one we want. * We should never get here in the non-paging case. */ mov ALLZEROS call get_free_or_disc_scb; mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; /* Jump instead of call as we want to return anyway */ mov ARG_1 jmp dma_scb;/* * Determine whether a target is using tagged or non-tagged transactions * by first looking for a matching transaction based on the TCL and if * that fails, looking up this device in the host's untagged SCB array. * The TCL to search for is assumed to be in SAVED_TCL. The value is * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged). * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information * in an SCB instead of having to go to the host. */get_untagged_SCBID: cmp DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host; mvi ARG_1, SCB_LIST_NULL; mov DISCONNECTED_SCBH call findSCB; cmp SINDEX, SCB_LIST_NULL je get_SCBID_from_host; or SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */ test SCB_CONTROL, TAG_ENB jnz . + 2; mov ARG_1, SCB_TAG ret; mvi ARG_1, SCB_LIST_NULL ret;/* * Fetch a byte from host memory given an index of (A + (256 * SINDEX)) * and a base address of SCBID_ADDR. The byte is returned in RETURN_2. */fetch_byte: mov ARG_2, SINDEX; if ((p->features & AHC_CMD_CHAN) != 0) { mvi DINDEX, CCHADDR; mvi SCBID_ADDR call set_1byte_addr; mvi CCHCNT, 1; mvi CCSGCTL, CCSGEN|CCSGRESET; test CCSGCTL, CCSGDONE jz .; mvi CCSGCTL, CCSGRESET; bmov RETURN_2, CCSGRAM, 1 ret; } else { mvi DINDEX, HADDR; mvi SCBID_ADDR call set_1byte_addr; mvi HCNT[0], 1; clr HCNT[1]; clr HCNT[2]; mvi DFCNTRL, HDMAEN|DIRECTION|FIFORESET; call dma_finish; mov RETURN_2, DFDAT ret; }/* * Prepare the hardware to post a byte to host memory given an * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR. */post_byte_setup: mov ARG_2, SINDEX; if ((p->features & AHC_CMD_CHAN) != 0) { mvi DINDEX, CCHADDR; mvi SCBID_ADDR call set_1byte_addr; mvi CCHCNT, 1; mvi CCSCBCTL, CCSCBRESET ret; } else { mvi DINDEX, HADDR; mvi SCBID_ADDR call set_1byte_addr; mvi HCNT[0], 1; clr HCNT[1]; clr HCNT[2]; mvi DFCNTRL, FIFORESET ret; }post_byte: if ((p->features & AHC_CMD_CHAN) != 0) { bmov CCSCBRAM, SINDEX, 1; or CCSCBCTL, CCSCBEN|CCSCBRESET; test CCSCBCTL, CCSCBDONE jz .; clr CCSCBCTL ret; } else { mov DFDAT, SINDEX; or DFCNTRL, HDMAEN|FIFOFLUSH; jmp dma_finish; }get_SCBID_from_host: mov A, SAVED_TCL; mvi UNTAGGEDSCB_OFFSET call fetch_byte; mov RETURN_1, RETURN_2 ret;phase_lock: test SSTAT1, REQINIT jz phase_lock; test SSTAT1, SCSIPERR jnz phase_lock; and SCSISIGO, PHASE_MASK, SCSISIGI; and LASTPHASE, PHASE_MASK, SCSISIGI ret;if ((p->features & AHC_CMD_CHAN) == 0) {set_stcnt_from_hcnt: mov STCNT[0], HCNT[0]; mov STCNT[1], HCNT[1]; mov STCNT[2], HCNT[2] ret;bcopy_7: mov DINDIR, SINDIR; mov DINDIR, SINDIR;bcopy_5: mov DINDIR, SINDIR;bcopy_4: mov DINDIR, SINDIR;bcopy_3: mov DINDIR, SINDIR; mov DINDIR, SINDIR; mov DINDIR, SINDIR ret;}/* * Setup addr assuming that A is an index into * an array of 32byte objects, SINDEX contains * the base address of that array, and DINDEX * contains the base address of the location * to store the indexed address. */set_32byte_addr: shr ARG_2, 3, A; shl A, 5;/* * Setup addr assuming that A + (ARG_1 * 256) is an * index into an array of 1byte objects, SINDEX contains * the base address of that array, and DINDEX contains * the base address of the location to store the computed * address. */set_1byte_addr: add DINDIR, A, SINDIR; mov A, ARG_2; adc DINDIR, A, SINDIR; clr A; adc DINDIR, A, SINDIR; adc DINDIR, A, SINDIR ret;/* * Either post or fetch and SCB from host memory based on the * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX. */dma_scb: mov A, SINDEX; if ((p->features & AHC_CMD_CHAN) != 0) { mvi DINDEX, CCHADDR; mvi HSCB_ADDR call set_32byte_addr; mov CCSCBPTR, SCBPTR; mvi CCHCNT, 32; test DMAPARAMS, DIRECTION jz dma_scb_tohost; mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET; cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .; jmp dma_scb_finish;dma_scb_tohost: if ((p->features & AHC_ULTRA2) == 0) { mvi CCSCBCTL, CCSCBRESET; bmov CCSCBRAM, SCB_CONTROL, 32; or CCSCBCTL, CCSCBEN|CCSCBRESET; test CCSCBCTL, CCSCBDONE jz .; } if ((p->features & AHC_ULTRA2) != 0) { if ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0) { mvi CCSCBCTL, CCARREN|CCSCBRESET; cmp CCSCBCTL, ARRDONE|CCARREN jne .; mvi CCHCNT, 32; mvi CCSCBCTL, CCSCBEN|CCSCBRESET; cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .; } else { mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET; cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .; } }dma_scb_finish: clr CCSCBCTL; test CCSCBCTL, CCARREN|CCSCBEN jnz .; ret; } if ((p->features & AHC_CMD_CHAN) == 0) { mvi DINDEX, HADDR; mvi HSCB_ADDR call set_32byte_addr; mvi HCNT[0], 32; clr HCNT[1]; clr HCNT[2]; mov DFCNTRL, DMAPARAMS; test DMAPARAMS, DIRECTION jnz dma_scb_fromhost; /* Fill it with the SCB data */copy_scb_tofifo: mvi SINDEX, SCB_CONTROL; add A, 32, SINDEX;copy_scb_tofifo_loop: mov DFDAT,SINDIR; mov DFDAT,SINDIR; mov DFDAT,SINDIR; mov DFDAT,SINDIR; mov DFDAT,SINDIR; mov DFDAT,SINDIR; mov DFDAT,SINDIR; mov DFDAT,SINDIR; cmp SINDEX, A jne copy_scb_tofifo_loop; or DFCNTRL, HDMAEN|FIFOFLUSH; jmp dma_finish;dma_scb_fromhost: mvi DINDEX, SCB_CONTROL; if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) { /* * Set the A to -24. It it hits 0, then we let * our code fall through to dfdat_in_8 to complete * the last of the copy. * * Also, things happen 8 bytes at a time in this * case, so we may need to drain the fifo at most * 3 times to keep things flowing */ mvi A, -24;dma_scb_hang_fifo: /* Wait for the first bit of data to hit the fifo */ test DFSTATUS, FIFOEMP jnz .;dma_scb_hang_wait: /* OK, now they've started to transfer into the fifo, * so wait for them to stop trying to transfer any * more data. */ test DFSTATUS, MREQPEND jnz .; /* * OK, they started, then they stopped, now see if they * managed to complete the job before stopping. Try * it multiple times to give the chip a few cycles to * set the flag if it did complete. */ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; test DFSTATUS, HDONE jnz dma_scb_hang_dma_done; /* * Too bad, the chip didn't complete the DMA, but there * aren't any more memory requests pending, so that * means it stopped part way through and hung. That's * our bug, so now we drain what data there is in the * fifo in order to get things going again. */dma_scb_hang_empty_fifo: call dfdat_in_8; add A, 8; add SINDEX, A, HCNT; /* * If there are another 8 bytes of data waiting in the * fifo, then the carry bit will be set as a result * of the above add command (unless A is non-negative, * in which case the carry bit won't be set). */ jc dma_scb_hang_empty_fifo; /* * We've emptied the fifo now, but we wouldn't have got * here if the memory transfer hadn't stopped part way * through, so go back up to the beginning of the * loop and start over. When it succeeds in getting * all the data down, HDONE will be set and we'll * jump to the code just below here. */ jmp dma_scb_hang_fifo;dma_scb_hang_dma_done: and DFCNTRL, ~HDMAEN; test DFCNTRL, HDMAEN jnz .; call dfdat_in_8; add A, 8; cmp A, 8 jne . - 2; ret; } else { call dma_finish; call dfdat_in_8; call dfdat_in_8; call dfdat_in_8; }dfdat_in_8: mov DINDIR,DFDAT;dfdat_in_7: mov DINDIR,DFDAT; mov DINDIR,DFDAT; mov DINDIR,DFDAT; mov DINDIR,DFDAT; mov DINDIR,DFDAT; mov DINDIR,DFDAT; mov DINDIR,DFDAT ret; }/* * Wait for DMA from host memory to data FIFO to complete, then disable * DMA and wait for it to acknowledge that it's off. */if ((p->features & AHC_CMD_CHAN) == 0) {dma_finish: test DFSTATUS,HDONE jz dma_finish; /* Turn off DMA */ and DFCNTRL, ~HDMAEN; test DFCNTRL, HDMAEN jnz .; ret;}add_scb_to_free_list: if ((p->flags & AHC_PAGESCBS) != 0) { mov SCB_NEXT, FREE_SCBH; mov FREE_SCBH, SCBPTR; } mvi SCB_TAG, SCB_LIST_NULL ret;if ((p->flags & AHC_PAGESCBS) != 0) {get_free_or_disc_scb: cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb; cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;return_error: mvi SINDEX, SCB_LIST_NULL ret;dequeue_disc_scb: mov SCBPTR, DISCONNECTED_SCBH;dma_up_scb: mvi DMAPARAMS, FIFORESET; mov SCB_TAG call dma_scb;unlink_disc_scb: mov DISCONNECTED_SCBH, SCB_NEXT ret;dequeue_free_scb: mov SCBPTR, FREE_SCBH; mov FREE_SCBH, SCB_NEXT ret;}add_scb_to_disc_list:/* * Link this SCB into the DISCONNECTED list. This list holds the * candidates for paging out an SCB if one is needed for a new command. * Modifying the disconnected list is a critical(pause dissabled) section. */ mov SCB_NEXT, DISCONNECTED_SCBH; mov DISCONNECTED_SCBH, SCBPTR ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -