aic7xxx.seq (18762) | aic7xxx.seq (19164) |
---|---|
1/*+M*********************************************************************** 2 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD. 3 * 4 *Copyright (c) 1994 John Aycock 5 * The University of Calgary Department of Computer Science. 6 * All rights reserved. 7 * 8 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing, --- 25 unchanged lines hidden (view full) --- 34 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 *SUCH DAMAGE. 39 * 40 *-M************************************************************************/ 41 | 1/*+M*********************************************************************** 2 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD. 3 * 4 *Copyright (c) 1994 John Aycock 5 * The University of Calgary Department of Computer Science. 6 * All rights reserved. 7 * 8 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing, --- 25 unchanged lines hidden (view full) --- 34 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 *SUCH DAMAGE. 39 * 40 *-M************************************************************************/ 41 |
42VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.42 1996/06/09 17:29:11 gibbs Exp $" | 42VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.42.2.2 1996/10/06 01:24:09 gibbs Exp $" |
43 44#if defined(__NetBSD__) 45#include "../../../../dev/ic/aic7xxxreg.h" 46#include "../../../../scsi/scsi_message.h" 47#elif defined(__FreeBSD__) 48#include "../../dev/aic7xxx/aic7xxx_reg.h" 49#include "../../scsi/scsi_message.h" 50#endif 51 52/* 53 * We can't just use ACCUM in the sequencer code because it 54 * must be treated specially by the assembler, and it currently 55 * looks for the symbol 'A'. This is the only register defined in 56 * the assembler's symbol space. 57 */ 58A = ACCUM 59 | 43 44#if defined(__NetBSD__) 45#include "../../../../dev/ic/aic7xxxreg.h" 46#include "../../../../scsi/scsi_message.h" 47#elif defined(__FreeBSD__) 48#include "../../dev/aic7xxx/aic7xxx_reg.h" 49#include "../../scsi/scsi_message.h" 50#endif 51 52/* 53 * We can't just use ACCUM in the sequencer code because it 54 * must be treated specially by the assembler, and it currently 55 * looks for the symbol 'A'. This is the only register defined in 56 * the assembler's symbol space. 57 */ 58A = ACCUM 59 |
60/* After starting the selection hardware, we check for reconnecting targets | 60/* 61 * A few words on the waiting SCB list: 62 * After starting the selection hardware, we check for reconnecting targets |
61 * as well as for our selection to complete just in case the reselection wins 62 * bus arbitration. The problem with this is that we must keep track of the 63 * SCB that we've already pulled from the QINFIFO and started the selection 64 * on just in case the reselection wins so that we can retry the selection at 65 * a later time. This problem cannot be resolved by holding a single entry 66 * in scratch ram since a reconnecting target can request sense and this will 67 * create yet another SCB waiting for selection. The solution used here is to 68 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list | 63 * as well as for our selection to complete just in case the reselection wins 64 * bus arbitration. The problem with this is that we must keep track of the 65 * SCB that we've already pulled from the QINFIFO and started the selection 66 * on just in case the reselection wins so that we can retry the selection at 67 * a later time. This problem cannot be resolved by holding a single entry 68 * in scratch ram since a reconnecting target can request sense and this will 69 * create yet another SCB waiting for selection. The solution used here is to 70 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list |
69 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB offsets, 70 * SCB_LIST_NULL is 0xff which is out of range. The kernel driver must 71 * add an entry to this list everytime a request sense occurs. The sequencer 72 * will automatically consume the entries. | 71 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, 72 * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to 73 * this list everytime a request sense occurs or after completing a non-tagged 74 * command for which a second SCB has been queued. The sequencer will 75 * automatically consume the entries. |
73 */ 74 75/* 76 * We assume that the kernel driver may reset us at any time, even in the 77 * middle of a DMA, so clear DFCNTRL too. 78 */ 79reset: 80 clr DFCNTRL 81 clr SCSISIGO /* De-assert BSY */ 82/* 83 * We jump to start after every bus free. 84 */ 85start: | 76 */ 77 78/* 79 * We assume that the kernel driver may reset us at any time, even in the 80 * middle of a DMA, so clear DFCNTRL too. 81 */ 82reset: 83 clr DFCNTRL 84 clr SCSISIGO /* De-assert BSY */ 85/* 86 * We jump to start after every bus free. 87 */ 88start: |
86 and FLAGS,0x0f /* clear target specific flags */ | 89 and FLAGS,0x07 /* clear target specific flags */ |
87 mvi SCSISEQ,ENRSELI /* Always allow reselection */ 88 clr SCSIRATE /* 89 * We don't know the target we will 90 * connect to, so default to narrow 91 * transfers to avoid parity problems. 92 */ 93poll_for_work: 94 /* 95 * Are we a twin channel device? 96 * For fairness, we check the other bus first, 97 * since we just finished a transaction on the 98 * current channel. 99 */ 100 test FLAGS,TWIN_BUS jz start2 101 xor SBLKCTL,SELBUSB /* Toggle to the other bus */ 102 test SSTAT0,SELDI jnz reselect 103 xor SBLKCTL,SELBUSB /* Toggle to the original bus */ 104start2: 105 test SSTAT0,SELDI jnz reselect | 90 mvi SCSISEQ,ENRSELI /* Always allow reselection */ 91 clr SCSIRATE /* 92 * We don't know the target we will 93 * connect to, so default to narrow 94 * transfers to avoid parity problems. 95 */ 96poll_for_work: 97 /* 98 * Are we a twin channel device? 99 * For fairness, we check the other bus first, 100 * since we just finished a transaction on the 101 * current channel. 102 */ 103 test FLAGS,TWIN_BUS jz start2 104 xor SBLKCTL,SELBUSB /* Toggle to the other bus */ 105 test SSTAT0,SELDI jnz reselect 106 xor SBLKCTL,SELBUSB /* Toggle to the original bus */ 107start2: 108 test SSTAT0,SELDI jnz reselect |
106 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting | 109 cmp WAITING_SCBH,SCB_LIST_NULL je test_queue 110start_waiting: 111 /* 112 * Pull the first entry off of the waiting SCB list 113 * We don't have to "test_busy" because only transactions that 114 * have passed that test can be in the WAITING_SCB list. 115 */ 116 mov SCBPTR,WAITING_SCBH 117 jmp start_scb2 118test_queue: 119 /* Has the driver posted any work for us? */ |
107 mov A, QCNTMASK 108 test QINCNT,A jz poll_for_work 109 110/* 111 * We have at least one queued SCB now and we don't have any | 120 mov A, QCNTMASK 121 test QINCNT,A jz poll_for_work 122 123/* 124 * We have at least one queued SCB now and we don't have any |
112 * SCBs in the list of SCBs awaiting selection. Set the SCB 113 * pointer from the FIFO so we see the right bank of SCB 114 * registers. | 125 * SCBs in the list of SCBs awaiting selection. If we have 126 * any SCBs availible for use, pull the tag from the QINFIFO 127 * and get to work on it. |
115 */ | 128 */ |
116 mov SCBPTR,QINFIFO | 129 test FLAGS, PAGESCBS jz dequeue_scb 130 call get_free_or_disc_scb 131 cmp SINDEX, SCB_LIST_NULL je poll_for_work 132dequeue_scb: 133 mov CUR_SCBID,QINFIFO 134 test FLAGS, PAGESCBS jnz dma_queued_scb 135 /* In the non-paging case, the SCBID == hardware SCB index */ 136 mov SCBPTR, CUR_SCBID 137dma_queued_scb: 138/* 139 * DMA the SCB from host ram into the current SCB location. 140 */ 141 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */ 142 mov CUR_SCBID call dma_scb |
117 118/* 119 * See if there is not already an active SCB for this target. This code 120 * locks out on a per target basis instead of target/lun. Although this 121 * is not ideal for devices that have multiple luns active at the same 122 * time, it is faster than looping through all SCB's looking for active | 143 144/* 145 * See if there is not already an active SCB for this target. This code 146 * locks out on a per target basis instead of target/lun. Although this 147 * is not ideal for devices that have multiple luns active at the same 148 * time, it is faster than looping through all SCB's looking for active |
123 * commands. It may be benificial to make findscb a more general procedure 124 * to see if the added cost of the search is negligible. This code also 125 * assumes that the kernel driver will clear the active flags on board 126 * initialization, board reset, and a target SELTO. Tagged commands 127 * don't set the active bits since you can queue more than one command 128 * at a time. We do, however, look to see if there are any non-tagged 129 * I/Os in progress, and requeue the command if there are. Tagged and 130 * non-tagged commands cannot be mixed to a single target. | 149 * commands. We also don't have enough spare SCB space for to store the 150 * SCBID of the currently busy transaction for each target/lun making it 151 * impossible to link up the SCBs. |
131 */ | 152 */ |
132 | |
133test_busy: | 153test_busy: |
134 mov FUNCTION1,SCB_TCL 135 mov A,FUNCTION1 136 test SCB_TCL,0x88 jz test_a /* Id < 8 && A channel */ 137 138 test ACTIVE_B,A jnz requeue 139 test SCB_CONTROL,TAG_ENB jnz start_scb 140 /* Mark the current target as busy */ 141 or ACTIVE_B,A 142 jmp start_scb 143 144/* Place the currently active SCB back on the queue for later processing */ 145requeue: 146 mov QINFIFO, SCBPTR | 154 test SCB_CONTROL, TAG_ENB jnz start_scb 155 mov SAVED_SCBPTR, SCBPTR 156 call index_untagged_scb 157 mov ARG_1, SINDIR /* 158 * ARG_1 should 159 * now have the SCB ID of 160 * any active, non-tagged, 161 * command for this target. 162 */ 163 cmp ARG_1, SCB_LIST_NULL je make_busy 164 test FLAGS, PAGESCBS jz simple_busy_link 165 /* 166 * Put this SCB back onto the free list. It 167 * may be necessary to satisfy the search for 168 * the active SCB. 169 */ 170 call add_scb_to_free_list 171 /* Find the active SCB */ 172 mov ALLZEROS call findSCB 173 /* Link us in */ 174 mov SCB_LINKED_NEXT, CUR_SCBID 175 /* Put it back on the disconnected list */ 176 call add_scb_to_disc_list |
147 jmp poll_for_work | 177 jmp poll_for_work |
178simple_busy_link: 179 mov SCBPTR, ARG_1 180 mov SCB_LINKED_NEXT, CUR_SCBID 181 jmp poll_for_work 182make_busy: 183 mov DINDIR, CUR_SCBID 184 mov SCBPTR, SAVED_SCBPTR |
|
148 | 185 |
149/* 150 * Pull the first entry off of the waiting for selection list 151 * We don't have to "test_busy" because only transactions that 152 * have passed that test can be in the waiting_scb list. 153 */ 154start_waiting: 155 mov SCBPTR,WAITING_SCBH 156 jmp start_scb2 157 158test_a: 159 test ACTIVE_A,A jnz requeue 160 test SCB_CONTROL,TAG_ENB jnz start_scb 161 /* Mark the current target as busy */ 162 or ACTIVE_A,A 163 | |
164start_scb: | 186start_scb: |
187 /* 188 * Place us on the waiting list in case our selection 189 * doesn't win during bus arbitration. 190 */ |
|
165 mov SCB_NEXT,WAITING_SCBH 166 mov WAITING_SCBH, SCBPTR 167start_scb2: 168 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */ 169 and A,0x08,SCB_TCL /* Get new channel bit */ 170 or SINDEX,A 171 mov SBLKCTL,SINDEX /* select channel */ 172 mov SCB_TCL call initialize_scsiid --- 12 unchanged lines hidden (view full) --- 185 * into the message out phase since we have ATN asserted. Prepare 186 * the message to send. 187 * 188 * Messages are stored in scratch RAM starting with a length byte 189 * followed by the message itself. 190 */ 191 192mk_identify: | 191 mov SCB_NEXT,WAITING_SCBH 192 mov WAITING_SCBH, SCBPTR 193start_scb2: 194 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */ 195 and A,0x08,SCB_TCL /* Get new channel bit */ 196 or SINDEX,A 197 mov SBLKCTL,SINDEX /* select channel */ 198 mov SCB_TCL call initialize_scsiid --- 12 unchanged lines hidden (view full) --- 211 * into the message out phase since we have ATN asserted. Prepare 212 * the message to send. 213 * 214 * Messages are stored in scratch RAM starting with a length byte 215 * followed by the message itself. 216 */ 217 218mk_identify: |
193 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */ 194 | |
195 and MSG0,0x7,SCB_TCL /* lun */ | 219 and MSG0,0x7,SCB_TCL /* lun */ |
220 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */ |
|
196 or MSG0,A /* or in disconnect privledge */ 197 or MSG0,MSG_IDENTIFYFLAG 198 mvi MSG_LEN, 1 199 200/* 201 * Send a tag message if TAG_ENB is set in the SCB control block. 202 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. 203 */ 204mk_tag: 205 test SCB_CONTROL,TAG_ENB jz mk_message | 221 or MSG0,A /* or in disconnect privledge */ 222 or MSG0,MSG_IDENTIFYFLAG 223 mvi MSG_LEN, 1 224 225/* 226 * Send a tag message if TAG_ENB is set in the SCB control block. 227 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. 228 */ 229mk_tag: 230 test SCB_CONTROL,TAG_ENB jz mk_message |
206 mvi DINDEX, MSG1 207 and DINDIR,0x23,SCB_CONTROL 208 mov DINDIR,SCB_TAG | 231 and MSG1,0x23,SCB_CONTROL 232 mov MSG2,SCB_TAG 233 add MSG_LEN,2 /* update message length */ |
209 | 234 |
210 add MSG_LEN,COMP_MSG0,DINDEX /* update message length */ 211 | |
212/* 213 * Interrupt the driver, and allow it to tweak the message buffer 214 * if it asks. 215 */ 216mk_message: 217 test SCB_CONTROL,MK_MESSAGE jz wait_for_selection 218 219 mvi INTSTAT,AWAITING_MSG 220 221wait_for_selection: 222 test SSTAT0,SELDO jnz select 223 test SSTAT0,SELDI jz wait_for_selection 224 225/* 226 * Reselection has been initiated by a target. Make a note that we've been | 235/* 236 * Interrupt the driver, and allow it to tweak the message buffer 237 * if it asks. 238 */ 239mk_message: 240 test SCB_CONTROL,MK_MESSAGE jz wait_for_selection 241 242 mvi INTSTAT,AWAITING_MSG 243 244wait_for_selection: 245 test SSTAT0,SELDO jnz select 246 test SSTAT0,SELDI jz wait_for_selection 247 248/* 249 * Reselection has been initiated by a target. Make a note that we've been |
227 * reselected, but haven't seen an IDENTIFY message from the target 228 * yet. | 250 * reselected, but haven't seen an IDENTIFY message from the target yet. |
229 */ 230reselect: 231 clr MSG_LEN /* Don't have anything in the mesg buffer */ 232 mov SELID call initialize_scsiid 233 or FLAGS,RESELECTED 234 jmp select2 235 236/* | 251 */ 252reselect: 253 clr MSG_LEN /* Don't have anything in the mesg buffer */ 254 mov SELID call initialize_scsiid 255 or FLAGS,RESELECTED 256 jmp select2 257 258/* |
237 * After the selection, remove this SCB from the "waiting for selection" | 259 * After the selection, remove this SCB from the "waiting SCB" |
238 * list. This is achieved by simply moving our "next" pointer into 239 * WAITING_SCBH. Our next pointer will be set to null the next time this 240 * SCB is used, so don't bother with it now. 241 */ 242select: 243 mov WAITING_SCBH,SCB_NEXT | 260 * list. This is achieved by simply moving our "next" pointer into 261 * WAITING_SCBH. Our next pointer will be set to null the next time this 262 * SCB is used, so don't bother with it now. 263 */ 264select: 265 mov WAITING_SCBH,SCB_NEXT |
244 or FLAGS,SELECTED | |
245select2: 246/* | 266select2: 267/* |
247 * Set CLRCHN here before the target has entered a data transfer mode - 248 * with synchronous SCSI, if you do it later, you blow away some 249 * data in the SCSI FIFO that the target has already sent to you. 250 */ 251 or SXFRCTL0,CLRCHN 252/* | |
253 * Initialize SCSIRATE with the appropriate value for this target. | 268 * Initialize SCSIRATE with the appropriate value for this target. |
269 * The SCSIRATE settings for each target are stored in an array 270 * based at TARG_SCRATCH. |
|
254 */ | 271 */ |
255 call ndx_dtr | 272ndx_dtr: 273 shr A,SCSIID,4 274 test SBLKCTL,SELBUSB jz ndx_dtr_2 275 or SAVED_TCL, SELBUSB /* Add the channel bit while we're here */ 276 or A,0x08 /* Channel B entries add 8 */ 277ndx_dtr_2: 278 add SINDEX,TARG_SCRATCH,A |
256 mov SCSIRATE,SINDIR 257 258/* | 279 mov SCSIRATE,SINDIR 280 281/* |
259 * Initialize Ultra mode setting. | 282 * Initialize Ultra mode setting and clear the SCSI channel. |
260 */ | 283 */ |
261 mov FUNCTION1,SCSIID 262 mov A,FUNCTION1 263 and SINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */ 264 test SCSIID, 0x80 jnz ultra_b /* Target ID > 7 */ 265 test SBLKCTL, SELBUSB jnz ultra_b /* Second channel device */ 266 test ULTRA_ENB,A jz set_sxfrctl0 267 or SINDEX, ULTRAEN jmp set_sxfrctl0 268ultra_b: 269 test ULTRA_ENB_B,A jz set_sxfrctl0 270 or SINDEX, ULTRAEN 271 | 284ultra: 285 and DINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */ 286 /* 287 * Set CLRCHN here before the target has entered a data transfer mode - 288 * with synchronous SCSI, if you do it later, you blow away some 289 * data in the SCSI FIFO that the target has already sent to you. 290 */ 291 or DINDEX, CLRCHN 292 mvi SINDEX, ULTRA_ENB_B 293 test SCSIID, 0x80 jnz ultra_2 /* Target ID > 7 */ 294 test SBLKCTL, SELBUSB jnz ultra_2 /* Second channel device */ 295 dec SINDEX 296ultra_2: 297 mov FUNCTION1,SCSIID 298 mov A,FUNCTION1 299 test SINDIR, A jz set_sxfrctl0 300 or DINDEX, ULTRAEN 301 |
272set_sxfrctl0: | 302set_sxfrctl0: |
273 mov SXFRCTL0,SINDEX | 303 mov SXFRCTL0,DINDEX |
274 275 mvi SCSISEQ,ENAUTOATNP /* 276 * ATN on parity errors 277 * for "in" phases 278 */ 279 mvi CLRSINT1,CLRBUSFREE 280 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */ 281/* --- 39 unchanged lines hidden (view full) --- 321 jmp data_phase_loop 322 323p_datain: 324 mvi DMAPARAMS,0x79 /* 325 * WIDEODD|SCSIEN|SDMAEN|HDMAEN| 326 * !DIRECTION|FIFORESET 327 */ 328data_phase_init: | 304 305 mvi SCSISEQ,ENAUTOATNP /* 306 * ATN on parity errors 307 * for "in" phases 308 */ 309 mvi CLRSINT1,CLRBUSFREE 310 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */ 311/* --- 39 unchanged lines hidden (view full) --- 351 jmp data_phase_loop 352 353p_datain: 354 mvi DMAPARAMS,0x79 /* 355 * WIDEODD|SCSIEN|SDMAEN|HDMAEN| 356 * !DIRECTION|FIFORESET 357 */ 358data_phase_init: |
329 call assert | 359 call assert /* 360 * Ensure entering a data 361 * phase is okay - seen identify, etc. 362 */ |
330 331 test FLAGS, DPHASE jnz data_phase_reinit | 363 364 test FLAGS, DPHASE jnz data_phase_reinit |
332 call sg_scb2ram 333 or FLAGS, DPHASE /* We have seen a data phase */ | |
334 | 365 |
366 /* 367 * Initialize the DMA address and counter from the SCB. 368 * Also set SG_COUNT and SG_NEXT in memory since we cannot 369 * modify the values in the SCB itself until we see a 370 * save data pointers message. 371 */ 372 mvi DINDEX, HADDR0 373 mvi SCB_DATAPTR call bcopy_7 374 375 call set_stcnt_from_hcnt 376 377 mov SG_COUNT,SCB_SGCOUNT 378 379 mvi DINDEX, SG_NEXT 380 mvi SCB_SGPTR call bcopy_4 381 382 /* We have seen a data phase */ 383 or FLAGS, DPHASE 384 |
|
335data_phase_loop: 336/* Guard against overruns */ 337 test SG_COUNT, 0xff jnz data_phase_inbounds 338/* 339 * Turn on 'Bit Bucket' mode, set the transfer count to 340 * 16meg and let the target run until it changes phase. 341 * When the transfer completes, notify the host that we 342 * had an overrun. 343 */ 344 or SXFRCTL1,BITBUCKET 345 mvi STCNT0,0xff 346 mvi STCNT1,0xff 347 mvi STCNT2,0xff 348 349data_phase_inbounds: | 385data_phase_loop: 386/* Guard against overruns */ 387 test SG_COUNT, 0xff jnz data_phase_inbounds 388/* 389 * Turn on 'Bit Bucket' mode, set the transfer count to 390 * 16meg and let the target run until it changes phase. 391 * When the transfer completes, notify the host that we 392 * had an overrun. 393 */ 394 or SXFRCTL1,BITBUCKET 395 mvi STCNT0,0xff 396 mvi STCNT1,0xff 397 mvi STCNT2,0xff 398 399data_phase_inbounds: |
350/* If we are the last SG block, don't set wideodd. */ | 400/* If we are the last SG block, ensure wideodd is off. */ |
351 cmp SG_COUNT,0x01 jne data_phase_wideodd 352 and DMAPARAMS, 0xbf /* Turn off WIDEODD */ 353data_phase_wideodd: 354 mov DMAPARAMS call dma 355 356/* Go tell the host about any overruns */ 357 test SXFRCTL1,BITBUCKET jnz data_phase_overrun 358 --- 19 unchanged lines hidden (view full) --- 378 * 379 * This, like all DMA's, assumes little-endian host data storage. 380 */ 381sg_load: 382 clr HCNT2 383 clr HCNT1 384 mvi HCNT0,SG_SIZEOF 385 | 401 cmp SG_COUNT,0x01 jne data_phase_wideodd 402 and DMAPARAMS, 0xbf /* Turn off WIDEODD */ 403data_phase_wideodd: 404 mov DMAPARAMS call dma 405 406/* Go tell the host about any overruns */ 407 test SXFRCTL1,BITBUCKET jnz data_phase_overrun 408 --- 19 unchanged lines hidden (view full) --- 428 * 429 * This, like all DMA's, assumes little-endian host data storage. 430 */ 431sg_load: 432 clr HCNT2 433 clr HCNT1 434 mvi HCNT0,SG_SIZEOF 435 |
386 mov HADDR0,SG_NEXT0 387 mov HADDR1,SG_NEXT1 388 mov HADDR2,SG_NEXT2 389 mov HADDR3,SG_NEXT3 | 436 mvi DINDEX, HADDR0 437 mvi SG_NEXT0 call bcopy_4 |
390 391 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */ 392 | 438 439 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */ 440 |
393/* 394 * Wait for DMA from host memory to data FIFO to complete, then disable 395 * DMA and wait for it to acknowledge that it's off. 396 */ 397dma_finish: 398 test DFSTATUS,HDONE jz dma_finish 399 /* Turn off DMA preserving WIDEODD */ 400 and DFCNTRL,WIDEODD 401dma_finish2: 402 test DFCNTRL,HDMAENACK jnz dma_finish2 | 441 call dma_finish |
403 404/* 405 * Copy data from FIFO into SCB data pointer and data count. This assumes | 442 443/* 444 * Copy data from FIFO into SCB data pointer and data count. This assumes |
406 * that the struct scatterlist has this structure (this and sizeof(struct 407 * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver): | 445 * that the SG segments are of the form: |
408 * | 446 * |
409 * struct scatterlist { 410 * char *address; four bytes, little-endian order 411 * ... four bytes, ignored 412 * unsigned short length; two bytes, little-endian order 413 * } 414 * 415 * 416 * In FreeBSD, the scatter list entry is only 8 bytes. 417 * | |
418 * struct ahc_dma_seg { | 447 * struct ahc_dma_seg { |
419 * physaddr addr; four bytes, little-endian order 420 * long len; four bytes, little endian order | 448 * u_int32_t addr; four bytes, little-endian order 449 * u_int32_t len; four bytes, little endian order |
421 * }; 422 */ | 450 * }; 451 */ |
452 mvi HADDR0 call dfdat_in_7 |
|
423 | 453 |
424 mov HADDR0,DFDAT 425 mov HADDR1,DFDAT 426 mov HADDR2,DFDAT 427 mov HADDR3,DFDAT 428/* 429 * For Linux, we must throw away four bytes since there is a 32bit gap 430 * in the middle of a struct scatterlist. 431 */ 432#ifdef __linux__ 433 mov NONE,DFDAT 434 mov NONE,DFDAT 435 mov NONE,DFDAT 436 mov NONE,DFDAT 437#endif 438 mov HCNT0,DFDAT 439 mov HCNT1,DFDAT 440 mov HCNT2,DFDAT 441 | |
442/* Load STCNT as well. It is a mirror of HCNT */ | 454/* Load STCNT as well. It is a mirror of HCNT */ |
443 mov STCNT0,HCNT0 444 mov STCNT1,HCNT1 445 mov STCNT2,HCNT2 446 test SSTAT1,PHASEMIS jz data_phase_loop | 455 call set_stcnt_from_hcnt 456 test SSTAT1,PHASEMIS jz data_phase_loop |
447 448data_phase_finish: 449/* 450 * After a DMA finishes, save the SG and STCNT residuals back into the SCB 451 * We use STCNT instead of HCNT, since it's a reflection of how many bytes 452 * were transferred on the SCSI (as opposed to the host) bus. 453 */ 454 mov SCB_RESID_DCNT0,STCNT0 --- 14 unchanged lines hidden (view full) --- 469 * Command phase. Set up the DMA registers and let 'er rip. 470 */ 471p_command: 472 call assert 473 474/* 475 * Load HADDR and HCNT. 476 */ | 457 458data_phase_finish: 459/* 460 * After a DMA finishes, save the SG and STCNT residuals back into the SCB 461 * We use STCNT instead of HCNT, since it's a reflection of how many bytes 462 * were transferred on the SCSI (as opposed to the host) bus. 463 */ 464 mov SCB_RESID_DCNT0,STCNT0 --- 14 unchanged lines hidden (view full) --- 479 * Command phase. Set up the DMA registers and let 'er rip. 480 */ 481p_command: 482 call assert 483 484/* 485 * Load HADDR and HCNT. 486 */ |
477 mov HADDR0, SCB_CMDPTR0 478 mov HADDR1, SCB_CMDPTR1 479 mov HADDR2, SCB_CMDPTR2 480 mov HADDR3, SCB_CMDPTR3 481 mov HCNT0, SCB_CMDLEN | 487 mvi DINDEX, HADDR0 488 mvi SCB_CMDPTR call bcopy_5 |
482 clr HCNT1 483 clr HCNT2 484 | 489 clr HCNT1 490 clr HCNT2 491 |
485 mov STCNT0, HCNT0 486 mov STCNT1, HCNT1 487 mov STCNT2, HCNT2 | 492 call set_stcnt_from_hcnt |
488 489 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN| 490 # DIRECTION|FIFORESET 491 jmp ITloop 492 493/* 494 * Status phase. Wait for the data byte to appear, then read it 495 * and store it into the SCB. --- 4 unchanged lines hidden (view full) --- 500 501/* 502 * Message out phase. If there is not an active message, but the target 503 * took us into this phase anyway, build a no-op message and send it. 504 */ 505p_mesgout: 506 test MSG_LEN, 0xff jnz p_mesgout_start 507 mvi MSG_NOOP call mk_mesg /* build NOP message */ | 493 494 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN| 495 # DIRECTION|FIFORESET 496 jmp ITloop 497 498/* 499 * Status phase. Wait for the data byte to appear, then read it 500 * and store it into the SCB. --- 4 unchanged lines hidden (view full) --- 505 506/* 507 * Message out phase. If there is not an active message, but the target 508 * took us into this phase anyway, build a no-op message and send it. 509 */ 510p_mesgout: 511 test MSG_LEN, 0xff jnz p_mesgout_start 512 mvi MSG_NOOP call mk_mesg /* build NOP message */ |
508 | |
509p_mesgout_start: 510/* 511 * Set up automatic PIO transfer from MSG0. Bit 3 in 512 * SXFRCTL0 (SPIOEN) is already on. 513 */ 514 mvi SINDEX,MSG0 515 mov DINDEX,MSG_LEN 516 --- 50 unchanged lines hidden (view full) --- 567 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs 568 cmp ALLZEROS,A je mesgin_complete 569 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs 570 cmp A,MSG_EXTENDED je mesgin_extended 571 cmp A,MSG_MESSAGE_REJECT je mesgin_reject 572 573rej_mesgin: 574/* | 513p_mesgout_start: 514/* 515 * Set up automatic PIO transfer from MSG0. Bit 3 in 516 * SXFRCTL0 (SPIOEN) is already on. 517 */ 518 mvi SINDEX,MSG0 519 mov DINDEX,MSG_LEN 520 --- 50 unchanged lines hidden (view full) --- 571 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs 572 cmp ALLZEROS,A je mesgin_complete 573 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs 574 cmp A,MSG_EXTENDED je mesgin_extended 575 cmp A,MSG_MESSAGE_REJECT je mesgin_reject 576 577rej_mesgin: 578/* |
575 * We have no idea what this message in is, and there's no way 576 * to pass it up to the kernel, so we issue a message reject and 577 * hope for the best. Since we're now using manual PIO mode to 578 * read in the message, there should no longer be a race condition 579 * present when we assert ATN. In any case, rejection should be a 580 * rare occurrence - signal the driver when it happens. | 579 * We have no idea what this message in is, so we issue a message reject 580 * and hope for the best. In any case, rejection should be a rare 581 * occurrence - signal the driver when it happens. |
581 */ 582 or SCSISIGO,ATNO /* turn on ATNO */ 583 mvi INTSTAT,SEND_REJECT /* let driver know */ 584 585 mvi MSG_MESSAGE_REJECT call mk_mesg 586 587mesgin_done: 588 call inb_last /*ack & turn auto PIO back on*/ 589 jmp ITloop 590 591 592mesgin_complete: 593/* | 582 */ 583 or SCSISIGO,ATNO /* turn on ATNO */ 584 mvi INTSTAT,SEND_REJECT /* let driver know */ 585 586 mvi MSG_MESSAGE_REJECT call mk_mesg 587 588mesgin_done: 589 call inb_last /*ack & turn auto PIO back on*/ 590 jmp ITloop 591 592 593mesgin_complete: 594/* |
594 * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT, 595 * and trigger a completion interrupt. Check status for non zero return 596 * and interrupt driver if needed. This allows the driver to interpret 597 * errors only when they occur instead of always uploading the scb. If 598 * the status is SCSI_CHECK, the driver will download a new scb requesting 599 * sense to replace the old one, modify the "waiting for selection" SCB list 600 * and set RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE the 601 * sequencer imediately jumps to main loop where it will run down the waiting 602 * SCB list and process the sense request. If the kernel driver does not 603 * wish to request sense, it need only clear RETURN_1, and the command is 604 * allowed to complete. We don't bother to post to the QOUTFIFO in the 605 * error case since it would require extra work in the kernel driver to 606 * ensure that the entry was removed before the command complete code tried 607 * processing it. 608 * 609 * First check for residuals | 595 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO, 596 * and trigger a completion interrupt. Before doing so, check to see if there 597 * is a residual or the status byte is something other than NO_ERROR (0). In 598 * either of these conditions, we upload the SCB back to the host so it can 599 * process this information. In the case of a non zero status byte, we 600 * additionally interrupt the kernel driver synchronously, allowing it to 601 * decide if sense should be retrieved. If the kernel driver wishes to request 602 * sense, it will fill the kernel SCB with a request sense command and set 603 * RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload 604 * the SCB, and process it as the next command by adding it to the waiting list. 605 * If the kernel driver does not wish to request sense, it need only clear 606 * RETURN_1, and the command is allowed to complete normally. We don't bother 607 * to post to the QOUTFIFO in the error cases since it would require extra 608 * work in the kernel driver to ensure that the entry was removed before the 609 * command complete code tried processing it. |
610 */ | 610 */ |
611 test SCB_RESID_SGCNT,0xff jz check_status | 611 |
612/* | 612/* |
613 * If we have a residual count, interrupt and tell the host. Other 614 * alternatives are to pause the sequencer on all command completes (yuck), 615 * dma the resid directly to the host (slick, we may have space to do it now) 616 * or have the sequencer pause itself when it encounters a non-zero resid 617 * (unecessary pause just to flag the command -yuck-, but takes one instruction 618 * and since it shouldn't happen that often is good enough for our purposes). | 613 * First check for residuals |
619 */ | 614 */ |
620resid: 621 mvi INTSTAT,RESIDUAL 622 623check_status: | 615 test SCB_RESID_SGCNT,0xff jnz upload_scb |
624 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */ | 616 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */ |
617upload_scb: 618 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/ 619 mov SCB_TAG call dma_scb 620check_status: 621 test SCB_TARGET_STATUS,0xff jz status_ok /* Just a residual? */ |
|
625 mvi INTSTAT,BAD_STATUS /* let driver know */ 626 cmp RETURN_1, SEND_SENSE jne status_ok | 622 mvi INTSTAT,BAD_STATUS /* let driver know */ 623 cmp RETURN_1, SEND_SENSE jne status_ok |
627 jmp mesgin_done | 624 /* This SCB becomes the next to execute as it will retrieve sense */ 625 mov SCB_LINKED_NEXT, SCB_TAG 626 jmp dma_next_scb |
628 629status_ok: 630/* First, mark this target as free. */ 631 test SCB_CONTROL,TAG_ENB jnz test_immediate /* 632 * Tagged commands 633 * don't busy the 634 * target. 635 */ | 627 628status_ok: 629/* First, mark this target as free. */ 630 test SCB_CONTROL,TAG_ENB jnz test_immediate /* 631 * Tagged commands 632 * don't busy the 633 * target. 634 */ |
636 mov FUNCTION1,SCB_TCL 637 mov A,FUNCTION1 638 test SCB_TCL,0x88 jz clear_a 639 xor ACTIVE_B,A 640 jmp test_immediate | 635 mov SAVED_SCBPTR, SCBPTR 636 mov SAVED_LINKPTR, SCB_LINKED_NEXT 637 call index_untagged_scb 638 mov DINDIR, SAVED_LINKPTR 639 mov SCBPTR, SAVED_SCBPTR |
641 | 640 |
642clear_a: 643 xor ACTIVE_A,A 644 | |
645test_immediate: 646 test SCB_CMDLEN,0xff jnz complete /* Immediate message complete */ 647/* 648 * Pause the sequencer until the driver gets around to handling the command 649 * complete. This is so that any action that might require carefull timing 650 * with the completion of this command can occur. 651 */ 652 mvi INTSTAT,IMMEDDONE | 641test_immediate: 642 test SCB_CMDLEN,0xff jnz complete /* Immediate message complete */ 643/* 644 * Pause the sequencer until the driver gets around to handling the command 645 * complete. This is so that any action that might require carefull timing 646 * with the completion of this command can occur. 647 */ 648 mvi INTSTAT,IMMEDDONE |
653 jmp start | 649 jmp dma_next_scb |
654complete: | 650complete: |
651 test FLAGS, PAGESCBS jz complete_post 652 /* Wait for a free slot - we may need to wait only in the paging case */ 653 mov A, QOUTCNT 654 cmp QFULLCNT, A je complete 655complete_post: 656 /* Post the SCB and issue an interrupt */ |
|
655 mov QOUTFIFO,SCB_TAG 656 mvi INTSTAT,CMDCMPLT | 657 mov QOUTFIFO,SCB_TAG 658 mvi INTSTAT,CMDCMPLT |
659 660dma_next_scb: 661 cmp SCB_LINKED_NEXT, SCB_LIST_NULL je mesgin_done 662 test FLAGS, PAGESCBS jnz dma_next_scb2 663 /* Only DMA on top of ourselves if we are the SCB to download */ 664 mov A, SCB_LINKED_NEXT 665 cmp SCB_TAG, A je dma_next_scb2 666 mov SCBPTR, A 667 jmp add_to_waiting_list 668dma_next_scb2: 669 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */ 670 mov SCB_TAG call dma_scb 671add_to_waiting_list: 672 mov SCB_NEXT,WAITING_SCBH 673 mov WAITING_SCBH, SCBPTR 674 or FLAGS, SCB_LISTED |
|
657 jmp mesgin_done 658 | 675 jmp mesgin_done 676 |
659 | |
660/* 661 * Is it an extended message? Copy the message to our message buffer and 662 * notify the host. The host will tell us whether to reject this message, 663 * respond to it with the message that the host placed in our message buffer, 664 * or simply to do nothing. 665 */ 666mesgin_extended: 667 mvi MSGIN_EXT_LEN call inb_next | 677/* 678 * Is it an extended message? Copy the message to our message buffer and 679 * notify the host. The host will tell us whether to reject this message, 680 * respond to it with the message that the host placed in our message buffer, 681 * or simply to do nothing. 682 */ 683mesgin_extended: 684 mvi MSGIN_EXT_LEN call inb_next |
668 mvi MSGIN_EXT_OPCODE call inb_next | |
669 mov A, MSGIN_EXT_LEN | 685 mov A, MSGIN_EXT_LEN |
670 dec A /* Length counts the op code */ 671 mvi SINDEX, MSGIN_EXT_BYTE0 | |
672mesgin_extended_loop: | 686mesgin_extended_loop: |
673 test A, 0xFF jz mesgin_extended_intr 674 cmp SINDEX, MSGIN_EXT_LASTBYTE je mesgin_extended_dump 675 call inb_next | 687 mov DINDEX call inb_next |
676 dec A | 688 dec A |
677/* 678 * We pass the arg to inb in SINDEX, but DINDEX is the one incremented 679 * so update SINDEX with DINDEX's value before looping again. 680 */ 681 mov DINDEX jmp mesgin_extended_loop 682mesgin_extended_dump: 683/* We have no more storage space, so dump the rest */ 684 test A, 0xFF jz mesgin_extended_intr 685 mvi NONE call inb_next 686 dec A 687 jmp mesgin_extended_dump | 689 cmp DINDEX, MSGIN_EXT_LASTBYTE jne mesgin_extended_loop_test 690 dec DINDEX /* dump by repeatedly filling the last byte */ 691mesgin_extended_loop_test: 692 test A, 0xFF jnz mesgin_extended_loop |
688mesgin_extended_intr: 689 mvi INTSTAT,EXTENDED_MSG /* let driver know */ 690 cmp RETURN_1,SEND_REJ je rej_mesgin 691 cmp RETURN_1,SEND_MSG jne mesgin_done 692/* The kernel has setup a message to be sent */ 693 or SCSISIGO,ATNO /* turn on ATNO */ 694 jmp mesgin_done 695 696/* 697 * Is it a disconnect message? Set a flag in the SCB to remind us 698 * and await the bus going free. 699 */ 700mesgin_disconnect: 701 or SCB_CONTROL,DISCONNECTED 702 test FLAGS, PAGESCBS jz mesgin_done | 693mesgin_extended_intr: 694 mvi INTSTAT,EXTENDED_MSG /* let driver know */ 695 cmp RETURN_1,SEND_REJ je rej_mesgin 696 cmp RETURN_1,SEND_MSG jne mesgin_done 697/* The kernel has setup a message to be sent */ 698 or SCSISIGO,ATNO /* turn on ATNO */ 699 jmp mesgin_done 700 701/* 702 * Is it a disconnect message? Set a flag in the SCB to remind us 703 * and await the bus going free. 704 */ 705mesgin_disconnect: 706 or SCB_CONTROL,DISCONNECTED 707 test FLAGS, PAGESCBS jz mesgin_done |
703/* 704 * Link this SCB into the DISCONNECTED list. This list holds the 705 * candidates for paging out an SCB if one is needed for a new command. 706 * Modifying the disconnected list is a critical(pause dissabled) section. 707 */ 708 mvi SCB_PREV, SCB_LIST_NULL 709 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */ 710 mov SCB_NEXT, DISCONNECTED_SCBH 711 mov DISCONNECTED_SCBH, SCBPTR 712 cmp SCB_NEXT,SCB_LIST_NULL je linkdone 713 mov SCBPTR,SCB_NEXT 714 mov SCB_PREV,DISCONNECTED_SCBH 715 mov SCBPTR,DISCONNECTED_SCBH 716linkdone: 717 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */ | 708 call add_scb_to_disc_list 709 or FLAGS, SCB_LISTED |
718 jmp mesgin_done 719 720/* | 710 jmp mesgin_done 711 712/* |
721 * Save data pointers message? Copy working values into the SCB, 722 * usually in preparation for a disconnect. | 713 * Save data pointers message: 714 * Copying RAM values back to SCB, for Save Data Pointers message, but 715 * only if we've actually been into a data phase to change them. This 716 * protects against bogus data in scratch ram and the residual counts 717 * since they are only initialized when we go into data_in or data_out. |
723 */ 724mesgin_sdptrs: | 718 */ 719mesgin_sdptrs: |
725 call sg_ram2scb | 720 test FLAGS, DPHASE jz mesgin_done 721 mov SCB_SGCOUNT,SG_COUNT 722 723 /* The SCB SGPTR becomes the next one we'll download */ 724 mvi DINDEX, SCB_SGPTR 725 mvi SG_NEXT0 call bcopy_4 726 727 /* The SCB DATAPTR0 becomes the current SHADDR */ 728 mvi DINDEX, SCB_DATAPTR0 729 mvi SHADDR0 call bcopy_4 730 731/* 732 * Use the residual number since STCNT is corrupted by any message transfer. 733 */ 734 mvi SCB_RESID_DCNT0 call bcopy_3 735 |
726 jmp mesgin_done 727 728/* 729 * Restore pointers message? Data pointers are recopied from the 730 * SCB anytime we enter a data phase for the first time, so all 731 * we need to do is clear the DPHASE flag and let the data phase 732 * code do the rest. 733 */ --- 6 unchanged lines hidden (view full) --- 740 741/* 742 * Identify message? For a reconnecting target, this tells us the lun 743 * that the reconnection is for - find the correct SCB and switch to it, 744 * clearing the "disconnected" bit so we don't "find" it by accident later. 745 */ 746mesgin_identify: 747 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/ | 736 jmp mesgin_done 737 738/* 739 * Restore pointers message? Data pointers are recopied from the 740 * SCB anytime we enter a data phase for the first time, so all 741 * we need to do is clear the DPHASE flag and let the data phase 742 * code do the rest. 743 */ --- 6 unchanged lines hidden (view full) --- 750 751/* 752 * Identify message? For a reconnecting target, this tells us the lun 753 * that the reconnection is for - find the correct SCB and switch to it, 754 * clearing the "disconnected" bit so we don't "find" it by accident later. 755 */ 756mesgin_identify: 757 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/ |
748 | |
749 and A,0x07 /* lun in lower three bits */ | 758 and A,0x07 /* lun in lower three bits */ |
750 or SAVED_TCL,A,SELID 751 and SAVED_TCL,0xf7 752 and A,SELBUSB,SBLKCTL /* B Channel?? */ 753 or SAVED_TCL,A | 759 or SAVED_TCL,A /* SAVED_TCL should be complete now */ |
754 call inb_last /* ACK */ 755 756/* 757 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 758 * If we get one, we use the tag returned to switch to find the proper 759 * SCB. With SCB paging, this requires using findSCB for both tagged 760 * and non-tagged transactions since the SCB may exist in any slot. 761 * If we're not using SCB paging, we can use the tag as the direct --- 17 unchanged lines hidden (view full) --- 779 add SINDEX,A,ARG_1 780 jc abort_tag 781 782/* 783 * Ensure that the SCB the tag points to is for an SCB transaction 784 * to the reconnecting target. 785 */ 786 test FLAGS, PAGESCBS jz index_by_tag | 760 call inb_last /* ACK */ 761 762/* 763 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 764 * If we get one, we use the tag returned to switch to find the proper 765 * SCB. With SCB paging, this requires using findSCB for both tagged 766 * and non-tagged transactions since the SCB may exist in any slot. 767 * If we're not using SCB paging, we can use the tag as the direct --- 17 unchanged lines hidden (view full) --- 785 add SINDEX,A,ARG_1 786 jc abort_tag 787 788/* 789 * Ensure that the SCB the tag points to is for an SCB transaction 790 * to the reconnecting target. 791 */ 792 test FLAGS, PAGESCBS jz index_by_tag |
787 call inb_last /* Ack Tag */ | |
788use_findSCB: 789 mov ALLZEROS call findSCB /* Have to search */ 790setup_SCB: 791 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */ 792 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */ | 793use_findSCB: 794 mov ALLZEROS call findSCB /* Have to search */ 795setup_SCB: 796 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */ 797 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */ |
798 test SCB_CONTROL,TAG_ENB jnz mesgin_done /* Ack Tag */ |
|
793 jmp ITloop 794index_by_tag: 795 mov SCBPTR,ARG_1 796 mov A,SAVED_TCL 797 cmp SCB_TCL,A jne abort_tag 798 test SCB_CONTROL,TAG_ENB jz abort_tag | 799 jmp ITloop 800index_by_tag: 801 mov SCBPTR,ARG_1 802 mov A,SAVED_TCL 803 cmp SCB_TCL,A jne abort_tag 804 test SCB_CONTROL,TAG_ENB jz abort_tag |
799 call inb_last /* Ack Successful tag */ | |
800 jmp setup_SCB 801 802abort_tag: 803 or SCSISIGO,ATNO /* turn on ATNO */ | 805 jmp setup_SCB 806 807abort_tag: 808 or SCSISIGO,ATNO /* turn on ATNO */ |
804 mvi INTSTAT,ABORT_TAG /* let driver know */ | 809abort_tag_msg: |
805 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */ 806 jmp mesgin_done 807 808/* 809 * Message reject? Let the kernel driver handle this. If we have an 810 * outstanding WDTR or SDTR negotiation, assume that it's a response from 811 * the target selecting 8bit or asynchronous transfer, otherwise just ignore 812 * it since we have no clue what it pertains to. --- 15 unchanged lines hidden (view full) --- 828 mvi CLRSINT1,CLRATNO 829 clr LASTPHASE 830 831/* 832 * if this is an immediate command, perform a psuedo command complete to 833 * notify the driver. 834 */ 835 test SCB_CMDLEN,0xff jz status_ok | 810 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */ 811 jmp mesgin_done 812 813/* 814 * Message reject? Let the kernel driver handle this. If we have an 815 * outstanding WDTR or SDTR negotiation, assume that it's a response from 816 * the target selecting 8bit or asynchronous transfer, otherwise just ignore 817 * it since we have no clue what it pertains to. --- 15 unchanged lines hidden (view full) --- 833 mvi CLRSINT1,CLRATNO 834 clr LASTPHASE 835 836/* 837 * if this is an immediate command, perform a psuedo command complete to 838 * notify the driver. 839 */ 840 test SCB_CMDLEN,0xff jz status_ok |
841 test FLAGS, SCB_LISTED jnz start 842 /* 843 * This SCB didn't disconnect or have a command complete, 844 * so put it on the free queue. It was probably the 845 * result of an abort of some sort. This prevents us 846 * from "leaking" SCBs. 847 */ 848 call add_scb_to_free_list |
|
836 jmp start 837 838/* 839 * Locking the driver out, build a one-byte message passed in SINDEX 840 * if there is no active message already. SINDEX is returned intact. 841 */ 842mk_mesg: 843 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */ --- 88 unchanged lines hidden (view full) --- 932 933/* 934 * Common SCSI initialization for selection and reselection. Expects 935 * the target SCSI ID to be in the upper four bits of SINDEX, and A's 936 * contents are stomped on return. 937 */ 938initialize_scsiid: 939 and SINDEX,0xf0 /* Get target ID */ | 849 jmp start 850 851/* 852 * Locking the driver out, build a one-byte message passed in SINDEX 853 * if there is no active message already. SINDEX is returned intact. 854 */ 855mk_mesg: 856 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */ --- 88 unchanged lines hidden (view full) --- 945 946/* 947 * Common SCSI initialization for selection and reselection. Expects 948 * the target SCSI ID to be in the upper four bits of SINDEX, and A's 949 * contents are stomped on return. 950 */ 951initialize_scsiid: 952 and SINDEX,0xf0 /* Get target ID */ |
953 mov SAVED_TCL, SINDEX /* Update the target portion of this */ |
|
940 and A,0x0f,SCSIID 941 or SINDEX,A 942 mov SCSIID,SINDEX ret 943 944/* 945 * Assert that if we've been reselected, then we've seen an IDENTIFY 946 * message. 947 */ 948assert: 949 test FLAGS,RESELECTED jz return /* reselected? */ 950 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */ 951 | 954 and A,0x0f,SCSIID 955 or SINDEX,A 956 mov SCSIID,SINDEX ret 957 958/* 959 * Assert that if we've been reselected, then we've seen an IDENTIFY 960 * message. 961 */ 962assert: 963 test FLAGS,RESELECTED jz return /* reselected? */ 964 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */ 965 |
952 mvi INTSTAT,NO_IDENT ret /* no - cause a kernel panic */ | 966 mvi INTSTAT,NO_IDENT ret /* no - tell the kernel */ |
953 954/* 955 * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag 956 * value in ARG_1. If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged 957 * SCB. Have the kernel print a warning message if it can't be found, and 958 * generate an ABORT/ABORT_TAG message to the target. SINDEX should be 959 * cleared on call. 960 */ 961findSCB: 962 mov A,SAVED_TCL 963 mov SCBPTR,SINDEX /* switch to next SCB */ | 967 968/* 969 * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag 970 * value in ARG_1. If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged 971 * SCB. Have the kernel print a warning message if it can't be found, and 972 * generate an ABORT/ABORT_TAG message to the target. SINDEX should be 973 * cleared on call. 974 */ 975findSCB: 976 mov A,SAVED_TCL 977 mov SCBPTR,SINDEX /* switch to next SCB */ |
964 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */ | |
965 cmp SCB_TCL,A jne findSCB1 /* target ID/channel/lun match? */ 966 test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/ 967 test SCB_CONTROL,TAG_ENB jnz findTaggedSCB 968 cmp ARG_1,SCB_LIST_NULL je foundSCB | 978 cmp SCB_TCL,A jne findSCB1 /* target ID/channel/lun match? */ 979 test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/ 980 test SCB_CONTROL,TAG_ENB jnz findTaggedSCB 981 cmp ARG_1,SCB_LIST_NULL je foundSCB |
969 jmp findSCB1 | 982findSCB1: 983 inc SINDEX 984 mov A,SCBCOUNT 985 cmp SINDEX,A jne findSCB 986/* 987 * We didn't find it. If we're paging, pull an SCB and DMA down the 988 * one we want. If we aren't paging or the SCB we dma down has the 989 * abort flag set, alert the kernel and send an abort message. 990 */ 991 test FLAGS, PAGESCBS jz find_abort 992 call get_free_or_disc_scb 993 mov CUR_SCBID, ARG_1 994 cmp CUR_SCBID, SCB_LIST_NULL jne find_dma_scb 995 call index_untagged_scb 996 mov CUR_SCBID, SINDIR 997find_dma_scb: 998 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */ 999 mov CUR_SCBID call dma_scb 1000 test SCB_CONTROL, ABORT_SCB jz return 1001find_abort: 1002 mvi INTSTAT,NO_MATCH /* not found - signal kernel */ 1003 or SCSISIGO,ATNO /* assert ATNO */ 1004 cmp ARG_1,SCB_LIST_NULL jne abort_tag_msg 1005 mvi MSG_ABORT call mk_mesg 1006 jmp ITloop |
970findTaggedSCB: 971 mov A, ARG_1 /* Tag passed in ARG_1 */ 972 cmp SCB_TAG,A jne findSCB1 /* Found it? */ 973foundSCB: | 1007findTaggedSCB: 1008 mov A, ARG_1 /* Tag passed in ARG_1 */ 1009 cmp SCB_TAG,A jne findSCB1 /* Found it? */ 1010foundSCB: |
974 test FLAGS,PAGESCBS jz foundSCB_ret | 1011 test SCB_CONTROL, ABORT_SCB jnz find_abort 1012 test FLAGS,PAGESCBS jz return 1013rem_scb_from_disc_list: |
975/* Remove this SCB from the disconnection list */ 976 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev 977 mov SAVED_LINKPTR, SCB_PREV 978 mov SCBPTR, SCB_NEXT 979 mov SCB_PREV, SAVED_LINKPTR 980 mov SCBPTR, SINDEX 981unlink_prev: 982 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */ 983 mov SAVED_LINKPTR, SCB_NEXT 984 mov SCBPTR, SCB_PREV 985 mov SCB_NEXT, SAVED_LINKPTR | 1014/* Remove this SCB from the disconnection list */ 1015 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev 1016 mov SAVED_LINKPTR, SCB_PREV 1017 mov SCBPTR, SCB_NEXT 1018 mov SCB_PREV, SAVED_LINKPTR 1019 mov SCBPTR, SINDEX 1020unlink_prev: 1021 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */ 1022 mov SAVED_LINKPTR, SCB_NEXT 1023 mov SCBPTR, SCB_PREV 1024 mov SCB_NEXT, SAVED_LINKPTR |
986 mov SCBPTR, SINDEX 987 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */ | 1025 mov SCBPTR, SINDEX ret |
988rHead: | 1026rHead: |
989 mov DISCONNECTED_SCBH,SCB_NEXT 990foundSCB_ret: 991 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */ | 1027 mov DISCONNECTED_SCBH,SCB_NEXT ret |
992 | 1028 |
993findSCB1: 994 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */ 995 inc SINDEX 996 mov A,SCBCOUNT 997 cmp SINDEX,A jne findSCB 998 999 mvi INTSTAT,NO_MATCH /* not found - signal kernel */ 1000 cmp RETURN_1,SCB_PAGEDIN je return 1001 or SCSISIGO,ATNO /* assert ATNO */ 1002 cmp ARG_1,SCB_LIST_NULL jne find_abort_tag 1003 mvi MSG_ABORT call mk_mesg 1004 jmp ITloop 1005find_abort_tag: 1006 mvi MSG_ABORT_TAG call mk_mesg 1007 jmp ITloop 1008 1009/* 1010 * Make a working copy of the scatter-gather parameters from the SCB. 1011 */ 1012sg_scb2ram: 1013 mov HADDR0, SCB_DATAPTR0 1014 mov HADDR1, SCB_DATAPTR1 1015 mov HADDR2, SCB_DATAPTR2 1016 mov HADDR3, SCB_DATAPTR3 1017 mov HCNT0, SCB_DATACNT0 1018 mov HCNT1, SCB_DATACNT1 1019 mov HCNT2, SCB_DATACNT2 1020 | 1029set_stcnt_from_hcnt: |
1021 mov STCNT0, HCNT0 1022 mov STCNT1, HCNT1 | 1030 mov STCNT0, HCNT0 1031 mov STCNT1, HCNT1 |
1023 mov STCNT2, HCNT2 | 1032 mov STCNT2, HCNT2 ret |
1024 | 1033 |
1025 mov SG_COUNT,SCB_SGCOUNT | 1034bcopy_7: 1035 mov DINDIR, SINDIR 1036 mov DINDIR, SINDIR 1037bcopy_5: 1038 mov DINDIR, SINDIR 1039bcopy_4: 1040 mov DINDIR, SINDIR 1041bcopy_3: 1042 mov DINDIR, SINDIR 1043 mov DINDIR, SINDIR 1044 mov DINDIR, SINDIR ret |
1026 | 1045 |
1027 mov SG_NEXT0, SCB_SGPTR0 1028 mov SG_NEXT1, SCB_SGPTR1 1029 mov SG_NEXT2, SCB_SGPTR2 1030 mov SG_NEXT3, SCB_SGPTR3 ret | 1046dma_scb: 1047 /* 1048 * SCB index is in SINDEX. Determine the physical address in 1049 * the host where this SCB is located and load HADDR with it. 1050 */ 1051 shr DINDEX, SINDEX, 3 1052 shl A, SINDEX, 5 1053 add HADDR0, A, HSCB_ADDR0 1054 mov A, DINDEX 1055 adc HADDR1, A, HSCB_ADDR1 1056 clr A 1057 adc HADDR2, A, HSCB_ADDR2 1058 adc HADDR3, A, HSCB_ADDR3 1059 /* Setup Count */ 1060 mvi HCNT0, 28 1061 clr HCNT1 1062 clr HCNT2 1063 mov DFCNTRL, DMAPARAMS 1064 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost 1065 /* Fill it with the SCB data */ 1066 call copy_scb_tofifo 1067 mvi DFCNTRL, 0xa /* HDMAEN | FIFOFLUSH */ 1068dma_scb_fromhost: 1069 call dma_finish 1070 /* If we were putting the SCB, we are done */ 1071 test DMAPARAMS, DIRECTION jz return 1072 mvi SCBARRAY call dfdat_in_7 1073 call dfdat_in_7_continued 1074 call dfdat_in_7_continued 1075 jmp dfdat_in_7_continued 1076dfdat_in_7: 1077 mov DINDEX,SINDEX 1078dfdat_in_7_continued: 1079 mov DINDIR,DFDAT 1080 mov DINDIR,DFDAT 1081 mov DINDIR,DFDAT 1082 mov DINDIR,DFDAT 1083 mov DINDIR,DFDAT 1084 mov DINDIR,DFDAT 1085 mov DINDIR,DFDAT ret |
1031 | 1086 |
1087copy_scb_tofifo: 1088 mvi SCBARRAY call dfdat_out_7 1089 call dfdat_out_7 1090 call dfdat_out_7 1091dfdat_out_7: 1092 mov DFDAT,SINDIR 1093 mov DFDAT,SINDIR 1094 mov DFDAT,SINDIR 1095 mov DFDAT,SINDIR 1096 mov DFDAT,SINDIR 1097 mov DFDAT,SINDIR 1098 mov DFDAT,SINDIR ret 1099 |
|
1032/* | 1100/* |
1033 * Copying RAM values back to SCB, for Save Data Pointers message, but 1034 * only if we've actually been into a data phase to change them. This 1035 * protects against bogus data in scratch ram and the residual counts 1036 * since they are only initialized when we go into data_in or data_out. | 1101 * Wait for DMA from host memory to data FIFO to complete, then disable 1102 * DMA and wait for it to acknowledge that it's off. |
1037 */ | 1103 */ |
1038sg_ram2scb: 1039 test FLAGS, DPHASE jz return 1040 mov SCB_SGCOUNT,SG_COUNT | 1104dma_finish: 1105 test DFSTATUS,HDONE jz dma_finish 1106 /* Turn off DMA preserving WIDEODD */ 1107 and DFCNTRL,WIDEODD 1108dma_finish2: 1109 test DFCNTRL,HDMAENACK jnz dma_finish2 1110 ret |
1041 | 1111 |
1042 mov SCB_SGPTR0,SG_NEXT0 1043 mov SCB_SGPTR1,SG_NEXT1 1044 mov SCB_SGPTR2,SG_NEXT2 1045 mov SCB_SGPTR3,SG_NEXT3 1046 1047 mov SCB_DATAPTR0,SHADDR0 1048 mov SCB_DATAPTR1,SHADDR1 1049 mov SCB_DATAPTR2,SHADDR2 1050 mov SCB_DATAPTR3,SHADDR3 | 1112index_untagged_scb: 1113 shr SINDEX, SCB_TCL, 4 1114 and SINDEX, 0x03 /* Bottom two bits of tid */ 1115 add SINDEX, SCB_ACTIVE0 1116 shr A, SCB_TCL, 6 /* Target ID divided by 4 */ 1117 test SCB_TCL, SELBUSB jz index_untagged_scb2 1118 or A, 2 /* Add 2 positions */ 1119index_untagged_scb2: 1120 mov SCBPTR, A /* 1121 * Select the SCB with this 1122 * target's information. 1123 */ 1124 mov DINDEX, SINDEX ret |
1051 | 1125 |
1126 1127get_free_or_disc_scb: 1128 mov SINDEX, ALLZEROS 1129 cmp FREE_SCBH, SCB_LIST_NULL jne get_free_scb 1130 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je return_error 1131 mov SCBPTR, DISCONNECTED_SCBH |
|
1052/* | 1132/* |
1053 * Use the residual number since STCNT is corrupted by any message transfer | 1133 * If we are starting a new transaction, we have to ensure that 1134 * there is at least one SCB left in case a reselection wins out. |
1054 */ | 1135 */ |
1055 mov SCB_DATACNT0,SCB_RESID_DCNT0 1056 mov SCB_DATACNT1,SCB_RESID_DCNT1 1057 mov SCB_DATACNT2,SCB_RESID_DCNT2 ret | 1136 test FLAGS, RESELECTED jnz dequeue_disc_scb 1137 cmp SCB_NEXT, SCB_LIST_NULL je return_error 1138dequeue_disc_scb: 1139/* 1140 * If we have a residual, then we are in the middle of some I/O 1141 * and we have to send this SCB back up to the kernel so that the 1142 * saved data pointers and residual information isn't lost. 1143 */ 1144 test SCB_RESID_SGCNT,0xff jz unlink_disc_scb 1145 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/ 1146 mov SCB_TAG call dma_scb 1147unlink_disc_scb: 1148 call rem_scb_from_disc_list 1149 ret 1150get_free_scb: 1151/* 1152 * If we are starting a new transaction, we have to ensure that 1153 * there is at least one SCB left in case a reselection wins out. 1154 */ 1155 test FLAGS, RESELECTED jnz dequeue_free_scb 1156 cmp SCB_NEXT, SCB_LIST_NULL jne dequeue_free_scb 1157 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je return_error 1158dequeue_free_scb: 1159 mov SCBPTR, FREE_SCBH 1160 mov FREE_SCBH, SCB_NEXT ret 1161return_error: 1162 mvi SINDEX, SCB_LIST_NULL ret |
1058 | 1163 |
1164add_scb_to_free_list: 1165 mov SCB_NEXT, FREE_SCBH 1166 mov FREE_SCBH, SCBPTR ret 1167 1168add_scb_to_disc_list: |
|
1059/* | 1169/* |
1060 * Add the array base TARG_SCRATCH to the target offset (the target address 1061 * is in SCSIID), and return the result in SINDEX. The accumulator 1062 * contains the 3->8 decoding of the target ID on return. | 1170 * Link this SCB into the DISCONNECTED list. This list holds the 1171 * candidates for paging out an SCB if one is needed for a new command. 1172 * Modifying the disconnected list is a critical(pause dissabled) section. |
1063 */ | 1173 */ |
1064ndx_dtr: 1065 shr A,SCSIID,4 1066 test SBLKCTL,SELBUSB jz ndx_dtr_2 1067 or A,0x08 /* Channel B entries add 8 */ 1068ndx_dtr_2: 1069 add SINDEX,TARG_SCRATCH,A ret | 1174 mvi SCB_PREV, SCB_LIST_NULL 1175 mov SCB_NEXT, DISCONNECTED_SCBH 1176 mov DISCONNECTED_SCBH, SCBPTR 1177 cmp SCB_NEXT,SCB_LIST_NULL je return 1178 mov SCBPTR,SCB_NEXT 1179 mov SCB_PREV,DISCONNECTED_SCBH 1180 mov SCBPTR,DISCONNECTED_SCBH ret 1181 |