FreeBSD ahd driver:
aic79xx.h:
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.
FreeBSD ahd driver:
Add parenthesis so that we get all of the bits all
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.
FreeBSD ahd driver:
When single stepping, only leave ENBUSFREE enabled
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.
FreeBSD ahd driver:
aic79xx.seq:
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.
FreeBSD ahd driver:
Work around SCSI spec violation by the Quantum Atlas 10K.
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.
FreeBSD ahd driver:
Fix a reported case of severe data corruption:
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)
FreeBSD ahd driver:
Add 7901B support.
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
FreeBSD ahd driver:
aic7770.c:
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.
FreeBSD ahd driver:
aic79xx.c:
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)
FreeBSD ahd driver:
Correct/Simplify ignore wide residue message handling
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.
FreeBSD ahd driver:
Change hadling of the Rev. A packetized lun output bug
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.
to the FreeBSD ahd driver:
Correct spelling errors.
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.