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