aic79xx.seq:
Convert the COMPLETE_DMA_SCB list to an "stailq". This allows us to
safely keep the SCB that is currently being DMA'ed back the host on
the head of the list while processing completions off of the bus. The
newly completed SCBs are appended to the tail of the queue. In the
past, we just dequeued the SCB that was in flight from the list, but
this could result in a lost completion should the host perform certain
types of error recovery that must cancel all in-flight SCB DMA operations.
Switch from using a 16bit completion entry, holding just the tag and the
completion valid bit, to a 64bit completion entry that also contains a
"status packet valid" indicator. This solves two problems:
o The SCB DMA engine on at least Rev B. silicon does not properly deal
with a PCI disconnect that occurs at a non-64bit aligned offset in the
chips "source buffer". When the transfer is resumed, the DMA engine
continues at the correct offset, but may wrap to the head of the buffer
causing duplicate completions to be reported to the host. By using a
completion buffer in host memory that is 64bit aligned and using 64bit
completion entries, such disconnects should only occur at aligned addresses.
This assumes that the host bridge will only disconnect on cache-line
boundaries and that cache-lines are multpiles of 64bits.
o By embedding the status information in the completion entry we can avoid
an extra memory reference to the HSCB for commands that complete without
error.
Use the comparison of a "host freeze count" and a "sequencer freeze count"
to allow the host to process most SCBs that complete with non-zero status
without having to clear critical sections. Instead the host can just pause the
sequencer, performs any necessary cleanup in the waiting for selection list,
increments its freeze count on the controller, and unpauses. This is only
possible because the sequencer defers completions of SCBs with bad status
until after all pending selections have completed. The sequencer then avoids
referencing any data structures the host may touch during completion of the
SCB until the freeze counts match.
aic79xx.c:
Change the strategy for allocating our sentinal HSCB for the QINFIFO. In
the past, this allocation was tacked onto the QOUTFIFO allocation. Now that
the qoutfifo has grown to accomodate larger completion entries, the old
approach will result in a 64byte allocation that costs an extra page of
coherent memory. We now do this extra allocation via ahd_alloc_scbs()
where the "unused space" can be used to allocate "normal" HSCBs.
In our packetized busfree handler, use the ENSELO bit to differentiate
between packetized and non-packetized unexpected busfree events that
occur just after selection, but before the sequencer has had the oportunity
to service the selection.
When cleaning out the waiting for selection list, use the SCSI mode
instead of the command channel mode. The SCB pointer in the command
channel mode may be referenced by the SCB dma engine even while the
sequencer is paused, whereas the SCSI mode SCB pointer is only accessed
by the sequencer.
Print the "complete on qfreeze" sequencer SCB completion list in
ahd_dump_card_state(). This list holds all SCB completions that are deferred
until a pending select-out qfreeze event has taken effect.
aic79xx.h:
Add definitions and structures to handle the new SCB completion scheme.
Add a controller flag that indicates if the controller is in HostRAID
mode.
aic79xx.reg:
Remove macros used for toggling from one data fifo mode to the other.
They have not been in use for some time.
Add scratch ram fields for our new qfreeze count scheme, converting
the complete dma list into an "stailq", and providing for the "complete
on qfreeze" SCB completion list. Some other fields were moved to retain
proper field alignment (alignment >= field size in bytes).
aic79xx.seq:
Add code to our idle loop to:
o Process deferred completions once a qfreeze event has taken full
effect.
o Thaw the queue once the sequencer and host qfreeze counts match.
Generate 64bit completion entries passing the SCB_SGPTR field as the
"good status" indicator. The first bit in this field is only set if
we have a valid status packet to send to the host.
Convert the COMPLETE_DMA_SCB list to an "stailq".
When using "setjmp" to register an idle loop handler, do not combine
the "ret" with the block move to pop the stack address in the same
instruction. At least on the A, this results in a return to the setjmp
caller, not to the new address at the top of the stack. Since we want
the latter (we want the newly registered handler to only be invoked from
the idle loop), we must use a separate ret instruction.
Add a few missing critical sections.
Close a race condition that can occur on Rev A. silicon. If both FIFOs
happen to be allocated before the sequencer has a chance to service the
FIFO that was allocated first, we must take special care to service the
FIFO that is not active on the SCSI bus first. This guarantees that a
FIFO will be freed to handle any snapshot requests for the FIFO that is
still on the bus. Chosing the incorrect FIFO will result in deadlock.
Update comments.
aic79xx_inline.h
Correct the offset calculation for the syncing of our qoutfifo.
Update ahd_check_cmdcmpltqueues() for the larger completion entries.
aic79xx_pci.c:
Attach to HostRAID controllers by default. In the future I may add a
sysctl to modify the behavior, but since FreeBSD does not have any
HostRAID drivers, failing to attach just results in more email and
bug reports for the author.
MFC After: 1week
to each other.
Correct the recovery thread's loop so that it
will terminate properly on shutdown. We also
clear the recovery_thread proc pointer so that
any additional calls to aic_terminate_recovery_thread()
will not attempt to kill a thread that doesn't
exist. Lastly, code the loop so that termination
will still be successfull even if the termination
request occurs just prior to us entering the loop
or while the recovery thread is off recovering
commands.
that would cause an infinite loop any time we
manually flush the good status FIFO. Also make
our loop delay unconditional to ensure we don't
miss any FIFO allocations by the hardware.
ahc_pci.c:
ahd_pci.c:
aic7xxx.c:
aic79xx.c:
aic_osm_lib.c:
aic_osm_lib.h:
Use common OSM routines from aic_osm_lib for bus dma operations,
delay routines, accessing CCBs, byte swapping, etc.
aic7xxx_pci.c:
Provide a better description for the 2915/30LP on attach.
aic7xxx.c:
aic79xx.c:
aic7770.c:
aic79xx_pci.c:
aic7xxx_pci.c:
aic7xxx_93cx6.c:
Move FBSDID behind an ifdef so that these core files will
still compile under other OSes.
aic79xx.h:
aic79xx_pci.c:
aic79xx.seq:
To speed up non-packetized CDB delivery in Rev B, all CDB
acks are "released" to the output sync as soon as the
command phase starts. There is only one problem with this
approach. If the target changes phase before all data are
sent, we have left over acks that can go out on the bus in
a data phase. Due to other chip contraints, this only
happens if the target goes to data-in, but if the acks go
out before we can test SDONE, we'll think that the transfer
has completed successfully. Work around this by taking
advantage of the 400ns or 800ns dead time between command
phase and the REQ of the new phase. If the transfer has
completed successfully, SCSIEN should fall *long* before we
see a phase change. We thus treat any phasemiss that
occurs before SCSIEN falls as an incomplete transfer.
aic79xx.h:
Add the AHD_FAST_CDB_DELIVERY feature.
aic79xx_pci.c:
Set AHD_FAST_CDB_DELIVERY for all Rev. B parts.
aic79xx.seq:
Test for PHASEMIS in the command phase for
all AHD_FAST_CDB_DELIVERY controlelrs.
ahd_pci.c:
ahc_pci.c:
aic7xxx.h:
aic79xx.h:
Move definition of controller BAR offsets to core header files.
aic7xxx.c:
aic79xx.c:
In the softc free routine, leave removal of a softc from the
global list of softcs to the OSM (the caller of this routine).
This allows us to avoid holding the softc list_lock during device
destruction where we may have to sleep waiting for our recovery
thread to halt.
ahc_pci.c:
Use ahc_pci_test_register access to validate I/O mapped in
addition to the tests already performed for memory mapped
access.
Remove unused ahc_power_state_change() function. The PCI
layer in both 4.X and 5.X now offer this functionality.
ahd_pci.c:
Remove reduntant definition of controller BAR offsets. These
are also defined in aic79xx.h.
Remove unused ahd_power_state_change() function. The PCI
layer in both 4.X and 5.X now offer this functionality.
aic7xxx.c:
aic79xx.c:
aic79xx.h:
aic7xxx.h:
aic7xxx_osm.c:
aic79xx_osm.c:
Move timeout handling to the driver cores. In the case
of the aic79xx driver, the algorithm has been enhanced
to try target resets before performing a bus reset. For
the aic7xxx driver, the algorithm is unchanged. Although
the drivers do not currently sleep during recovery (recovery
is timeout driven), the cores do expect all processing to
be performed via a recovery thread. Our timeout handlers
are now little stubs that wakeup the recovery thread.
aic79xx.c:
aic79xx.h:
aic79xx_inline.h:
Change shared_data allocation to use a map_node so
that the sentinel hscb can use this map node in
ahd_swap_with_next_hscb. This routine now swaps
the hscb_map pointer in additon to the hscb
contents so that any sync operations occur on
the correct map.
physaddr -> busaddr
Pointed out by: Jason Thorpe <thorpej@wasabisystems.com>
aic79xx.c:
Make more use of the in/out/w/l/q macros for accessing
byte registers in the chip.
Correct some issues in the ahd_flush_qoutfifo() routine.
o Run the qoutfifo only once the command channel
DMA engine has been halted. This closes a window
where we might have missed some entries.
o Change ahd_run_data_fifo() to not loop to completion.
If we happen to start on the wrong FIFO and the other
FIFO has a snapshot savepointers, we might deadlock.
This required our delay between FIFO tests to be
moved to the ahd_flush_qoutfifo() routine.
o Update/add comments.
o Remove spurious test for COMPLETE_DMA list being empty
when completing transactions from the GSFIFO with
residuals. The SCB must be put on the COMPLETE_DMA
scb list unconditionally.
o When halting command channel DMA activity, we must
disable the DMA channel in all cases but an update
of the QOUTFIFO. The latter case is required so
that the sequencer will update its position in the
QOUTFIFO. Previously, we left the channel enabled
for all "push" DMAs. This left us vulnerable to
the sequencer handling an SCB push long after that
SCB was already processed manually by this routine.
o Correct the polarity of tests involving
ahd_scb_active_in_fifo(). This routine returns
non-zero for true.
Return to processing bad status completions through
the qoutfifo. This reduces the time that the sequencer
is kept paused when handling transactions with bad
status or underruns.
When waiting for the controller to quiece selections,
add a delay to our loop. Otherwise we may fail to wait
long enough for the sequencer to comply.
On H2A4 hardware, use the slow slewrate for non-paced
transfers. This mirrors what the Adaptec Windows
drivers do.
On the Rev B. only slow down the CRC timing for
older U160 devices that might need the slower timing.
We define "older" as devices that do not support
packetized protocol.
Wait up to 5000 * 5us for the SEEPROM to become unbusy.
Write ops seem to take much longer than read ops.
aic79xx.seq:
For controllers with the FAINT_LED bug, turn the diagnostic
led feature on during selection and reselection. This covers
the non-packetized case. The LED will be disabled for
non-packetized transfers once we return to the top level idle
loop. Add more comments about the busy LED workaround.
Extend a critical section around the entire
command channel idle loop process. Previously
the portion of this handler that directly manipulated
the linked list of completed SCBs was not protected.
This is the likely cause of the recent reports of
commands being completed twice by the driver.
Extend critical sections across the test for,
and the longjump to, longjump routines. This
prevents the firmware from trying to jump to
a longjmp handler that was just cleared by the
host.
Improve the locations of several critical section
begin and end points. Typically these changes
remove instructions that did not need to be
inside a critical section.
Close the "busfree after selection, but before busfree
interrupts can be enabled" race to just a single sequencer
instruction. We now test the BSY line explicitly before
clearing the busfree status and enabling the busfree
interrupt.
Close a race condition in the processing of HS_MAILBOX
updates. We now clear the "updated" status before the
copy. This ensures that we don't accidentally clear
the status incorrectly when the host sneaks in an update
just after our last copy, but before we clear the status.
This race has never been observed.
Don't re-enable SCSIEN if we lose the race to disable SCSIEN
in our interrupt handler's workaround for the RevA data-valid
too early issue.
aic79xx_inline.h:
Add comments indicating that the order in which bytes are
read or written in ahd_inw and ahd_outw is important. This
allows us to use these inlines when accessing registers with
side-effects.
aic79xx_pci.c:
The 29320 and the 29320B are 7902 not 7901 based products.
Correct the driver banner.
aic7xxx.h:
Enable the use of the auto-access pause feature
on the aic7870 and aic7880. It was disabled due
to an oversight.
aic7xxx.reg:
Move TARG_IMMEDIATE_SCB to alias LAST_MSG to
avoid leaving garbage in MWI_RESIDUAL. This
prevents spurious overflows whn operating target
mode on controllers that require the MWI_RESIDUAL
work-around.
aic7xxx.seq:
AHC_TMODE_WIDEODD_BUG is a bug, not a softc flag.
Reference the correct softc field when testing
for its presence.
Set the NOT_IDENTIFIED and NO_CDB_SENT bits
in SEQ_FLAGS to indicate that the nexus is
invalid in await busfree.
aic7xxx_93cx6.c:
Add support for the C56/C66 versions of the EWEN and EWDS
commands.
aic7xxx.c:
aic7xxx_pci.c:
Move test for the validity of left over BIOS data
to ahc_test_register_access(). This guarantees that
any left over CHIPRST value is not clobbered by our
register access test and lost to the test that was
in ahc_reset.
this problem put these lines back in. While they should be
unnecessary, they appear to be sometimes necessary.
Reviewed in concept: dfr
Approved by: re (scottl@)
to the pci attachment. Cardbus is a derived class of pci so all pci
drivers are automatically available for matching against cardbus devices.
Reviewed by: imp
aic7xxx_pci.c:
When performing our register test, be careful
to avoid resetting the chip when pausing the
controller. The test reads the HCNTRL register
and then writes it back with the PAUSE bit
explicitly set. If the last write to the controller
before our probe is to reset it, the CHIPRST
bit will still be set, so we must mask it off
before the PAUSE operation. On some chip versions,
we cannot access registers for a few 100us after
a reset, so this inadvertant reset was causing PCI
errors to occur on the read to check for paused
status.
Submitted by: gibbs
Add two new arguments to bus_dma_tag_create(): lockfunc and lockfuncarg.
Lockfunc allows a driver to provide a function for managing its locking
semantics while using busdma. At the moment, this is used for the
asynchronous busdma_swi and callback mechanism. Two lockfunc implementations
are provided: busdma_lock_mutex() performs standard mutex operations on the
mutex that is specified from lockfuncarg. dftl_lock() is a panic
implementation and is defaulted to when NULL, NULL are passed to
bus_dma_tag_create(). The only time that NULL, NULL should ever be used is
when the driver ensures that bus_dmamap_load() will not be deferred.
Drivers that do not provide their own locking can pass
busdma_lock_mutex,&Giant args in order to preserve the former behaviour.
sparc64 and powerpc do not provide real busdma_swi functions, so this is
largely a noop on those platforms. The busdma_swi on is64 is not properly
locked yet, so warnings will be emitted on this platform when busdma
callback deferrals happen.
If anyone gets panics or warnings from dflt_lock() being called, please
let me know right away.
Reviewed by: tmm, gibbs
have completed across the bus but not to the host before
processing of an exception condition (busfree, bus reset,
etc.). When flushing the controller of completed commands,
we also look for packetized commands that have completed
with good status and are stored in the "good status fifo".
The hardware will post to the good status fifo even if
data for that command is still active in a FIFO. In
one particular failure case, a command outstanding on the
bus reconnected, transferred data into a FIFO, and provided
good status while the host driver was processing an expected
busfree event (PPR message negotiation). This resulted in
an entry in the good status fifo that we completed, but
since the sequencer was paused, the data in the data FIFO
for this command had never been transferred to the host.
Once the busfree processing was complete, the sequencer
was unpaused, and the data completed its transfer to the
host. In some instances, the client for the data was notified
of the completion and attempted to view the data before
it arrived. This case only occurred during FreeBSD's
multi-target probe of the SCSI bus while some devices are
negotiating to go packetized and some devices are already
running in packetized.
The fix is to run and FIFOs active with a context in the
good status fifo to completion before completing the command
to the SCSI layer. This requies duplicating the FIFO rundown
operations in the host driver that would usually be handled
by the firmware, but there is no other alternative.
Don't blindly shutdown the SCB dma engine when restarting
the sequencer. We may be killing an operation that is
not supposed to be cancelled. The cases where we need to
shutdown these dma engines are already handled elsewhere in
the driver.
Fix a few more ahd_in?() -> ahd_in?_scbram() instances.
Add softc flag to indicate that we have seen at
least one selection since the last bus reset or
SE/LVD bus change.
aic79xx.c:
Fix a few style nits.
In ahd_update_pending_scbs(), only touch card registers
once we have found an SCB that needs to be updated.
This removes lots of clutter from PCI traces taken of
error recovery performed by the driver.
Short circuit the first selection iocell workaround handler
if we've run once since the last bus reset or iocell change.
This also removes clutter from PCI traces.
Note if completions are pending in the qoutfifo when we dump
card state.
Add a comment in ahd_clear_critical_sections() about
our need to leave ENBUSFREE set in SIMODE1 while single
stepping.
Re-arrange some delay loops so that we always perform
a read after any register write and before the delay.
This should make the delay loop more accurate.
When completing message processing for a packetized
commention, return the controller to a state where
invalid non-packetized phases will still cause protocol
violations. These are the same operations as those
performed in the clear_target_state routine in the
firmware.
Now that we have a chip with working ABORTPENDING
support (the 7901B), comment out the automatic use
of this feature until we can adequately test it.
The previous checkin updated the bug mask for the
7901B so this code was exercised.
When resetting the bus, perform an ahd_flush_device_writes()
call so that our reset assertion delay is acurately
timed from when the reset bit is written to the controller.
Remove an old comment that no longer applies.
Fix a jump in our unexpected non-packetized phase
handler to use an explicit lable. The old code
had a hardcoded jump offset that was off by one
instruction.
Add a 7901A specific feature definition.
aic79xx_pci.c:
Split out the general aic790X setup into it's own
setup handler that works on single and dual controllers.
Adjust all other PCI setup handlers to initialize the
chips basic features and type before calling the generic
handler.
Turn off a few Rev B workarounds that are not required
on the 7901B.
of the contents of the CCSCBCTL register into our
local varaible. The other bits are used in later tests.
This avoids a potential deadlock in ahd_run_qoutfifo()
if we happen to catch the DMA engine in just the right
state.
Devices below may experience a change in geometry.
* Due to a bug, aic(4) never used extended geometry. Changes all drives
>1G to now use extended translation.
* sbp(4) drives exactly 1 GB in size now no longer use extended geometry.
* umass(4) drives exactly 1 GB in size now no longer use extended geometry.
For all other controllers in this commit, this should be a no-op.
Looked over by: scottl
if it was already enabled. We don't want to set it
when it shouldn't be set, we just don't want to
inadvertantly turn it off. This should fix a recent
report of the aic7xxx driver repeatedly complaining of
"unexpected busfree while idle" in one configuration.
successfully mapping our registers. This
avoids the disabling of memory mapped I/O
just because some other driver probe happened
to touch our registers.
This drive delays going async after receiving a WDTR
message. We now send an SDTR message after a WDTR even
if our goal is to go async. This should work even for
confused devices.
If we get an unexpected busfree when attempting a WDTR
or SDTR, only set the goal negotiation parameters we were
trying to negotiate to off. This means that should a WDTR
message fail, we will still try an SDTR if our goal is
non-async.
Fix a few more places where we were looking at goal.period
instead of goal.offset for determining if we should be
negotiating sync. This should not have any impact on
our behavior, but the offset is more definitive and should
be used.
aic79xx.c:
aic79xx.h:
aic79xx_pci.c:
aic7xxx.c:
aic7xxx.h:
aic7xxx_pci.c:
Switch ah?_reset() to take an additional "reinit" argument.
Use this instead of init_level to determin if the chip
should be fully reinitialized after a chip reset. This
is required so that ah?_shutdown() can reset the chip
without side-effects.
aic79xx.c:
Implement ahd_suspend() and ahd_resume().
aic7xxx.c:
Change ahc_loadseq() to *not* restart the sequencer.
This brings the loadseq behavior in line with that
of the 7902 driver and also simplifies the init routine.
Correct the resume routine to enable interrupts and
restart the sequencer.
Use the special LUNLEN_SINGLE_LEVEL constant for
post Rev A4 hardware for single byte luns. Without
this change, Rev B hardware would place the single
byte of lun data in byte 0 of the lun structure when
it should be in byte 1. Since there are few if any
devices on the market that support multiple luns in
target mode, the corrupted lun field (which was only
corrupted for non-zero luns) wasn't hurting us.
Approved by: re (rwatson)
aic79xx.h:
aic79xx.reg:
Return the SCB_TAG field to 16byte alignment.
It seems that on some PCI systems, SCBs are not
transferred correctly to the controller with
the previous placement of the SCB_TAG field.
Approved by: re (rwatson)
BUS_DMASYNC_ definitions remain as before. The does not change the ABI,
and reverts the API to be a bit more compatible and flexible. This has
survived a full 'make universe'.
Approved by: re (bmah)
aic79xx.c:
In ahd_handle_ign_wide_residue():
o Use SCB_XFERLEN_ODD SCB field to determine transfer
"oddness" rather than the DATA_COUNT_ODD logic.
SCB_XFERLEN_ODD is toggled on every ignore wide
residue message so that multiple ignore wide residue
messages for the same transaction are properly supported.
o If the sg list has been exausted, the sequencer
doesn't bother to update the residual data count
since it is known to be zero. Perform the zeroing
manually before calculating the remaining data count.
o Use multibyte in/out macros instead of shifting/masking
by hand.
aic79xx_inline.h:
In ahd_setup_scb_common(), setup the SCB_XFERLEN_ODD field.
aic79xx.reg:
Use the SCB_TASK_ATTRIBUTE field as a bit field in the
non-packetized case. We currently only define one bit,
SCB_XFERLEN_ODD.
Remove the ODD_SEG bit field that was used to carry the odd
transfer length information through the SG cache. This
is obviated by SCB_XFERLEN_ODD field.
Remove the DATA_COUNT_ODD scratch ram byte that was used
dynamicaly compute data transfer oddness. This is obviated
by SCB_XFERLEN_ODD field.
aic79xx.seq:
Remove all updates to the DATA_COUNT_ODD scratch ram field.
Remove all uses of ODD_SEG. These two save quite a few
sequencer instructions.
Use SCB_XFERLEN_ODD to validate the end of transfer
ignore wide residue message case.
aic7xxx.c:
In ahc_handle_ign_wide_residue():
o Use SCB_XFERLEN_ODD SCB field to determine transfer
"oddness" rather than the DATA_COUNT_ODD logic.
SCB_XFERLEN_ODD is toggled on every ignore wide
residue message so that multiple ignore wide residue
messages for the same transaction are properly supported.
o If the sg list has been exausted, the sequencer
doesn't bother to update the residual data count
since it is known to be zero. Perform the zeroing
manually before calculating the remaining data count.
o Ensure that SG_LIST_NULL is cleared in the
residual sg pointer for "mid-transfer" ignore
wide residue cases.
o Use multibyte in/out macros instead of shifting/masking
by hand.
aic7xxx.h:
Modify the SCB_GET_LUN() macro to mask the lun hardware
SCB field with LID. This leaves two bits in the LUN
field that can be used for other purposes.
aic7xxx.reg:
Change LID to be 0x3F. This is the maximum supported
lun size for non-packetized SCSI. Map the top bit
of the lun to SCB_XFERLEN_ODD. The host must set
this bit whenever a transfer is an odd length.
Remove the ODD_SEG bit field that was used to carry the odd
transfer length information through the SG cache. This
is obviated by SCB_XFERLEN_ODD field.
Remove the DATA_COUNT_ODD scratch ram byte that was used
dynamicaly compute data transfer oddness. This is obviated
by SCB_XFERLEN_ODD field.
aic7xxx.seq:
Be more careful in our handling of the SCB_LUN field. It
must be masked with LID if only lun information is desired.
Remove all updates to the DATA_COUNT_ODD scratch ram field.
Remove all uses of ODD_SEG. These two save quite a few
sequencer instructions.
Use SCB_XFERLEN_ODD to validate the end of transfer
ignore wide residue message case.
aic7xxx_inline.h:
In ahc_queue_scb(), setup the SCB_XFERLEN_ODD field.
Approved by: RE
FAILDIS in the SEQCTL register, not the HCNTRL register.
aic7xxx.c:
Remeber SEQCTL settings in the "seqctl" field of our
softc. seqctl defaults to just having FASTMODE set,
but the bus attachments can override this.
aic7xxx.h:
Add the seqctl softc field.
aic7xxx_pci.c:
Update the seqctl softc field and manually update SEQCTL
when to many PCI errors occur
Approved by: RE
to be more efficient by having the sequencer copy the
single byte of valid lun data into the long lun field.
aic79xx.c:
Memset our hardware SCB to 0 so that untouched
fields don't confuse diagnostic output. With the
old method for handling the Rev A bug, if the long
lun field was not 0, this could result in bogus
lun information being sent to drives.
Use the same SCB transfer size for all chip types
now that the long lun is not DMA'ed to the chip.
aic79xx.seq:
Add code to copy lun information for Rev.A hardware.
aic79xx_inline.h:
Remove host update of the long_lun field on every
packetized command.
Sort IDs based on chip type.
Remove IROC IDs. We'll switch to using the IROC masks
if/when we want to start attaching to IROC controllers.
Approved by: RE
Switch to handling bad SCSI status as a sequencer interrupt
instead of having the kernel proccess these failures via
the completion queue. This is done because:
o The old scheme required us to pause the sequencer and clear
critical sections for each SCB. It seems that these pause
actions, if coincident with a sequencer FIFO interrupt, would
result in a FIFO interrupt getting lost or directing to the
wrong FIFO. This caused hangs when the driver was stressed
under high "queue full" loads.
o The completion code assumed that it was always called with
the sequencer running. This may not be the case in timeout
processing where completions occur manually via
ahd_pause_and_flushwork().
o With this scheme, the extra expense of clearing critical
sections is avoided since the sequencer will only self pause
once all pending selections have cleared and it is not in
a critical section.
aic79xx.c
Add code to handle the new BAD_SCB_STATUS sequencer
interrupt code. This just redirects the SCB through
the already existing ahd_complete_scb() code path.
Remove code in ahd_handle_scsi_status() that paused
the sequencer, made sure that no selections where
pending, and cleared critical sections. Bad
status SCBs are now only processed when all of these
conditions are true.
aic79xx.reg:
Add the BAD_SCB_STATUS sequencer interrupt code.
aic79xx.seq:
When completing an SCB upload to the host, if
we are doing this because the SCB contains non-zero
SCSI status, defer completing the SCB until there
are no pending selection events. When completing
these SCBs, use the new BAD_SCB_STATUS sequencer
interrupt. For all other uploaded SCBs (currently
only for underruns), the SCB is completed via the
normal done queue. Additionally, keep the SCB that
is currently being uploaded on the COMPLETE_DMA_SCB
list until the dma is completed, not just until the
DMA is started. This ensures that the DMA is restarted
properly should the host disable the DMA transfer for
some reason.
In our RevA workaround for Maxtor drives, guard against
the host pausing us while trying to pause I/O until the
first data-valid REQ by clearing the current snapshot
so that we can tell if the transfer has completed prior
to us noticing the REQINIT status.
In cfg4data_intr, shave off an instruction before getting
the data path running by adding an entrypoint to the
overrun handler to also increment the FIFO use count.
In the overrun handler, be sure to clear our LONGJMP
address in both exit paths.
Perform a few sequencer optimizations.
aic79xx.c:
Print the full path from the SCB when a packetized
status overrun occurs.
Remove references to LONGJMP_SCB which is being
removed from firmware usage.
Print the new SCB_FIFO_USE_COUNT field in the
per-SCB section of ahd_dump_card_state(). The
SCB_TAG field is now re-used by the sequencer,
so it no longer makes sense to reference this
field in the kernel driver.
aic79xx.h:
Re-arrange fields in the hardware SCB from largest
size type to smallest. This makes it easier to
move fields without changing field alignment.
The hardware scb tag field is now down near the
"spare" portion of the SCB to facilitate reuse
by the sequencer.
aic79xx.reg:
Remove LONGJMP_ADDR.
Rearrange SCB fields to match aic79xx.h.
Add SCB_FIFO_USE_COUNT as the first byte
of the SCB_TAG field.
aic79xx.seq:
Add a per-SCB "Fifos in use count" field and use
it to determine when it is safe (all data posted)
to deliver status back to the host. The old method
involved polling one or both FIFOs to verify that
the current task did not have pending data. This
makes running down the GSFIFO very cheap, so we
will empty the GSFIFO in one idle loop pass in
all cases.
Use this simplification of the completion process
to prune down the data FIFO teardown sequencer for
packetized transfers. Much more code is now shared
between the data residual and transfer complete cases.
Correct some issues in the packetized status handler.
It used to be possible to CLRCHN our FIFO before status
had fully transferred to the host. We also failed to
handle NONPACKREQ phases that could occur should a CRC
error occur during transmission of the status data packet.
Correct a few big endian issues:
aic79xx.c:
aic79xx_inline.h:
aic79xx_pci.c:
aic79xx_osm.c:
o Always get the SCB's tag via the SCB_GET_TAG acccessor
o Add missing use of byte swapping macros when touching
hscb fields.
o Don't double swap SEEPROM data when it is printed.
Correct a big-endian bug. We cannot assign a
o When assigning a 32bit LE variable to a 64bit LE
variable, we must be explict about how the words
of the 64bit LE variable are initialized. Cast to
(uint32_t*) to do this.
aic79xx.c:
In ahd_clear_critical_section(), hit CRLSCSIINT
after restoring the interrupt masks to avoid what
appears to be a glitch on SCSIINT. Any real SCSIINT
status will be persistent and will immidiately
reset SCSIINT. This clear should only get rid of
spurious SCSIINTs.
This glitch was the cause of the "Unexpected PKT busfree"
status that occurred under high queue full loads
Call ahd_fini_scbdata() after shutdown so that
any ahd_chip_init() routine that might access
SCB data will not access free'd memory.
Reset the bus on an IOERR since the chip doesn't
seem to reset to the new voltage level without
this.
Change offset calculation for scatter gather maps
so that the calculation is correct if an integral
multiple of sg lists does not fit in the allocation
size.
Adjust bus dma tag for data buffers based on 39BIT
addressing flag in our softc.
Use the QFREEZE count to simplify ahd_pause_and_flushworkd().
We can thus rely on the sequencer eventually clearing ENSELO.
In ahd_abort_scbs(), fix a bug that could potentially
corrupt sequencer state. The saved SCB was being
restored in the SCSI mode instead of the saved mode.
It turns out that the SCB did not need to be saved at all
as the scbptr is already restored by all subroutines
called during this function that modify that register.
aic79xx.c:
aic79xx.h:
aic79xx_pci.c:
Add support for parsing the seeprom vital product
data. The VPD data are currently unused.
aic79xx.h:
aic79xx.seq:
aic79xx_pci.c:
Add a firmware workaround to make the LED blink
brighter during packetized operations on the H2A.
aic79xx_inline.h:
The host does not use timer interrupts, so don't
gate our decision on whether or not to unpause
the sequencer on whether or not a timer interrupt
is pending.
aic7xxx.h:
Split out core chip initialization into ahc_chip_init().
This will allow us to reset the chip correctly at times
other than initial chip setup.
aic7770.c
aic7xxx_pci.c:
Flesh out bus chip init methods for our two
bus attachments and use these, in addition to
bus suspend/resume hooks to get the core in
better shape for handling these events.
When disabling PCI parity error checking, use FAILDIS.
Although the chip docs indicate that clearing PERRESPEN
should also work, it does not.
Auto-disable pci parity error checking after informing
the user of AHC_PCI_TARGET_PERR_THRESH number of parity
errors observed as a target.
aic7xxx.h:
aic7xxx_pci.c
aic7770.c
aic7xxx.c
Add the instruction_ram_size softc field.
Remove the now unused stack_size softc field.
Modify ahc_loadseq to return a failure code
and to actually check the downloaded instruction
count against the limit set in our softc.
Modify callers of ahc_loadseq to handle load
failures as appropriate.
Set instruction RAM sizes for each chip type.
aic7xxx_pci.c:
Add some delay in the aic785X termination
control code. This may fix problems with
the 2930.
Be consistent in how we access config space
registers. 16bit registers are accessed using
16bit ops.
aic7xxx.c:
Correct spelling errors.
Have ahc_force_renegotiation() take a devinfo as is done
in the U320 driver. Use this argument to correct a bug
in the selection timeout handler where we forced a renegotiation
with the last device that had set SAVED_SCSIID. SAVED_SCSIID
is only updated once a selection is *sucessfull* and so is
stale for any selection timeout.
Cleanup the setup of the devinfo for busfree events. We
now use this devinfo for a call to ahc_force_renegotiation()
at the bottom of the routine, so it must be initialized in
all cases.
In ahc_pause_and_flushwork(), adjust the loop so that it
will exit in the hot-eject case even if the INT_PEND mask
is something other than 0xFF (as it is in this driver).
Correct a wrapping string constant.
Call ahc_fini_scbdata() after shutdown so that
any ahc_chip_init() routine that might access
SCB data will not access free'd memory.
Correctly setup our buffer tag to indicate that 39bit
addressing is available if in 39bit addressing mode.
Rearrange some variable declarations based on
type size.
aic7xxx.c
aic7xxx.h:
aic7xxx.reg:
Consistently use MAX_OFFSET for the user max syncrate
set from non-volatile storage. This ensures that the
offset does not conflict with AHC_OFFSET_UNKNOWN.
Change AHC_OFFSET_UNKNOWN to 0xFF. This is
a value that the curr->offset can never be,
unlike '0' which we previously used. This
fixes code that only checks for a non-zero
offset to determine if a sync negotiation
is required since it will fire in the unknown
case even if the goal is async.
Change MAX_OFFSET to 0x7f which is the max
offset U160 aic7xxx controllers can negotiate.
This ensures that curr->offset will not
match AHC_OFFSET_UNKNOWN.
aic7xxx_inline.h:
Have our inline interrupt handler return with a value
indicating whether we serviced a real interrupt. This
is required for Linux support.
Return earlier if the interrupt is not for us.