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