aic7xxx.seq revision 7562
140843Smsmith# @(#)aic7xxx.seq 1.32 94/11/29 jda 240843Smsmith# 340843Smsmith# Adaptec 274x/284x/294x device driver for Linux and FreeBSD. 440843Smsmith# Copyright (c) 1994 The University of Calgary Department of Computer Science. 594290Sdcs# 651786Sdcs# This program is free software; you can redistribute it and/or modify 751786Sdcs# it under the terms of the GNU General Public License as published by 840843Smsmith# the Free Software Foundation; either version 2 of the License, or 940843Smsmith# (at your option) any later version. 1040843Smsmith# 1140843Smsmith# This program is distributed in the hope that it will be useful, 1240843Smsmith# but WITHOUT ANY WARRANTY; without even the implied warranty of 1340843Smsmith# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1440843Smsmith# GNU General Public License for more details. 1540843Smsmith# 1640843Smsmith# You should have received a copy of the GNU General Public License 1740843Smsmith# along with this program; if not, write to the Free Software 1840843Smsmith# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1940843Smsmith# 2040843Smsmith 2140843Smsmith# FreeBSD, Twin, Wide, 2 command per target support, tagged queuing and other 2240843Smsmith# optimizations provided by Justin T. Gibbs (gibbs@FreeBSD.org) 2340843Smsmith# 2440843Smsmith 2540843SmsmithVERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.11 1995/03/31 14:06:02 gibbs Exp $" 2640843Smsmith 2740843SmsmithSCBMASK = 0x1f 2840843Smsmith 2940843SmsmithSCSISEQ = 0x00 3040843SmsmithSXFRCTL0 = 0x01 3140843SmsmithSXFRCTL1 = 0x02 3240843SmsmithSCSISIGI = 0x03 3376116SdcsSCSISIGO = 0x03 3461584SdcsSCSIRATE = 0x04 3561584SdcsSCSIID = 0x05 3676116SdcsSCSIDATL = 0x06 3761584SdcsSTCNT = 0x08 3861584SdcsSTCNT+0 = 0x08 3961584SdcsSTCNT+1 = 0x09 4061584SdcsSTCNT+2 = 0x0a 4161584SdcsSSTAT0 = 0x0b 4261584SdcsCLRSINT1 = 0x0c 4376116SdcsSSTAT1 = 0x0c 4461584SdcsSIMODE1 = 0x11 4561584SdcsSCSIBUSL = 0x12 4661584SdcsSHADDR = 0x14 4761584SdcsSELID = 0x19 4876116SdcsSBLKCTL = 0x1f 4976116SdcsSEQCTL = 0x60 5076116SdcsA = 0x64 # == ACCUM 5176116SdcsSINDEX = 0x65 5261584SdcsDINDEX = 0x66 5340843SmsmithALLZEROS = 0x6a 5440843SmsmithNONE = 0x6a 5540843SmsmithSINDIR = 0x6c 5676116SdcsDINDIR = 0x6d 5776116SdcsFUNCTION1 = 0x6e 5856718SdcsHADDR = 0x88 5956718SdcsHADDR+1 = 0x89 6040843SmsmithHADDR+2 = 0x8a 6194290SdcsHADDR+3 = 0x8b 6240843SmsmithHCNT = 0x8c 6394290SdcsHCNT+0 = 0x8c 6494290SdcsHCNT+1 = 0x8d 6594290SdcsHCNT+2 = 0x8e 6640843SmsmithSCBPTR = 0x90 6740843SmsmithINTSTAT = 0x91 6851786SdcsDFCNTRL = 0x93 6940843SmsmithDFSTATUS = 0x94 7051786SdcsDFDAT = 0x99 7140843SmsmithQINFIFO = 0x9b 7240843SmsmithQINCNT = 0x9c 7340843SmsmithQOUTFIFO = 0x9d 7440843Smsmith 7540843SmsmithSCSICONF_A = 0x5a 7640843SmsmithSCSICONF_B = 0x5b 7740843Smsmith 7840843Smsmith# The two reserved bytes at SCBARRAY+1[23] are expected to be set to 7940843Smsmith# zero, and the reserved bit in SCBARRAY+0 is used as an internal flag 8040843Smsmith# to indicate whether or not to reload scatter-gather parameters after 8140843Smsmith# a disconnect. We also use bits 6 & 7 to indicate whether or not to 8240843Smsmith# initiate SDTR or WDTR repectively when starting this command. 8340843Smsmith# 8440843SmsmithSCBARRAY+0 = 0xa0 8540843Smsmith 8660959SdcsDISCONNECTED = 0x04 8760959SdcsNEEDDMA = 0x08 8840843SmsmithSG_LOAD = 0x10 8940843SmsmithTAG_ENB = 0x20 9040843SmsmithNEEDSDTR = 0x40 9140843SmsmithNEEDWDTR = 0x80 9240843Smsmith 9340843SmsmithSCBARRAY+1 = 0xa1 9440843SmsmithSCBARRAY+2 = 0xa2 9540843SmsmithSCBARRAY+3 = 0xa3 9640843SmsmithSCBARRAY+4 = 0xa4 9740843SmsmithSCBARRAY+5 = 0xa5 9840843SmsmithSCBARRAY+6 = 0xa6 9940843SmsmithSCBARRAY+7 = 0xa7 10040843SmsmithSCBARRAY+8 = 0xa8 10140843SmsmithSCBARRAY+9 = 0xa9 10276116SdcsSCBARRAY+10 = 0xaa 10376116SdcsSCBARRAY+11 = 0xab 10476116SdcsSCBARRAY+12 = 0xac 10576116SdcsSCBARRAY+13 = 0xad 10676116SdcsSCBARRAY+14 = 0xae 10776116SdcsSCBARRAY+15 = 0xaf 10876116SdcsSCBARRAY+16 = 0xb0 10976116SdcsSCBARRAY+17 = 0xb1 11040843SmsmithSCBARRAY+18 = 0xb2 11140843SmsmithSCBARRAY+19 = 0xb3 11240843SmsmithSCBARRAY+20 = 0xb4 11376116SdcsSCBARRAY+21 = 0xb5 11476116SdcsSCBARRAY+22 = 0xb6 11576116SdcsSCBARRAY+23 = 0xb7 11676116SdcsSCBARRAY+24 = 0xb8 11740843SmsmithSCBARRAY+25 = 0xb9 11840843SmsmithSCBARRAY+26 = 0xba 11940843SmsmithSCBARRAY+27 = 0xbb 12040843SmsmithSCBARRAY+28 = 0xbc 12140843SmsmithSCBARRAY+29 = 0xbd 12276116Sdcs 12376116SdcsBAD_PHASE = 0x01 # unknown scsi bus phase 12476116SdcsCMDCMPLT = 0x02 12540843SmsmithSEND_REJECT = 0x11 # sending a message reject 12676116SdcsNO_IDENT = 0x21 # no IDENTIFY after reconnect 12740843SmsmithNO_MATCH = 0x31 # no cmd match for reconnect 12876116SdcsMSG_SDTR = 0x41 # SDTR message recieved 12976116SdcsMSG_WDTR = 0x51 # WDTR message recieved 13040843SmsmithMSG_REJECT = 0x61 # Reject message recieved 13176116SdcsBAD_STATUS = 0x71 # Bad status from target 13276116SdcsRESIDUAL = 0x81 # Residual byte count != 0 13376116SdcsABORT_TAG = 0x91 # Sent an ABORT_TAG message 13476116Sdcs 13576116Sdcs# The host adapter card (at least the BIOS) uses 20-2f for SCSI 13676116Sdcs# device information, 32-33 and 5a-5f as well. As it turns out, the 13776116Sdcs# BIOS trashes 20-2f, writing the synchronous negotiation results 13876116Sdcs# on top of the BIOS values, so we re-use those for our per-target 13976116Sdcs# scratchspace (actually a value that can be copied directly into 14076116Sdcs# SCSIRATE). The kernel driver will enable synchronous negotiation 14176116Sdcs# for all targets that have a value other than 0 in the lower four 14240843Smsmith# bits of the target scratch space. This should work irregardless of 14340843Smsmith# whether the bios has been installed. NEEDWDTR and NEEDSDTR are the top 14440843Smsmith# two bits of the SCB control byte. The kernel driver will set these 14540843Smsmith# when a WDTR or SDTR message should be sent to the target the SCB's 14640843Smsmith# command references. 14740843Smsmith# 14840843Smsmith# The high bit of DROPATN is set if ATN should be dropped before the ACK 14940843Smsmith# when outb is called. REJBYTE contains the first byte of a MESSAGE IN 15040843Smsmith# message, so the driver can report an intelligible error if a message is 15140843Smsmith# rejected. 15240843Smsmith# 15340843Smsmith# FLAGS's high bit is true if we are currently handling a reselect; 15440843Smsmith# its next-highest bit is true ONLY IF we've seen an IDENTIFY message 15540843Smsmith# from the reselecting target. If we haven't had IDENTIFY, then we have 15676116Sdcs# no idea what the lun is, and we can't select the right SCB register 15776116Sdcs# bank, so force a kernel panic if the target attempts a data in/out or 15876116Sdcs# command phase instead of corrupting something. 15976116Sdcs# 16076116Sdcs# Note that SG_NEXT occupies four bytes. 16176116Sdcs# 16276116SdcsSYNCNEG = 0x20 16376116Sdcs 16476116SdcsDROPATN = 0x30 16576116SdcsREJBYTE = 0x31 16676116SdcsDISC_DSB_A = 0x32 16740843SmsmithDISC_DSB_B = 0x33 16876116Sdcs 16976116SdcsMSG_LEN = 0x34 17076116SdcsMSG_START+0 = 0x35 17176116SdcsMSG_START+1 = 0x36 17240843SmsmithMSG_START+2 = 0x37 17394290SdcsMSG_START+3 = 0x38 17494290SdcsMSG_START+4 = 0x39 17540843SmsmithMSG_START+5 = 0x3a 17694290Sdcs-MSG_START+0 = 0xcb # 2's complement of MSG_START+0 17794290Sdcs 17894290SdcsARG_1 = 0x4a # sdtr conversion args & return 17994290SdcsBUS_16_BIT = 0x01 18094290SdcsRETURN_1 = 0x4a 18194290Sdcs 18294290SdcsSIGSTATE = 0x4b # value written to SCSISIGO 18394290Sdcs 18494290Sdcs# Linux users should use 0xc (12) for SG_SIZEOF 18594290SdcsSG_SIZEOF = 0x8 # sizeof(struct ahc_dma) 18694290Sdcs#SG_SIZEOF = 0xc # sizeof(struct scatterlist) 18794290SdcsSCB_SIZEOF = 0x13 # sizeof SCB to DMA (19 bytes) 18894290Sdcs 18994290SdcsSG_NOLOAD = 0x4c # load SG pointer/length? 19094290SdcsSG_COUNT = 0x4d # working value of SG count 19194290SdcsSG_NEXT = 0x4e # working value of SG pointer 19294290SdcsSG_NEXT+0 = 0x4e 19394290SdcsSG_NEXT+1 = 0x4f 19494290SdcsSG_NEXT+2 = 0x50 19594290SdcsSG_NEXT+3 = 0x51 19694290Sdcs 19794290SdcsSCBCOUNT = 0x52 # the actual number of SCBs 19894290SdcsFLAGS = 0x53 # Device configuration flags 19994290SdcsTWIN_BUS = 0x01 20094290SdcsWIDE_BUS = 0x02 20194290SdcsMAX_SYNC = 0x08 20294290SdcsSENSE = 0x10 20376116SdcsACTIVE_MSG = 0x20 20440843SmsmithIDENTIFY_SEEN = 0x40 20540843SmsmithRESELECTED = 0x80 20640843Smsmith 207ACTIVE_A = 0x54 208ACTIVE_B = 0x55 209SAVED_TCL = 0x56 210# Poll QINCNT for work - the lower bits contain 211# the number of entries in the Queue In FIFO. 212# 213start: 214 test FLAGS,SENSE jnz start_sense 215start_nosense: 216 test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device? 217# For fairness, we check the other bus first, since we just finished a 218# transaction on the current channel. 219 xor SBLKCTL,0x08 # Toggle to the other bus 220 test SCSISIGI,0x4 jnz reselect # BSYI 221 xor SBLKCTL,0x08 # Toggle to the original bus 222start2: 223 test SCSISIGI,0x4 jnz reselect # BSYI 224 test QINCNT,SCBMASK jz start_nosense 225 226# We have at least one queued SCB now. Set the SCB pointer 227# from the FIFO so we see the right bank of SCB registers, 228# then set SCSI options and set the initiator and target 229# SCSI IDs. 230# 231 mov SCBPTR,QINFIFO 232 233# If the control byte of this SCB has the NEEDDMA flag set, we have 234# yet to DMA it from host memory 235 236test SCBARRAY+0,NEEDDMA jz test_busy 237 clr HCNT+2 238 clr HCNT+1 239 mvi HCNT+0,SCB_SIZEOF 240 241 mvi DINDEX,HADDR 242 mvi SCBARRAY+26 call bcopy_4 243 244 mvi DFCNTRL,0xd # HDMAEN|DIRECTION|FIFORESET 245 246# Wait for DMA from host memory to data FIFO to complete, then disable 247# DMA and wait for it to acknowledge that it's off. 248# 249 call dma_finish 250 251# Copy the SCB from the FIFO to the SCBARRAY 252 253 mvi DINDEX, SCBARRAY+0 254 call bcopy_3_dfdat 255 call bcopy_4_dfdat 256 call bcopy_4_dfdat 257 call bcopy_4_dfdat 258 call bcopy_4_dfdat 259 260# See if there is not already an active SCB for this target. This code 261# locks out on a per target basis instead of target/lun. Although this 262# is not ideal for devices that have multiple luns active at the same 263# time, it is faster than looping through all SCB's looking for active 264# commands. It may be benificial to make findscb a more general procedure 265# to see if the added cost of the search is negligible. This code also 266# assumes that the kernel driver will clear the active flags on board 267# initialization, board reset, and a target's SELTO. 268 269test_busy: 270 test SCBARRAY+0,0x20 jnz start_scb 271 and FUNCTION1,0x70,SCBARRAY+1 272 mov A,FUNCTION1 273 test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel 274 275 test ACTIVE_B,A jnz requeue 276 or ACTIVE_B,A # Mark the current target as busy 277 jmp start_scb 278 279start_sense: 280# Clear the SENSE flag first, then do a normal start_scb 281 and FLAGS,0xef 282 jmp start_scb 283 284# Place the currently active back on the queue for later processing 285requeue: 286 mov QINFIFO, SCBPTR 287 jmp start_nosense 288 289test_a: 290 test ACTIVE_A,A jnz requeue 291 or ACTIVE_A,A # Mark the current target as busy 292 293start_scb: 294 or SCBARRAY+0,NEEDDMA 295 and SINDEX,0xf7,SBLKCTL #Clear the channel select bit 296 and A,0x08,SCBARRAY+1 #Get new channel bit 297 or SINDEX,A 298 mov SBLKCTL,SINDEX # select channel 299 mov SCBARRAY+1 call initialize 300 clr SG_NOLOAD 301 and FLAGS,0x3f # !RESELECTING 302 303# As soon as we get a successful selection, the target should go 304# into the message out phase since we have ATN asserted. Prepare 305# the message to send, locking out the device driver. If the device 306# driver hasn't beaten us with an ABORT or RESET message, then tack 307# on an SDTR negotiation if required. 308# 309# Messages are stored in scratch RAM starting with a flag byte (high bit 310# set means active message), one length byte, and then the message itself. 311# 312 mov SCBARRAY+1 call disconnect # disconnect ok? 313 314 and SINDEX,0x7,SCBARRAY+1 # lun 315 or SINDEX,A # return value from disconnect 316 or SINDEX,0x80 call mk_mesg # IDENTIFY message 317 318 mov A,SINDEX 319 test SCBARRAY+0,0xe0 jz !message # WDTR, SDTR or TAG?? 320 cmp MSG_START+0,A jne !message # did driver beat us? 321 322# Tag Message if Tag enabled in SCB control block. Use SCBPTR as the tag 323# value 324 325mk_tag: 326 mvi DINDEX, MSG_START+1 327 test SCBARRAY+0,TAG_ENB jz mk_tag_done 328 and A,0x23,SCBARRAY+0 329 mov DINDIR,A 330 mov DINDIR,SCBPTR 331 332 add MSG_LEN,-MSG_START+0,DINDEX # update message length 333 334mk_tag_done: 335 336 mov DINDEX call mk_dtr # build DTR message if needed 337 338!message: 339 340# Enable selection phase as an initiator, and do automatic ATN 341# after the selection. 342# 343 mvi SCSISEQ,0x48 # ENSELO|ENAUTOATNO 344 345# Wait for successful arbitration. The AIC-7770 documentation says 346# that SELINGO indicates successful arbitration, and that it should 347# be used to look for SELDO. However, if the sequencer is paused at 348# just the right time - a parallel fsck(8) on two drives did it for 349# me - then SELINGO can flip back to false before we've seen it. This 350# makes the sequencer sit in the arbitration loop forever. This is 351# Not Good. 352# 353# Therefore, I've added a check in the arbitration loop for SELDO 354# too. This could arguably be made a critical section by disabling 355# pauses, but I don't want to make a potentially infinite loop a CS. 356# I suppose you could fold it into the select loop, too, but since 357# I've been hunting this bug for four days it's kinda like a trophy. 358# 359arbitrate: 360 test SSTAT0,0x40 jnz *select # SELDO 361 test SSTAT0,0x10 jz arbitrate # SELINGO 362 363# Wait for a successful selection. If the hardware selection 364# timer goes off, then the driver gets the interrupt, so we don't 365# need to worry about it. 366# 367select: 368 test SSTAT0,0x40 jz select # SELDO 369 jmp *select 370 371# Reselection is being initiated by a target - we've seen the BSY 372# line driven active, and we didn't do it! Enable the reselection 373# hardware, and wait for it to finish. Make a note that we've been 374# reselected, but haven't seen an IDENTIFY message from the target 375# yet. 376# 377reselect: 378 mvi SCSISEQ,0x10 # ENRSELI 379 380reselect1: 381 test SSTAT0,0x20 jz reselect1 # SELDI 382 mov SELID call initialize 383 384 and FLAGS,0x3f # reselected, no IDENTIFY 385 or FLAGS,RESELECTED 386 387# After the [re]selection, make sure that the [re]selection enable 388# bit is off. This chip is flaky enough without extra things 389# turned on. Also clear the BUSFREE bit in SSTAT1 since we'll be 390# using it shortly. 391# 392*select: 393 clr SCSISEQ 394 mvi CLRSINT1,0x8 # CLRBUSFREE 395 396# Main loop for information transfer phases. If BSY is false, then 397# we have a bus free condition, expected or not. Otherwise, wait 398# for the target to assert REQ before checking MSG, C/D and I/O 399# for the bus phase. 400# 401# We can't simply look at the values of SCSISIGI here (if we want 402# to do synchronous data transfer), because the target won't assert 403# REQ if it's already sent us some data that we haven't acknowledged 404# yet. 405# 406ITloop: 407 test SSTAT1,0x8 jnz p_busfree # BUSFREE 408 test SSTAT1,0x1 jz ITloop # REQINIT 409 410 and A,0xe0,SCSISIGI # CDI|IOI|MSGI 411 412 cmp ALLZEROS,A je p_dataout 413 cmp A,0x40 je p_datain 414 cmp A,0x80 je p_command 415 cmp A,0xc0 je p_status 416 cmp A,0xa0 je p_mesgout 417 cmp A,0xe0 je p_mesgin 418 419 mvi INTSTAT,BAD_PHASE # unknown - signal driver 420 421p_dataout: 422 mvi 0 call scsisig # !CDO|!IOO|!MSGO 423 call assert 424 call sg_load 425 426 mvi DINDEX,HADDR 427 mvi SCBARRAY+19 call bcopy_4 428 429# mvi DINDEX,HCNT # implicit since HCNT is next to HADDR 430 mvi SCBARRAY+23 call bcopy_3 431 432 mvi DINDEX,STCNT 433 mvi SCBARRAY+23 call bcopy_3 434 435# If we are the last SG block, don't set wideodd. 436 test SCBARRAY+18,0xff jnz p_dataout_wideodd 437 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN| 438 # DIRECTION|FIFORESET 439 jmp p_dataout_rest 440 441p_dataout_wideodd: 442 mvi 0xbd call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN| 443 # DIRECTION|FIFORESET 444 445p_dataout_rest: 446# After a DMA finishes, save the final transfer pointer and count 447# back into the SCB, in case a device disconnects in the middle of 448# a transfer. Use SHADDR and STCNT instead of HADDR and HCNT, since 449# it's a reflection of how many bytes were transferred on the SCSI 450# (as opposed to the host) bus. 451# 452 mvi DINDEX,SCBARRAY+23 453 mvi STCNT call bcopy_3 454 455 mvi DINDEX,SCBARRAY+19 456 mvi SHADDR call bcopy_4 457 458 call sg_advance 459 mov SCBARRAY+18,SG_COUNT # residual S/G count 460 461 jmp ITloop 462 463p_datain: 464 mvi 0x40 call scsisig # !CDO|IOO|!MSGO 465 call assert 466 call sg_load 467 468 mvi DINDEX,HADDR 469 mvi SCBARRAY+19 call bcopy_4 470 471# mvi DINDEX,HCNT # implicit since HCNT is next to HADDR 472 mvi SCBARRAY+23 call bcopy_3 473 474 mvi DINDEX,STCNT 475 mvi SCBARRAY+23 call bcopy_3 476 477# If we are the last SG block, don't set wideodd. 478 test SCBARRAY+18,0xff jnz p_datain_wideodd 479 mvi 0x39 call dma # SCSIEN|SDMAEN|HDMAEN| 480 # !DIRECTION|FIFORESET 481 jmp p_datain_rest 482p_datain_wideodd: 483 mvi 0xb9 call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN| 484 # !DIRECTION|FIFORESET 485p_datain_rest: 486 mvi DINDEX,SCBARRAY+23 487 mvi STCNT call bcopy_3 488 489 mvi DINDEX,SCBARRAY+19 490 mvi SHADDR call bcopy_4 491 492 call sg_advance 493 mov SCBARRAY+18,SG_COUNT # residual S/G count 494 495 jmp ITloop 496 497# Command phase. Set up the DMA registers and let 'er rip - the 498# two bytes after the SCB SCSI_cmd_length are zeroed by the driver, 499# so we can copy those three bytes directly into HCNT. 500# 501p_command: 502 mvi 0x80 call scsisig # CDO|!IOO|!MSGO 503 call assert 504 505 mvi DINDEX,HADDR 506 mvi SCBARRAY+7 call bcopy_4 507 508# mvi DINDEX,HCNT # implicit since HCNT is next to HADDR 509 mvi SCBARRAY+11 call bcopy_3 510 511 mvi DINDEX,STCNT 512 mvi SCBARRAY+11 call bcopy_3 513 514 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN| 515 # DIRECTION|FIFORESET 516 jmp ITloop 517 518# Status phase. Wait for the data byte to appear, then read it 519# and store it into the SCB. 520# 521p_status: 522 mvi 0xc0 call scsisig # CDO|IOO|!MSGO 523 524 mvi SCBARRAY+14 call inb 525 jmp ITloop 526 527# Message out phase. If there is no active message, but the target 528# took us into this phase anyway, build a no-op message and send it. 529# 530p_mesgout: 531 mvi 0xa0 call scsisig # CDO|!IOO|MSGO 532 mvi 0x8 call mk_mesg # build NOP message 533 534# Set up automatic PIO transfer from MSG_START. Bit 3 in 535# SXFRCTL0 (SPIOEN) is already on. 536# 537 mvi SINDEX,MSG_START+0 538 mov DINDEX,MSG_LEN 539 clr A 540 541# When target asks for a byte, drop ATN if it's the last one in 542# the message. Otherwise, keep going until the message is exhausted. 543# (We can't use outb for this since it wants the input in SINDEX.) 544# 545# Keep an eye out for a phase change, in case the target issues 546# a MESSAGE REJECT. 547# 548p_mesgout2: 549 test SSTAT0,0x2 jz p_mesgout2 # SPIORDY 550 test SSTAT1,0x10 jnz p_mesgout6 # PHASEMIS 551 552 cmp DINDEX,1 jne p_mesgout3 # last byte? 553 mvi CLRSINT1,0x40 # CLRATNO - drop ATN 554 555# Write a byte to the SCSI bus. The AIC-7770 refuses to automatically 556# send ACKs in automatic PIO or DMA mode unless you make sure that the 557# "expected" bus phase in SCSISIGO matches the actual bus phase. This 558# behaviour is completely undocumented and caused me several days of 559# grief. 560# 561# After plugging in different drives to test with and using a longer 562# SCSI cable, I found that I/O in Automatic PIO mode ceased to function, 563# especially when transferring >1 byte. It seems to be much more stable 564# if STCNT is set to one before the transfer, and SDONE (in SSTAT0) is 565# polled for transfer completion - for both output _and_ input. The 566# only theory I have is that SPIORDY doesn't drop right away when SCSIDATL 567# is accessed (like the documentation says it does), and that on a longer 568# cable run, the sequencer code was fast enough to loop back and see 569# an SPIORDY that hadn't dropped yet. 570# 571p_mesgout3: 572 call one_stcnt 573 mov SCSIDATL,SINDIR 574 575p_mesgout4: 576 test SSTAT0,0x4 jz p_mesgout4 # SDONE 577 dec DINDEX 578 inc A 579 cmp MSG_LEN,A jne p_mesgout2 580 581# If the next bus phase after ATN drops is a message out, it means 582# that the target is requesting that the last message(s) be resent. 583# 584p_mesgout5: 585 test SSTAT1,0x8 jnz p_mesgout6 # BUSFREE 586 test SSTAT1,0x1 jz p_mesgout5 # REQINIT 587 588 and A,0xe0,SCSISIGI # CDI|IOI|MSGI 589 cmp A,0xa0 jne p_mesgout6 590 mvi 0x10 call scsisig # ATNO - re-assert ATN 591 592 jmp ITloop 593 594p_mesgout6: 595 mvi CLRSINT1,0x40 # CLRATNO - in case of PHASEMIS 596 and FLAGS,0xdf # no active msg 597 jmp ITloop 598 599# Message in phase. Bytes are read using Automatic PIO mode, but not 600# using inb. This alleviates a race condition, namely that if ATN had 601# to be asserted under Automatic PIO mode, it had to beat the SCSI 602# circuitry sending an ACK to the target. This showed up under heavy 603# loads and really confused things, since ABORT commands wouldn't be 604# seen by the drive after an IDENTIFY message in until it had changed 605# to a data I/O phase. 606# 607p_mesgin: 608 mvi 0xe0 call scsisig # CDO|IOO|MSGO 609 mvi A call inb_first # read the 1st message byte 610 mvi REJBYTE,A # save it for the driver 611 612 cmp ALLZEROS,A jne p_mesgin1 613 614# We got a "command complete" message, so put the SCB pointer 615# into the Queue Out, and trigger a completion interrupt. 616# Check status for non zero return and interrupt driver if needed 617# This allows the driver to interpret errors only when they occur 618# instead of always uploading the scb. If the status is SCSI_CHECK, 619# the driver will download a new scb requesting sense, to replace 620# the old one and set the SENSE sequencer flag. If the sense flag is 621# set, the sequencer imediately jumps to start working on the sense 622# command. If the kernel driver does not wish to request sense, it need 623# do nothing, and the command is allowed to complete. We don't 624# bother to post to the QOUTFIFO in the error case since it would require 625# extra work in the kernel driver to ensure that the entry was removed 626# before the command complete code tried processing it. 627 628 test SCBARRAY+15,0xff jnz resid 629 test SCBARRAY+16,0xff jnz resid 630 test SCBARRAY+17,0xff jnz resid 631 632check_status: 633 test SCBARRAY+14,0xff jz status_ok # 0 Status? 634 mvi INTSTAT,BAD_STATUS # let driver know 635 test FLAGS,SENSE jz status_ok 636 jmp p_mesgin_done 637 638status_ok: 639# First, mark this target as free. 640 test SCBARRAY+0,0x20 jnz complete # Tagged command 641 and FUNCTION1,0x70,SCBARRAY+1 642 mov A,FUNCTION1 643 test SCBARRAY+1,0x88 jz clear_a 644 xor ACTIVE_B,A 645 jmp complete 646 647clear_a: 648 xor ACTIVE_A,A 649 650complete: 651 mov QOUTFIFO,SCBPTR 652 mvi INTSTAT,CMDCMPLT 653 jmp p_mesgin_done 654 655# If we have a residual count, interrupt and tell the host. Other 656# alternatives are to pause the sequencer on all command completes (yuck), 657# dma the resid directly to the host (slick, but a ton of instructions), or 658# have the sequencer pause itself when it encounters a non-zero resid 659# (unecessary pause just to flag the command -- yuck, but takes few instructions 660# and since it shouldn't happen that offten is good enough for our purposes). 661 662resid: 663 mvi INTSTAT,RESIDUAL 664 jmp check_status 665 666# Is it an extended message? We only support the synchronous and wide data 667# transfer request messages, which will probably be in response to 668# WDTR or SDTR message outs from us. If it's not SDTR or WDTR, reject it - 669# apparently this can be done after any message in byte, according 670# to the SCSI-2 spec. 671# 672p_mesgin1: 673 cmp A,1 jne p_mesgin2 # extended message code? 674 675 mvi ARG_1 call inb_next # extended message length 676 mvi A call inb_next # extended message code 677 678 cmp A,1 je p_mesginSDTR # Syncronous negotiation message 679 cmp A,3 je p_mesginWDTR # Wide negotiation message 680 jmp p_mesginN 681 682p_mesginWDTR: 683 cmp ARG_1,2 jne p_mesginN # extended mesg length = 2 684 mvi A call inb_next # Width of bus 685 mvi INTSTAT,MSG_WDTR # let driver know 686 test RETURN_1,0x80 jz p_mesgin_done# Do we need to send WDTR? 687 688# We didn't initiate the wide negotiation, so we must respond to the request 689 and RETURN_1,0x7f # Clear the SEND_WDTR Flag 690 or FLAGS,ACTIVE_MSG 691 mvi DINDEX,MSG_START+0 692 mvi MSG_START+0 call mk_wdtr # build WDTR message 693 or SINDEX,0x10,SIGSTATE # turn on ATNO 694 call scsisig 695 jmp p_mesgin_done 696 697p_mesginSDTR: 698 cmp ARG_1,3 jne p_mesginN # extended mesg length = 3 699 mvi ARG_1 call inb_next # xfer period 700 mvi A call inb_next # REQ/ACK offset 701 mvi INTSTAT,MSG_SDTR # call driver to convert 702 703 test RETURN_1,0x80 jz p_mesgin_done# Do we need to mk_sdtr? 704 705 or FLAGS,ACTIVE_MSG 706 mvi DINDEX, MSG_START+0 707 mvi MSG_START+0 call mk_sdtr 708 or SINDEX,0x10,SIGSTATE # turn on ATNO 709 call scsisig 710 jmp p_mesgin_done 711 712# Is it a disconnect message? Set a flag in the SCB to remind us 713# and await the bus going free. 714# 715p_mesgin2: 716 cmp A,4 jne p_mesgin3 # disconnect code? 717 718 or SCBARRAY+0,0x4 # set "disconnected" bit 719 jmp p_mesgin_done 720 721# Save data pointers message? Copy working values into the SCB, 722# usually in preparation for a disconnect. 723# 724p_mesgin3: 725 cmp A,2 jne p_mesgin4 # save data pointers code? 726 727 call sg_ram2scb 728 jmp p_mesgin_done 729 730# Restore pointers message? Data pointers are recopied from the 731# SCB anyway at the start of any DMA operation, so the only thing 732# to copy is the scatter-gather values. 733# 734p_mesgin4: 735 cmp A,3 jne p_mesgin5 # restore pointers code? 736 737 call sg_scb2ram 738 jmp p_mesgin_done 739 740# Identify message? For a reconnecting target, this tells us the lun 741# that the reconnection is for - find the correct SCB and switch to it, 742# clearing the "disconnected" bit so we don't "find" it by accident later. 743# 744p_mesgin5: 745 test A,0x80 jz p_mesgin6 # identify message? 746 747 test A,0x78 jnz p_mesginN # !DiscPriv|!LUNTAR|!Reserved 748 749 and A,0x07 # lun in lower three bits 750 or SAVED_TCL,A,SELID 751 and SAVED_TCL,0xf7 752 and A,0x08,SBLKCTL # B Channel?? 753 or SAVED_TCL,A 754 call inb_last # Ack 755 756# Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. 757# If we get one, we use the tag returned to switch to the proper 758# SCB. Otherwise, we just use the findSCB method. 759p_mesgin5_loop: 760 test SSTAT1,0x08 jnz use_findSCB # BUSFREE 761 test SSTAT1,0x01 jz p_mesgin5_loop # REQINIT 762 and A,0xe0,SCSISIGI # CDI|IOI|MSGI 763 cmp A,0xe0 jne use_findSCB # Still p_mesgin? 764 mvi A call inb_first 765 cmp A,0x20 je get_tag # Simple Tag message? 766use_findSCB: 767 mov ALLZEROS call findSCB # Have to search 768 769# If a active message is present after calling findSCB, then either it 770# or the driver is trying to abort the command. Either way, something 771# untoward has happened and we should just leave it alone. 772# 773setup_SCB: 774 and SCBARRAY+0,0xfb # clear disconnect bit in SCB 775 or FLAGS,0xc0 # make note of IDENTIFY 776 777 call sg_scb2ram # implied restore pointers 778 # required on reselect 779 jmp ITloop 780 781get_tag: 782 mvi A call inb_next 783 test A,0xf0 jnz abort_tag # Tag in range? 784 mov SCBPTR,A 785 mov A,SAVED_TCL 786 cmp SCBARRAY+1,A jne abort_tag 787 test SCBARRAY+0,TAG_ENB jz abort_tag 788 call inb_last # ACK 789 jmp setup_SCB 790 791# Message reject? Let the kernel driver handle this. If we have an 792# outstanding WDTR or SDTR negotiation, assume that it's a response from 793# the target selecting 8bit or asynchronous transfer, otherwise just ignore 794# it since we have no clue what it pertains to. 795# 796p_mesgin6: 797 cmp A,7 jne p_mesgin7 # message reject code? 798 799 mvi INTSTAT, MSG_REJECT 800 jmp p_mesgin_done 801 802# [ ADD MORE MESSAGE HANDLING HERE ] 803# 804p_mesgin7: 805 806# We have no idea what this message in is, and there's no way 807# to pass it up to the kernel, so we issue a message reject and 808# hope for the best. Since we're now using manual PIO mode to 809# read in the message, there should no longer be a race condition 810# present when we assert ATN. In any case, rejection should be a 811# rare occurrence - signal the driver when it happens. 812# 813p_mesginN: 814 or SINDEX,0x10,SIGSTATE # turn on ATNO 815 call scsisig 816 mvi INTSTAT,SEND_REJECT # let driver know 817 818 mvi 0x7 call mk_mesg # MESSAGE REJECT message 819 820p_mesgin_done: 821 call inb_last # ack & turn auto PIO back on 822 jmp ITloop 823 824abort_tag: 825 or SINDEX,0x10,SIGSTATE # turn on ATNO 826 call scsisig 827 mvi INTSTAT,ABORT_TAG # let driver know 828 mvi 0xd call mk_mesg # ABORT TAG message 829 jmp p_mesgin_done 830 831# Bus free phase. It might be useful to interrupt the device 832# driver if we aren't expecting this. For now, make sure that 833# ATN isn't being asserted and look for a new command. 834# 835p_busfree: 836 mvi CLRSINT1,0x40 # CLRATNO 837 clr SIGSTATE 838 jmp start 839 840# Instead of a generic bcopy routine that requires an argument, we unroll 841# the two cases that are actually used, and call them explicitly. This 842# not only reduces the overhead of doing a bcopy by 2/3rds, but ends up 843# saving space in the program since you don't have to put the argument 844# into the accumulator before the call. Both functions expect DINDEX to 845# contain the destination address and SINDEX to contain the source 846# address. 847bcopy_3: 848 mov DINDIR,SINDIR 849 mov DINDIR,SINDIR 850 mov DINDIR,SINDIR ret 851 852bcopy_4: 853 mov DINDIR,SINDIR 854 mov DINDIR,SINDIR 855 mov DINDIR,SINDIR 856 mov DINDIR,SINDIR ret 857 858bcopy_3_dfdat: 859 mov DINDIR,DFDAT 860 mov DINDIR,DFDAT 861 mov DINDIR,DFDAT ret 862 863bcopy_4_dfdat: 864 mov DINDIR,DFDAT 865 mov DINDIR,DFDAT 866 mov DINDIR,DFDAT 867 mov DINDIR,DFDAT ret 868 869# Locking the driver out, build a one-byte message passed in SINDEX 870# if there is no active message already. SINDEX is returned intact. 871# 872mk_mesg: 873 mvi SEQCTL,0x50 # PAUSEDIS|FASTMODE 874 test FLAGS,ACTIVE_MSG jnz mk_mesg1 # active message? 875 876 or FLAGS,ACTIVE_MSG # if not, there is now 877 mvi MSG_LEN,1 # length = 1 878 mov MSG_START+0,SINDEX # 1-byte message 879 880mk_mesg1: 881 mvi SEQCTL,0x10 ret # !PAUSEDIS|FASTMODE 882 883# Input byte in Automatic PIO mode. The address to store the byte 884# in should be in SINDEX. DINDEX will be used by this routine. 885# 886inb: 887 test SSTAT0,0x2 jz inb # SPIORDY 888 mov DINDEX,SINDEX 889 call one_stcnt # xfer one byte 890 mov DINDIR,SCSIDATL 891inb1: 892 test SSTAT0,0x4 jz inb1 # SDONE - wait to "finish" 893 ret 894 895# Carefully read data in Automatic PIO mode. I first tried this using 896# Manual PIO mode, but it gave me continual underrun errors, probably 897# indicating that I did something wrong, but I feel more secure leaving 898# Automatic PIO on all the time. 899# 900# According to Adaptec's documentation, an ACK is not sent on input from 901# the target until SCSIDATL is read from. So we wait until SCSIDATL is 902# latched (the usual way), then read the data byte directly off the bus 903# using SCSIBUSL. When we have pulled the ATN line, or we just want to 904# acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI 905# spec guarantees that the target will hold the data byte on the bus until 906# we send our ACK. 907# 908# The assumption here is that these are called in a particular sequence, 909# and that REQ is already set when inb_first is called. inb_{first,next} 910# use the same calling convention as inb. 911# 912inb_first: 913 mov DINDEX,SINDEX 914 mov DINDIR,SCSIBUSL ret # read byte directly from bus 915 916inb_next: 917 mov DINDEX,SINDEX # save SINDEX 918 919 call one_stcnt # xfer one byte 920 mov NONE,SCSIDATL # dummy read from latch to ACK 921inb_next1: 922 test SSTAT0,0x4 jz inb_next1 # SDONE 923inb_next2: 924 test SSTAT0,0x2 jz inb_next2 # SPIORDY - wait for next byte 925 mov DINDIR,SCSIBUSL ret # read byte directly from bus 926 927inb_last: 928 call one_stcnt # ACK with dummy read 929 mov NONE,SCSIDATL 930inb_last1: 931 test SSTAT0,0x4 jz inb_last1 # wait for completion 932 ret 933 934# Output byte in Automatic PIO mode. The byte to output should be 935# in SINDEX. If DROPATN's high bit is set, then ATN will be dropped 936# before the byte is output. 937# 938outb: 939 test SSTAT0,0x2 jz outb # SPIORDY 940 call one_stcnt # xfer one byte 941 942 test DROPATN,0x80 jz outb1 943 mvi CLRSINT1,0x40 # CLRATNO 944 clr DROPATN 945outb1: 946 mov SCSIDATL,SINDEX 947outb2: 948 test SSTAT0,0x4 jz outb2 # SDONE 949 ret 950 951# Write the value "1" into the STCNT registers, for Automatic PIO 952# transfers. 953# 954one_stcnt: 955 clr STCNT+2 956 clr STCNT+1 957 mvi STCNT+0,1 ret 958 959# DMA data transfer. HADDR and HCNT must be loaded first, and 960# SINDEX should contain the value to load DFCNTRL with - 0x3d for 961# host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared 962# during initialization. 963# 964dma: 965 mov DFCNTRL,SINDEX 966dma1: 967dma2: 968 test SSTAT0,0x1 jnz dma3 # DMADONE 969 test SSTAT1,0x10 jz dma1 # PHASEMIS, ie. underrun 970 971# We will be "done" DMAing when the transfer count goes to zero, or 972# the target changes the phase (in light of this, it makes sense that 973# the DMA circuitry doesn't ACK when PHASEMIS is active). If we are 974# doing a SCSI->Host transfer, the data FIFO should be flushed auto- 975# magically on STCNT=0 or a phase change, so just wait for FIFO empty 976# status. 977# 978dma3: 979 test SINDEX,0x4 jnz dma5 # DIRECTION 980dma4: 981 test DFSTATUS,0x1 jz dma4 # !FIFOEMP 982 983# Now shut the DMA enables off, and copy STCNT (ie. the underrun 984# amount, if any) to the SCB registers; SG_COUNT will get copied to 985# the SCB's residual S/G count field after sg_advance is called. Make 986# sure that the DMA enables are actually off first lest we get an ILLSADDR. 987# 988dma5: 989 clr DFCNTRL # disable DMA 990dma6: 991 test DFCNTRL,0x38 jnz dma6 # SCSIENACK|SDMAENACK|HDMAENACK 992 993 mvi DINDEX,SCBARRAY+15 994 mvi STCNT call bcopy_3 995 996 ret 997 998dma_finish: 999 test DFSTATUS,0x8 jz dma_finish # HDONE 1000 1001 clr DFCNTRL # disable DMA 1002dma_finish2: 1003 test DFCNTRL,0x8 jnz dma_finish2 # HDMAENACK 1004 ret 1005 1006# Common SCSI initialization for selection and reselection. Expects 1007# the target SCSI ID to be in the upper four bits of SINDEX, and A's 1008# contents are stomped on return. 1009# 1010initialize: 1011 and SINDEX,0xf0 # Get target ID 1012 and A,0x0f,SCSIID 1013 or SINDEX,A 1014 mov SCSIID,SINDEX 1015 1016# Esundry initialization. 1017# 1018 clr DROPATN 1019 clr SIGSTATE 1020 1021# Turn on Automatic PIO mode now, before we expect to see a REQ 1022# from the target. It shouldn't hurt anything to leave it on. Set 1023# CLRCHN here before the target has entered a data transfer mode - 1024# with synchronous SCSI, if you do it later, you blow away some 1025# data in the SCSI FIFO that the target has already sent to you. 1026# 1027 mvi SXFRCTL0,0x8a # DFON|SPIOEN|CLRCHN 1028 1029# Initialize scatter-gather pointers by setting up the working copy 1030# in scratch RAM. 1031# 1032 call sg_scb2ram 1033 1034# Initialize SCSIRATE with the appropriate value for this target. 1035# 1036 call ndx_dtr 1037 mov SCSIRATE,SINDIR ret 1038 1039# Assert that if we've been reselected, then we've seen an IDENTIFY 1040# message. 1041# 1042assert: 1043 test FLAGS,RESELECTED jz return # reselected? 1044 test FLAGS,IDENTIFY_SEEN jnz return # seen IDENTIFY? 1045 1046 mvi INTSTAT,NO_IDENT ret # no - cause a kernel panic 1047 1048# Find out if disconnection is ok from the information the BIOS has left 1049# us. The tcl from SCBARRAY+1 should be in SINDEX; A will 1050# contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok) 1051# on exit. 1052# 1053# To allow for wide or twin busses, we check the upper bit of the target ID 1054# and the channel ID and look at the appropriate disconnect register. 1055# 1056disconnect: 1057 and FUNCTION1,0x70,SINDEX # strip off extra just in case 1058 mov A,FUNCTION1 1059 test SINDEX, 0x88 jz disconnect_a 1060 1061 test DISC_DSB_B,A jz disconnect1 # bit nonzero if DISabled 1062 clr A ret 1063 1064disconnect_a: 1065 test DISC_DSB_A,A jz disconnect1 # bit nonzero if DISabled 1066 clr A ret 1067 1068disconnect1: 1069 mvi A,0x40 ret 1070 1071# Locate the SCB matching the target ID/channel/lun in SAVED_TCL and switch 1072# the SCB to it. Have the kernel print a warning message if it can't be 1073# found, and generate an ABORT message to the target. SINDEX should be 1074# cleared on call. 1075# 1076findSCB: 1077 mov A,SAVED_TCL 1078 mov SCBPTR,SINDEX # switch to new SCB 1079 cmp SCBARRAY+1,A jne findSCB1 # target ID/channel/lun match? 1080 test SCBARRAY+0,0x4 jz findSCB1 # should be disconnected 1081 ret 1082 1083findSCB1: 1084 inc SINDEX 1085 mov A,SCBCOUNT 1086 cmp SINDEX,A jne findSCB 1087 1088 mvi INTSTAT,NO_MATCH # not found - signal kernel 1089 mvi 0x6 call mk_mesg # ABORT message 1090 1091 or SINDEX,0x10,SIGSTATE # assert ATNO 1092 call scsisig 1093 ret 1094 1095# Make a working copy of the scatter-gather parameters in the SCB. 1096# 1097sg_scb2ram: 1098 mov SG_COUNT,SCBARRAY+2 1099 1100 mvi DINDEX,SG_NEXT 1101 mvi SCBARRAY+3 call bcopy_4 1102 1103 mvi SG_NOLOAD,0x80 1104 test SCBARRAY+0,0x10 jnz return # don't reload s/g? 1105 clr SG_NOLOAD ret 1106 1107# Copying RAM values back to SCB, for Save Data Pointers message. 1108# 1109sg_ram2scb: 1110 mov SCBARRAY+2,SG_COUNT 1111 1112 mvi DINDEX,SCBARRAY+3 1113 mvi SG_NEXT call bcopy_4 1114 1115 and SCBARRAY+0,0xef,SCBARRAY+0 1116 test SG_NOLOAD,0x80 jz return # reload s/g? 1117 or SCBARRAY+0,SG_LOAD ret 1118 1119# Load a struct scatter if needed and set up the data address and 1120# length. If the working value of the SG count is nonzero, then 1121# we need to load a new set of values. 1122# 1123# This, like the above DMA, assumes a little-endian host data storage. 1124# 1125sg_load: 1126 test SG_COUNT,0xff jz return # SG being used? 1127 test SG_NOLOAD,0x80 jnz return # don't reload s/g? 1128 1129 clr HCNT+2 1130 clr HCNT+1 1131 mvi HCNT+0,SG_SIZEOF 1132 1133 mvi DINDEX,HADDR 1134 mvi SG_NEXT call bcopy_4 1135 1136 mvi DFCNTRL,0xd # HDMAEN|DIRECTION|FIFORESET 1137 1138# Wait for DMA from host memory to data FIFO to complete, then disable 1139# DMA and wait for it to acknowledge that it's off. 1140# 1141 1142 call dma_finish 1143 1144# Copy data from FIFO into SCB data pointer and data count. This assumes 1145# that the struct scatterlist has this structure (this and sizeof(struct 1146# scatterlist) == 12 are asserted in aic7xxx.c): 1147# 1148# struct scatterlist { 1149# char *address; /* four bytes, little-endian order */ 1150# ... /* four bytes, ignored */ 1151# unsigned short length; /* two bytes, little-endian order */ 1152# } 1153# 1154 1155# Not in FreeBSD. the scatter list entry is only 8 bytes. 1156# 1157# struct ahc_dma_seg { 1158# physaddr addr; /* four bytes, little-endian order */ 1159# long len; /* four bytes, little endian order */ 1160# }; 1161# 1162 1163 mvi DINDEX, SCBARRAY+19 1164 call bcopy_4_dfdat 1165 1166# For Linux, we must throw away four bytes since there is a 32bit gap 1167# in the middle of a struct scatterlist 1168# mov NONE,DFDAT 1169# mov NONE,DFDAT 1170# mov NONE,DFDAT 1171# mov NONE,DFDAT 1172 1173 call bcopy_3_dfdat #Only support 24 bit length. 1174 ret 1175 1176# Advance the scatter-gather pointers only IF NEEDED. If SG is enabled, 1177# and the SCSI transfer count is zero (note that this should be called 1178# right after a DMA finishes), then move the working copies of the SG 1179# pointer/length along. If the SCSI transfer count is not zero, then 1180# presumably the target is disconnecting - do not reload the SG values 1181# next time. 1182# 1183sg_advance: 1184 test SG_COUNT,0xff jz return # s/g enabled? 1185 1186 test STCNT+0,0xff jnz sg_advance1 # SCSI transfer count nonzero? 1187 test STCNT+1,0xff jnz sg_advance1 1188 test STCNT+2,0xff jnz sg_advance1 1189 1190 clr SG_NOLOAD # reload s/g next time 1191 dec SG_COUNT # one less segment to go 1192 1193 clr A # add sizeof(struct scatter) 1194 add SG_NEXT+0,SG_SIZEOF,SG_NEXT+0 1195 adc SG_NEXT+1,A,SG_NEXT+1 1196 adc SG_NEXT+2,A,SG_NEXT+2 1197 adc SG_NEXT+3,A,SG_NEXT+3 ret 1198 1199sg_advance1: 1200 mvi SG_NOLOAD,0x80 ret # don't reload s/g next time 1201 1202# Add the array base SYNCNEG to the target offset (the target address 1203# is in SCSIID), and return the result in SINDEX. The accumulator 1204# contains the 3->8 decoding of the target ID on return. 1205# 1206ndx_dtr: 1207 shr A,SCSIID,4 1208 test SBLKCTL,0x08 jz ndx_dtr_2 1209 or A,0x08 # Channel B entries add 8 1210ndx_dtr_2: 1211 add SINDEX,SYNCNEG,A 1212 1213 and FUNCTION1,0x70,SCSIID # 3-bit target address decode 1214 mov A,FUNCTION1 ret 1215 1216# If we need to negotiate transfer parameters, build the WDTR or SDTR message 1217# starting at the address passed in SINDEX. DINDEX is modified on return. 1218# The SCSI-II spec requires that Wide negotiation occur first and you can 1219# only negotiat one or the other at a time otherwise in the event of a message 1220# reject, you wouldn't be able to tell which message was the culpret. 1221# 1222mk_dtr: 1223 test SCBARRAY+0,0xc0 jz return # NEEDWDTR|NEEDSDTR 1224 test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit 1225 or FLAGS, MAX_SYNC # Force an offset of 15 1226 1227mk_sdtr: 1228 mvi DINDIR,1 # extended message 1229 mvi DINDIR,3 # extended message length = 3 1230 mvi DINDIR,1 # SDTR code 1231 call sdtr_to_rate 1232 mov DINDIR,RETURN_1 # REQ/ACK transfer period 1233 test FLAGS, MAX_SYNC jnz mk_sdtr_max_sync 1234 and DINDIR,0xf,SINDIR # Sync Offset 1235 1236mk_sdtr_done: 1237 add MSG_LEN,-MSG_START+0,DINDEX ret # update message length 1238 1239mk_sdtr_max_sync: 1240# We're initiating sync negotiation, so request the max offset we can (15) 1241 mvi DINDIR, 0x0f 1242 xor FLAGS, MAX_SYNC 1243 jmp mk_sdtr_done 1244 1245mk_wdtr_16bit: 1246 mvi ARG_1,BUS_16_BIT 1247mk_wdtr: 1248 mvi DINDIR,1 # extended message 1249 mvi DINDIR,2 # extended message length = 2 1250 mvi DINDIR,3 # WDTR code 1251 mov DINDIR,ARG_1 # bus width 1252 1253 add MSG_LEN,-MSG_START+0,DINDEX ret # update message length 1254 1255# Set SCSI bus control signal state. This also saves the last-written 1256# value into a location where the higher-level driver can read it - if 1257# it has to send an ABORT or RESET message, then it needs to know this 1258# so it can assert ATN without upsetting SCSISIGO. The new value is 1259# expected in SINDEX. Change the actual state last to avoid contention 1260# from the driver. 1261# 1262scsisig: 1263 mov SIGSTATE,SINDEX 1264 mov SCSISIGO,SINDEX ret 1265 1266sdtr_to_rate: 1267 call ndx_dtr # index scratch space for target 1268 shr A,SINDIR,0x4 1269 dec SINDEX #Preserve SINDEX 1270 and A,0x7 1271 clr RETURN_1 1272sdtr_to_rate_loop: 1273 test A,0x0f jz sdtr_to_rate_done 1274 add RETURN_1,0x18 1275 dec A 1276 jmp sdtr_to_rate_loop 1277sdtr_to_rate_done: 1278 shr RETURN_1,0x2 1279 add RETURN_1,0x18 ret 1280 1281return: 1282 ret 1283