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