Update DPT driver from 1.4.3 to 1.4.5
Submitted by: Simon Shapiro <shimon@simon-shapiro.org>
This commit is contained in:
parent
84dd0fd0bb
commit
b755b88510
@ -2,7 +2,7 @@
|
||||
# LINT -- config file for checking all the sources, tries to pull in
|
||||
# as much of the source tree as it can.
|
||||
#
|
||||
# $Id: LINT,v 1.448 1998/08/03 19:14:31 msmith Exp $
|
||||
# $Id: LINT,v 1.449 1998/08/04 21:44:08 brian Exp $
|
||||
#
|
||||
# NB: You probably don't want to try running a kernel built from this
|
||||
# file. Instead, you should start from GENERIC, and add options from
|
||||
@ -1560,6 +1560,10 @@ options SPX_HACK
|
||||
|
||||
# The 'dpt' driver provides support for DPT controllers (http://www.dpt.com/).
|
||||
# These have hardware RAID-{0,1,5} support, and do multi-initiator I/O.
|
||||
# The DPT controllers are commonly re-licensed under other brand-names -
|
||||
# some controllers by Olivetti, Dec, HP, AT&T, SNI, AST, Alphatronic, NEC and
|
||||
# Compaq are actually DPT controllers.
|
||||
#
|
||||
# See sys/dev/dpt for debugging and other subtle options.
|
||||
# DPT_VERIFY_HINTR Performs some strict hardware interrupts testing.
|
||||
# Only use if you suspect PCI bus corruption problems
|
||||
@ -1569,9 +1573,9 @@ options SPX_HACK
|
||||
# slots to exactly what the DPT can hold at one time,
|
||||
# enable this option.
|
||||
# DPT_MEASURE_PERFORMANCE Enables a set of (semi)invasive metrics. Various
|
||||
# instruments are enabled. Assumed to be enabled by
|
||||
# /usr/sbin/dpt_* tools.
|
||||
# DPT_FREELIST_IS_STACK For optimat L{1,2} CPU cache utilization, enable
|
||||
# instruments are enabled. The tools in
|
||||
# /usr/sbin/dpt_* assume these to be enabled.
|
||||
# DPT_FREELIST_IS_STACK For optimal L{1,2} CPU cache utilization, enable
|
||||
# this option. Otherwise, the transaction queue is
|
||||
# a LIFO. I cannot measure the performance gain.
|
||||
# DPT_HANDLE_TIMEOUTS Normally device timeouts are handled by the DPT.
|
||||
@ -1585,6 +1589,15 @@ options SPX_HACK
|
||||
# any interrupt that got lost. Seems to help in some
|
||||
# DPT-firmware/Motherboard combinations. Minimal
|
||||
# cost, great benefit.
|
||||
# DPT_RESET_HBA Make "reset" actually reset the controller
|
||||
# instead of fudging it. Only enable this if you
|
||||
# are 100% certain you need it.
|
||||
# DPT_SHUTDOWN_SLEEP Reset controller if a request take more than
|
||||
# this number of seconds. Do NOT enable this
|
||||
# unless you are really, really, really certain
|
||||
# you need it. You are advised to call Simon (the
|
||||
# driver author) before setting it, and NEVER,
|
||||
# EVER set it to less than 300s (5 minutes).
|
||||
|
||||
controller dpt0
|
||||
|
||||
@ -1597,3 +1610,8 @@ options DPT_HANDLE_TIMEOUTS
|
||||
options DPT_TIMEOUT_FACTOR=4
|
||||
options DPT_INTR_DELAY=200 # Some motherboards need that
|
||||
options DPT_LOST_IRQ
|
||||
options DPT_RESET_HBA
|
||||
|
||||
# Don't EVER set this without having talked to Simon Shapiro on the phone
|
||||
# first.
|
||||
options DPT_SHUTDOWN_SLEEP=500
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: options,v 1.87 1998/07/06 04:55:22 julian Exp $
|
||||
# $Id: options,v 1.88 1998/07/12 01:48:14 bde Exp $
|
||||
#
|
||||
# On the handling of kernel options
|
||||
#
|
||||
@ -192,15 +192,17 @@ IPFILTER_LKM opt_ipfilter.h
|
||||
NATM opt_natm.h
|
||||
|
||||
# DPT driver debug flags
|
||||
DPT_VERIFY_HINTR opt_dpt.h
|
||||
DPT_USE_SINTR opt_dpt.h
|
||||
DPT_RESTRICTED_FREELIST opt_dpt.h
|
||||
DPT_MEASURE_PERFORMANCE opt_dpt.h
|
||||
DPT_FREELIST_IS_STACK opt_dpt.h
|
||||
DPT_HANDLE_TIMEOUTS opt_dpt.h
|
||||
DPT_TIMEOUT_FACTOR opt_dpt.h
|
||||
DPT_VERIFY_HINTR opt_dpt.h
|
||||
DPT_USE_SINTR opt_dpt.h
|
||||
DPT_RESTRICTED_FREELIST opt_dpt.h
|
||||
DPT_MEASURE_PERFORMANCE opt_dpt.h
|
||||
DPT_FREELIST_IS_STACK opt_dpt.h
|
||||
DPT_HANDLE_TIMEOUTS opt_dpt.h
|
||||
DPT_TIMEOUT_FACTOR opt_dpt.h
|
||||
DPT_INTR_DELAY opt_dpt.h
|
||||
DPT_LOST_IRQ opt_dpt.h
|
||||
DPT_SHUTDOWN_SLEEP opt_dpt.h
|
||||
DPT_RESET_HBA opt_dpt.h
|
||||
|
||||
# Misc debug flags. Most of these should probably be replaced with
|
||||
# 'DEBUG', and then let people recompile just the interesting modules
|
||||
|
@ -36,7 +36,7 @@
|
||||
* future.
|
||||
*/
|
||||
|
||||
#ident "$Id: dpt_control.c,v 1.6 1998/06/07 17:09:42 dfr Exp $"
|
||||
#ident "$Id: dpt_control.c,v 1.7 1998/07/13 09:52:51 bde Exp $"
|
||||
|
||||
#include "opt_dpt.h"
|
||||
|
||||
@ -67,8 +67,6 @@ static vm_offset_t dpt_physmap(u_int32_t paddr, vm_size_t size);
|
||||
static void dpt_unphysmap(u_int8_t * vaddr, vm_size_t size);
|
||||
|
||||
static void dpt_get_sysinfo(void);
|
||||
static INLINE dpt_softc_t *dpt_minor2softc(int minor_no);
|
||||
static INLINE int dpt_minor2unit(int minor_no);
|
||||
|
||||
static int dpt_open(dev_t dev, int flags, int fmt, struct proc * p);
|
||||
static int dpt_close(dev_t dev, int flags, int fmt, struct proc * p);
|
||||
@ -102,6 +100,52 @@ NULL, -1};
|
||||
static struct buf *dpt_inbuf[DPT_MAX_ADAPTERS];
|
||||
static char dpt_rw_command[DPT_MAX_ADAPTERS][DPT_RW_CMD_LEN + 1];
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
void
|
||||
dpt_reset_performance(dpt_softc_t *dpt)
|
||||
{
|
||||
int ndx;
|
||||
|
||||
/* Zero out all command counters */
|
||||
bzero(&dpt->performance, sizeof(dpt_perf_t));
|
||||
for ( ndx = 0; ndx < 256; ndx ++ )
|
||||
dpt->performance.min_command_time[ndx] = BIG_ENOUGH;
|
||||
|
||||
dpt->performance.min_intr_time = BIG_ENOUGH;
|
||||
dpt->performance.min_waiting_time = BIG_ENOUGH;
|
||||
dpt->performance.min_submit_time = BIG_ENOUGH;
|
||||
dpt->performance.min_complete_time = BIG_ENOUGH;
|
||||
dpt->performance.min_eata_tries = BIG_ENOUGH;
|
||||
|
||||
for (ndx = 0; ndx < 10; ndx++ ) {
|
||||
dpt->performance.read_by_size_min_time[ndx] = BIG_ENOUGH;
|
||||
dpt->performance.write_by_size_min_time[ndx] = BIG_ENOUGH;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
|
||||
/**
|
||||
* Given a minor device number,
|
||||
* return the pointer to its softc structure
|
||||
*/
|
||||
|
||||
dpt_softc_t *
|
||||
dpt_minor2softc(int minor_no)
|
||||
{
|
||||
dpt_softc_t *dpt;
|
||||
|
||||
if (dpt_minor2unit(minor_no & ~SCSI_CONTROL_MASK) == -1)
|
||||
return (NULL);
|
||||
|
||||
for (dpt = TAILQ_FIRST(&dpt_softc_list);
|
||||
(dpt != NULL) && (dpt->unit != (minor_no & ~SCSI_CONTROL_MASK));
|
||||
dpt = TAILQ_NEXT(dpt, links));
|
||||
|
||||
return (dpt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a physical address to virtual one.
|
||||
* This is a first cut, experimental thing
|
||||
@ -159,40 +203,6 @@ dpt_unphysmap(u_int8_t * vaddr, vm_size_t size)
|
||||
kmem_free(kernel_map, (vm_offset_t) vaddr, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a minor device number, get its SCSI Unit.
|
||||
*/
|
||||
|
||||
static INLINE int
|
||||
dpt_minor2unit(int minor)
|
||||
{
|
||||
int unit;
|
||||
|
||||
unit = minor2hba(minor & ~SCSI_CONTROL_MASK);
|
||||
|
||||
return (unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a minor device number,
|
||||
* return the pointer to its softc structure
|
||||
*/
|
||||
|
||||
static INLINE dpt_softc_t *
|
||||
dpt_minor2softc(int minor_no)
|
||||
{
|
||||
dpt_softc_t *dpt;
|
||||
|
||||
if (dpt_minor2unit(minor_no & ~SCSI_CONTROL_MASK) == -1)
|
||||
return (NULL);
|
||||
|
||||
for (dpt = TAILQ_FIRST(&dpt_softc_list);
|
||||
(dpt != NULL) && (dpt->unit != (minor_no & ~SCSI_CONTROL_MASK));
|
||||
dpt = TAILQ_NEXT(dpt, links));
|
||||
|
||||
return (dpt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect interesting system information
|
||||
* The following is one of the worst hacks I have ever allowed my
|
||||
@ -620,7 +630,7 @@ dpt_read(dev_t dev, struct uio * uio, int ioflag)
|
||||
wbp += x;
|
||||
} else if (strcmp(command, DPT_RW_CMD_CLEAR_METRICS) == 0) {
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
bzero(&dpt->performance, sizeof(dpt->performance));
|
||||
dpt_reset_performance(dpt);
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
|
||||
x = sprintf(wbp, "dpt%d: Metrics have been cleared\n",
|
||||
@ -628,9 +638,6 @@ dpt_read(dev_t dev, struct uio * uio, int ioflag)
|
||||
work_size += x;
|
||||
wbp += x;
|
||||
} else if (strcmp(command, DPT_RW_CMD_SHOW_LED) == 0) {
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
bzero(&dpt->performance, sizeof(dpt->performance));
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
|
||||
x = sprintf(wbp, "dpt%d:%s\n",
|
||||
dpt->unit, i2bin(dpt_blinking_led(dpt), 8));
|
||||
@ -697,8 +704,8 @@ dpt_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, struct proc * p)
|
||||
|
||||
switch (cmd) {
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
case DPT_IOCTL_INTERNAL_METRICS:
|
||||
(void) memcpy(cmdarg, (char *) &dpt->performance, sizeof(dpt_perf_t));
|
||||
case DPT_IOCTL_INTERNAL_METRICS:
|
||||
memcpy(cmdarg, &dpt->performance, sizeof(dpt->performance));
|
||||
return (0);
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
case DPT_IOCTL_SOFTC:
|
||||
@ -757,7 +764,7 @@ dpt_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, struct proc * p)
|
||||
udpt.cache_type = dpt->cache_type;
|
||||
udpt.cache_size = dpt->cache_size;
|
||||
|
||||
(void) memcpy(cmdarg, (char *) &udpt, sizeof(dpt_user_softc_t));
|
||||
memcpy(cmdarg, &udpt, sizeof(dpt_user_softc_t));
|
||||
return (0);
|
||||
case SDI_SEND:
|
||||
case DPT_IOCTL_SEND:
|
||||
@ -821,9 +828,7 @@ dpt_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, struct proc * p)
|
||||
(caddr_t *) eata_pass_thru->command_buffer,
|
||||
sizeof(dpt_sysinfo)));
|
||||
case EATAUSRCMD:
|
||||
printf("%d\n", __LINE__);
|
||||
result = dpt_user_cmd(dpt, eata_pass_thru, cmdarg, minor_no);
|
||||
printf("%d\n", __LINE__);
|
||||
return (result);
|
||||
case DPT_BLINKLED:
|
||||
result = dpt_blinking_led(dpt);
|
||||
|
@ -34,7 +34,7 @@
|
||||
* caveats: We may need an eisa and an isa files too
|
||||
*/
|
||||
|
||||
#ident "$Id: dpt_pci.c,v 1.5 1998/03/11 00:30:16 julian Exp $"
|
||||
#ident "$Id: dpt_pci.c,v 1.6 1998/06/02 00:32:38 eivind Exp $"
|
||||
|
||||
#include "opt_devfs.h"
|
||||
#include "opt_dpt.h"
|
||||
@ -213,21 +213,7 @@ dpt_pci_attach(pcici_t config_id, int unit)
|
||||
dpt->commands_processed = 0;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
/* Zero out all command counters */
|
||||
bzero((void *)&dpt->performance, sizeof(dpt_perf_t));
|
||||
for ( ndx = 0; ndx < 256; ndx ++ )
|
||||
dpt->performance.min_command_time[ndx] = BIG_ENOUGH;
|
||||
|
||||
dpt->performance.min_intr_time = BIG_ENOUGH;
|
||||
dpt->performance.min_waiting_time = BIG_ENOUGH;
|
||||
dpt->performance.min_submit_time = BIG_ENOUGH;
|
||||
dpt->performance.min_complete_time = BIG_ENOUGH;
|
||||
dpt->performance.min_eata_tries = BIG_ENOUGH;
|
||||
|
||||
for (ndx = 0; ndx < 10; ndx++ ) {
|
||||
dpt->performance.read_by_size_min_time[ndx] = BIG_ENOUGH;
|
||||
dpt->performance.write_by_size_min_time[ndx] = BIG_ENOUGH;
|
||||
}
|
||||
dpt_reset_performance(dpt);
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
|
||||
dpt->unit = unit;
|
||||
@ -481,14 +467,13 @@ dpt_pci_attach(pcici_t config_id, int unit)
|
||||
* We never get the entries made.
|
||||
*/
|
||||
#ifdef DEVFS
|
||||
dpt->devfs_data_token = devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d", dpt->unit);
|
||||
dpt->devfs_ctl_token = devfs_add_devswf(&dpt_cdevsw,
|
||||
dpt->unit | SCSI_CONTROL_MASK,
|
||||
DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d.ctl", dpt->unit);
|
||||
(void) devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d", dpt->unit);
|
||||
(void) devfs_add_devswf(&dpt_cdevsw, dpt->unit | SCSI_CONTROL_MASK,
|
||||
DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d.ctl", dpt->unit);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -37,9 +37,9 @@
|
||||
* Last but not least, many thanx to UCB and the FreeBSD
|
||||
* team for creating and maintaining such a wonderful O/S.
|
||||
*
|
||||
* TODO: * Add EISA and ISA probe code.
|
||||
* TODO: * Add ISA probe code.
|
||||
* * Add driver-level RSID-0. This will allow interoperability with
|
||||
* NiceTry, M$-Doze, Win-Dog, Slowlaris, etc. in recognizing RAID
|
||||
* NiceTry, M$-Doze, Win-Dog, Slowlaris, etc., in recognizing RAID
|
||||
* arrays that span controllers (Wow!).
|
||||
*/
|
||||
|
||||
@ -64,7 +64,8 @@
|
||||
* 3. dpt_handle_timeouts potentially inserts into the queue
|
||||
*/
|
||||
|
||||
#ident "$Id: dpt_scsi.c,v 1.6 1998/06/02 00:32:38 eivind Exp $"
|
||||
#ident "$Id: dpt_scsi.c,v 1.32 1998/08/03 16:45:12 root Exp root $"
|
||||
|
||||
#define _DPT_C_
|
||||
|
||||
#include "opt_dpt.h"
|
||||
@ -83,6 +84,13 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
/* The HBA reset option uses the same timer as the lost IRQ option*/
|
||||
#ifdef DPT_RESET_HBA
|
||||
#ifndef DPT_LOST_IRQ
|
||||
#define DPT_LOST_IRQ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/dpt.h>
|
||||
|
||||
#ifdef INLINE
|
||||
@ -98,6 +106,8 @@ int dpt_controllers_present = 0;
|
||||
|
||||
/* Function Prototypes */
|
||||
|
||||
#define microtime_now dpt_time_now()
|
||||
|
||||
static INLINE u_int32_t dpt_inl(dpt_softc_t * dpt, u_int32_t offset);
|
||||
static INLINE u_int8_t dpt_inb(dpt_softc_t * dpt, u_int32_t offset);
|
||||
static INLINE void
|
||||
@ -368,6 +378,117 @@ dpt_raid_busy(dpt_softc_t * dpt)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef DPT_RESET_HBA
|
||||
|
||||
/*
|
||||
** Function name : dpt_reset_hba
|
||||
**
|
||||
** Description : Reset the HBA and properly discard all pending work
|
||||
** Input : Minor Device Number
|
||||
** Output : Nothing
|
||||
*/
|
||||
|
||||
static void
|
||||
dpt_reset_hba(int minor)
|
||||
{
|
||||
dpt_softc_t *dpt;
|
||||
eata_ccb_t *ccb;
|
||||
int ospl;
|
||||
dpt_ccb_t dccb, *dccbp;
|
||||
int result;
|
||||
struct scsi_xfer *xs;
|
||||
|
||||
if ((dpt = dpt_minor2softc(minor)) == NULL) {
|
||||
printf("DPT: Ignoring invalid minor %d in dpt_reset_hba\n", minor);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepare a control block. The SCSI command part is immaterial */
|
||||
dccb.xs = NULL;
|
||||
dccb.flags = 0;
|
||||
dccb.state = DPT_CCB_STATE_NEW;
|
||||
dccb.std_callback = NULL;
|
||||
dccb.wrbuff_callback = NULL;
|
||||
|
||||
ccb = &dccb.eata_ccb;
|
||||
ccb->CP_OpCode = EATA_CMD_RESET;
|
||||
ccb->SCSI_Reset = 0;
|
||||
ccb->HBA_Init = 1;
|
||||
ccb->Auto_Req_Sen = 1;
|
||||
ccb->cp_id = 0; /* Should be ignored */
|
||||
ccb->DataIn = 1;
|
||||
ccb->DataOut = 0;
|
||||
ccb->Interpret = 1;
|
||||
ccb->reqlen = htonl(sizeof(struct scsi_sense_data));
|
||||
ccb->cp_statDMA = htonl(vtophys(&ccb->cp_statDMA));
|
||||
ccb->cp_reqDMA = htonl(vtophys(&ccb->cp_reqDMA));
|
||||
ccb->cp_viraddr = (u_int32_t) & ccb;
|
||||
|
||||
ccb->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO;
|
||||
ccb->cp_scsi_cmd = 0; /* Should be ignored */
|
||||
|
||||
/* Lock up the submitted queue. We are very persistant here */
|
||||
ospl = splcam();
|
||||
while (dpt->queue_status & DPT_SUBMITTED_QUEUE_ACTIVE) {
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
dpt->queue_status |= DPT_SUBMITTED_QUEUE_ACTIVE;
|
||||
splx(ospl);
|
||||
|
||||
/* Send the RESET message */
|
||||
if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb,
|
||||
EATA_CMD_RESET, 0, 0, 0, 0)) != 0) {
|
||||
printf("dpt%d: Failed to send the RESET message.\n"
|
||||
" Trying cold boot (ouch!)\n", dpt->unit);
|
||||
|
||||
|
||||
if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb,
|
||||
EATA_COLD_BOOT, 0, 0, 0, 0))
|
||||
!= 0) {
|
||||
panic("dpt%d: Faild to cold boot the HBA\n", dpt->unit);
|
||||
}
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
dpt->performance.cold_boots++;
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
}
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
dpt->performance.warm_starts++;
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
|
||||
printf("dpt%d: Aborting pending requests. O/S should re-submit\n",
|
||||
dpt->unit);
|
||||
|
||||
while ((dccbp = TAILQ_FIRST(&dpt->completed_ccbs)) != NULL) {
|
||||
struct scsi_xfer *xs = dccbp->xs;
|
||||
|
||||
/* Not all transactions have xs structs */
|
||||
if (xs != NULL) {
|
||||
/* Tell the kernel proper this did not complete well */
|
||||
xs->error |= XS_SELTIMEOUT;
|
||||
xs->flags |= SCSI_ITSDONE;
|
||||
scsi_done(xs);
|
||||
}
|
||||
|
||||
dpt_Qremove_submitted(dpt, dccbp);
|
||||
|
||||
/* Remember, Callbacks are NOT in the standard queue */
|
||||
if (dccbp->std_callback != NULL) {
|
||||
(dccbp->std_callback) (dpt, dccbp->eata_ccb.cp_channel, dccbp);
|
||||
} else {
|
||||
ospl = splcam();
|
||||
dpt_Qpush_free(dpt, dccbp);
|
||||
splx(ospl);
|
||||
}
|
||||
}
|
||||
|
||||
printf("dpt%d: reset done aborting all pending commands\n", dpt->unit);
|
||||
dpt->queue_status &= ~DPT_SUBMITTED_QUEUE_ACTIVE;
|
||||
}
|
||||
|
||||
#endif /* DPT_RESET_HBA */
|
||||
|
||||
/**
|
||||
* Build a Command Block for target mode READ/WRITE BUFFER,
|
||||
* with the ``sync'' bit ON.
|
||||
@ -438,8 +559,6 @@ dpt_target_ccb(dpt_softc_t * dpt, int bus, u_int8_t target, u_int8_t lun,
|
||||
|
||||
/* Setup a target mode READ command */
|
||||
|
||||
#define cmd_ct dpt->performance.command_count[(int)ccb->eata_ccb.cp_scsi_cmd];
|
||||
|
||||
static void
|
||||
dpt_set_target(int redo, dpt_softc_t * dpt,
|
||||
u_int8_t bus, u_int8_t target, u_int8_t lun, int mode,
|
||||
@ -447,10 +566,6 @@ dpt_set_target(int redo, dpt_softc_t * dpt,
|
||||
{
|
||||
int ospl;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
struct timeval now;
|
||||
#endif
|
||||
|
||||
if (dpt->target_mode_enabled) {
|
||||
ospl = splcam();
|
||||
|
||||
@ -461,9 +576,8 @@ dpt_set_target(int redo, dpt_softc_t * dpt,
|
||||
ccb->transaction_id = ++dpt->commands_processed;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
++cmd_ct;
|
||||
microtime(&now);
|
||||
ccb->command_started = now;
|
||||
dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++;
|
||||
ccb->command_started = microtime_now;
|
||||
#endif
|
||||
dpt_Qadd_waiting(dpt, ccb);
|
||||
dpt_sched_queue(dpt);
|
||||
@ -477,11 +591,11 @@ dpt_set_target(int redo, dpt_softc_t * dpt,
|
||||
|
||||
/**
|
||||
* Schedule a buffer to be sent to another target.
|
||||
* The work will be scheduled and the callback provided will be called when the work is
|
||||
* actually done.
|
||||
* The work will be scheduled and the callback provided will be called when
|
||||
* the work is actually done.
|
||||
*
|
||||
* Please NOTE: ``Anyone'' can send a buffer, but only registered clients get notified
|
||||
of receipt of buffers.
|
||||
* Please NOTE: ``Anyone'' can send a buffer, but only registered clients
|
||||
* get notified of receipt of buffers.
|
||||
*/
|
||||
|
||||
int
|
||||
@ -498,9 +612,6 @@ dpt_send_buffer(int unit,
|
||||
dpt_softc_t *dpt;
|
||||
dpt_ccb_t *ccb = NULL;
|
||||
int ospl;
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
struct timeval now;
|
||||
#endif
|
||||
|
||||
/* This is an external call. Be a bit paranoid */
|
||||
for (dpt = TAILQ_FIRST(&dpt_softc_list);
|
||||
@ -540,18 +651,17 @@ valid_unit:
|
||||
splx(ospl);
|
||||
|
||||
bcopy(dpt->rw_buffer[channel][target][lun] + offset, data, length);
|
||||
dpt_target_ccb(dpt, channel, target, lun, ccb, mode, SCSI_TM_WRITE_BUFFER,
|
||||
length, offset);
|
||||
ccb->std_callback = (ccb_callback) callback; /* A hack. Potential
|
||||
* trouble */
|
||||
dpt_target_ccb(dpt, channel, target, lun, ccb, mode,
|
||||
SCSI_TM_WRITE_BUFFER,
|
||||
length, offset);
|
||||
ccb->std_callback = (ccb_callback) callback; /* Potential trouble */
|
||||
|
||||
ospl = splcam();
|
||||
ccb->transaction_id = ++dpt->commands_processed;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
++cmd_ct;
|
||||
microtime(&now);
|
||||
ccb->command_started = now;
|
||||
dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++;
|
||||
ccb->command_started = microtime_now;
|
||||
#endif
|
||||
dpt_Qadd_waiting(dpt, ccb);
|
||||
dpt_sched_queue(dpt);
|
||||
@ -748,9 +858,9 @@ dpt_send_eata_command(dpt_softc_t * dpt, eata_ccb_t * cmd_block,
|
||||
u_int8_t result;
|
||||
u_int32_t test;
|
||||
u_int32_t swapped_cmdaddr;
|
||||
|
||||
|
||||
if (!retries)
|
||||
retries = 1000;
|
||||
retries = 10000;
|
||||
|
||||
/*
|
||||
* I hate this polling nonsense. Wish there was a way to tell the DPT
|
||||
@ -780,6 +890,11 @@ dpt_send_eata_command(dpt_softc_t * dpt, eata_ccb_t * cmd_block,
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* The controller is alive, advance the wedge timer */
|
||||
#ifdef DPT_RESET_HBA
|
||||
dpt->last_contact = microtime_now;
|
||||
#endif
|
||||
|
||||
if (cmd_block != NULL) {
|
||||
swapped_cmdaddr = vtophys(cmd_block);
|
||||
|
||||
@ -865,7 +980,6 @@ dpt_user_cmd(dpt_softc_t * dpt, eata_pt_t * user_cmd,
|
||||
int submitted;
|
||||
dpt_ccb_t *ccb;
|
||||
void *data;
|
||||
struct timeval now;
|
||||
|
||||
data = NULL;
|
||||
channel = minor2hba(minor_no);
|
||||
@ -1013,9 +1127,8 @@ dpt_user_cmd(dpt_softc_t * dpt, eata_pt_t * user_cmd,
|
||||
ccb->data = data;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
++dpt->performance.command_count[(int) ccb->eata_ccb.cp_scsi_cmd];
|
||||
microtime(&now);
|
||||
ccb->command_started = now;
|
||||
++dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd];
|
||||
ccb->command_started = microtime_now;
|
||||
#endif
|
||||
ospl = splcam();
|
||||
dpt_Qadd_waiting(dpt, ccb);
|
||||
@ -1851,6 +1964,11 @@ dpt_scsi_cmd(struct scsi_xfer * xs)
|
||||
ospl = splcam();
|
||||
if ((dpt->state & DPT_LOST_IRQ_SET) == 0) {
|
||||
printf("dpt%d: Initializing Lost IRQ Timer\n", dpt->unit);
|
||||
#ifdef DPT_RESET_HBA
|
||||
printf("dpt%d: HBA will reset if irresponsive for %d seconds\n",
|
||||
dpt->unit, DPT_RESET_HBA);
|
||||
dpt->last_contact = microtime_now;
|
||||
#endif
|
||||
dpt->state |= DPT_LOST_IRQ_SET;
|
||||
timeout(dpt_irq_timeout, dpt, hz);
|
||||
}
|
||||
@ -2109,13 +2227,20 @@ dpt_scsi_cmd(struct scsi_xfer * xs)
|
||||
if ((status & HA_SERROR) || (ndx == xs->timeout)) {
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
#ifdef DPT_RESET_HBA
|
||||
else {
|
||||
/*
|
||||
* We received a reply and did not time out.
|
||||
* Advance the wedge counter.
|
||||
*/
|
||||
dpt->last_contact = microtime_now;
|
||||
}
|
||||
#endif /* DPT_RESET_HBA */
|
||||
|
||||
dpt_Qpush_free(dpt, ccb);
|
||||
splx(ospl);
|
||||
return (COMPLETE);
|
||||
} else {
|
||||
struct timeval junk;
|
||||
|
||||
/**
|
||||
* Not a polled command.
|
||||
* The command can be queued normally.
|
||||
@ -2129,10 +2254,8 @@ dpt_scsi_cmd(struct scsi_xfer * xs)
|
||||
ccb->transaction_id = ++dpt->commands_processed;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
#define cmd_ndx (int)ccb->eata_ccb.cp_scsi_cmd
|
||||
++dpt->performance.command_count[cmd_ndx];
|
||||
microtime(&junk);
|
||||
ccb->command_started = junk;
|
||||
++dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd];
|
||||
ccb->command_started = microtime_now;
|
||||
#endif
|
||||
dpt_Qadd_waiting(dpt, ccb);
|
||||
splx(ospl);
|
||||
@ -2275,12 +2398,7 @@ dpt_intr(void *arg)
|
||||
#endif
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
{
|
||||
struct timeval junk;
|
||||
|
||||
microtime(&junk);
|
||||
dpt->performance.intr_started = junk;
|
||||
}
|
||||
dpt->performance.intr_started = microtime_now;
|
||||
#endif
|
||||
|
||||
/* First order of business is to check if this interrupt is for us */
|
||||
@ -2297,12 +2415,17 @@ dpt_intr(void *arg)
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* The controller is alive, advance the wedge timer */
|
||||
#ifdef DPT_RESET_HBA
|
||||
dpt->last_contact = microtime_now;
|
||||
#endif
|
||||
|
||||
if (!dpt->handle_interrupts) {
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
++dpt->performance.aborted_interrupts;
|
||||
#endif
|
||||
status = dpt_inb(dpt, HA_RSTATUS); /* This CLEARS
|
||||
* interrupts */
|
||||
status = dpt_inb(dpt, HA_RSTATUS); /* This CLEARS interrupts! */
|
||||
return;
|
||||
}
|
||||
/**
|
||||
@ -2332,12 +2455,10 @@ dpt_intr(void *arg)
|
||||
|
||||
#ifdef DPT_HANDLE_TIMEOUTS
|
||||
if (dccb->state & DPT_CCB_STATE_MARKED_LOST) {
|
||||
struct timeval now;
|
||||
u_int32_t age;
|
||||
struct scsi_xfer *xs = dccb->xs;
|
||||
|
||||
microtime(&now);
|
||||
age = dpt_time_delta(dccb->command_started, now);
|
||||
age = dpt_time_delta(dccb->command_started, microtime_now);
|
||||
|
||||
printf("dpt%d: Salvaging Tx %d from the jaws of destruction "
|
||||
"(%d/%d)\n",
|
||||
@ -2484,11 +2605,8 @@ dpt_intr(void *arg)
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
{
|
||||
u_int32_t result;
|
||||
struct timeval junk;
|
||||
|
||||
microtime(&junk);
|
||||
|
||||
result = dpt_time_delta(dpt->performance.intr_started, junk);
|
||||
result = dpt_time_delta(dpt->performance.intr_started, microtime_now);
|
||||
|
||||
if (result != ~0) {
|
||||
if (dpt->performance.max_intr_time < result)
|
||||
@ -2595,14 +2713,13 @@ dpt_complete(dpt_softc_t * dpt)
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
{
|
||||
u_int32_t result;
|
||||
struct timeval junk;
|
||||
|
||||
microtime(&junk);
|
||||
ccb->command_ended = junk;
|
||||
#define time_delta dpt_time_delta(ccb->command_started, ccb->command_ended)
|
||||
result = time_delta;
|
||||
#define maxctime dpt->performance.max_command_time[ccb->eata_ccb.cp_scsi_cmd]
|
||||
#define minctime dpt->performance.min_command_time[ccb->eata_ccb.cp_scsi_cmd]
|
||||
|
||||
ccb->command_ended = microtime_now;
|
||||
result = time_delta;
|
||||
|
||||
if (result != ~0) {
|
||||
if (maxctime < result) {
|
||||
@ -2689,7 +2806,7 @@ dpt_process_completion(dpt_softc_t * dpt,
|
||||
struct scsi_rw_big *cmd;
|
||||
int op_type;
|
||||
|
||||
cmd = (struct scsi_rw_big *) & ccb->eata_ccb.cp_scsi_cmd;
|
||||
cmd = (struct scsi_rw_big *) &ccb->eata_ccb.cp_scsi_cmd;
|
||||
|
||||
switch (cmd->op_code) {
|
||||
case 0xa8: /* 12-byte READ */
|
||||
@ -2865,6 +2982,10 @@ dpt_process_completion(dpt_softc_t * dpt,
|
||||
* basis.
|
||||
* It is a completely ugly hack which purpose is to handle the problem of
|
||||
* missing interrupts on certain platforms..
|
||||
*
|
||||
* An additional task is to optionally check if the controller is wedged.
|
||||
* A wedeged controller is one which has not accepted a command, nor sent
|
||||
* an interrupt in the last DPT_RESET_HBA seconds.
|
||||
*/
|
||||
|
||||
static void
|
||||
@ -2883,6 +3004,34 @@ dpt_irq_timeout(void *arg)
|
||||
printf("dpt %d: %d lost Interrupts Recovered\n",
|
||||
dpt->unit, ++dpt->lost_interrupts);
|
||||
}
|
||||
#ifdef DPT_RESET_HBA
|
||||
{
|
||||
int max_wedge, contact_delta;
|
||||
|
||||
if (TAILQ_EMPTY(&dpt->waiting_ccbs)) {
|
||||
dpt->last_contact = microtime_now;
|
||||
} else {
|
||||
/* If nothing is waiting, we cannot assume we are wedged */
|
||||
if (DPT_RESET_HBA < 1)
|
||||
max_wedge = 1000000;
|
||||
else
|
||||
max_wedge = 1000000 * DPT_RESET_HBA;
|
||||
|
||||
contact_delta = dpt_time_delta(dpt->last_contact,
|
||||
microtime_now);
|
||||
|
||||
if (contact_delta > max_wedge) {
|
||||
printf("dpt%d: Appears wedged for %d.%d (%d.0)seconds.\n"
|
||||
" Resetting\n",
|
||||
dpt->unit, contact_delta/1000000,
|
||||
(contact_delta % 1000000) / 100000,
|
||||
DPT_RESET_HBA);
|
||||
dpt_reset_hba(dpt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* DPT_RESET_HBA */
|
||||
|
||||
dpt->state &= ~DPT_LOST_IRQ_ACTIVE;
|
||||
}
|
||||
timeout(dpt_irq_timeout, (caddr_t) dpt, hz * 1);
|
||||
@ -2933,13 +3082,10 @@ dpt_handle_timeouts(dpt_softc_t * dpt)
|
||||
ccb != NULL;
|
||||
ccb = TAILQ_NEXT(ccb, links)) {
|
||||
struct scsi_xfer *xs;
|
||||
struct timeval now;
|
||||
u_int32_t age, max_age;
|
||||
|
||||
xs = ccb->xs;
|
||||
|
||||
microtime(&now);
|
||||
age = dpt_time_delta(ccb->command_started, now);
|
||||
age = dpt_time_delta(ccb->command_started, microtime_now);
|
||||
|
||||
#define TenSec 10000000
|
||||
|
||||
@ -3054,10 +3200,8 @@ dpt_Qremove_completed(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
u_int32_t complete_time;
|
||||
struct timeval now;
|
||||
|
||||
microtime(&now);
|
||||
complete_time = dpt_time_delta(ccb->command_ended, now);
|
||||
complete_time = dpt_time_delta(ccb->command_ended, microtime_now);
|
||||
|
||||
if (complete_time != ~0) {
|
||||
if (dpt->performance.max_complete_time < complete_time)
|
||||
@ -3102,7 +3246,7 @@ static INLINE_Q void
|
||||
dpt_Qpush_free(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
#ifdef DPT_FREELIST_IS_STACK
|
||||
TAILQ_INSERT_HEAD(&dpt->free_ccbs, ccb, links);
|
||||
TAILQ_INSERT_HEAD(&dpt->free_ccbs, ccb, links)
|
||||
#else
|
||||
TAILQ_INSERT_TAIL(&dpt->free_ccbs, ccb, links);
|
||||
#endif
|
||||
@ -3116,14 +3260,11 @@ dpt_Qpush_free(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
static INLINE_Q void
|
||||
dpt_Qadd_waiting(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
struct timeval junk;
|
||||
|
||||
TAILQ_INSERT_TAIL(&dpt->waiting_ccbs, ccb, links);
|
||||
++dpt->waiting_ccbs_count;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
microtime(&junk);
|
||||
ccb->command_ended = junk;
|
||||
ccb->command_ended = microtime_now;
|
||||
if (dpt->waiting_ccbs_count > dpt->performance.max_waiting_count)
|
||||
dpt->performance.max_waiting_count = dpt->waiting_ccbs_count;
|
||||
#endif
|
||||
@ -3138,14 +3279,11 @@ dpt_Qadd_waiting(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
static INLINE_Q void
|
||||
dpt_Qpush_waiting(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
struct timeval junk;
|
||||
|
||||
TAILQ_INSERT_HEAD(&dpt->waiting_ccbs, ccb, links);
|
||||
++dpt->waiting_ccbs_count;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
microtime(&junk);
|
||||
ccb->command_ended = junk;
|
||||
ccb->command_ended = microtime_now;
|
||||
|
||||
if (dpt->performance.max_waiting_count < dpt->waiting_ccbs_count)
|
||||
dpt->performance.max_waiting_count = dpt->waiting_ccbs_count;
|
||||
@ -3163,11 +3301,9 @@ static INLINE_Q void
|
||||
dpt_Qremove_waiting(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
struct timeval now;
|
||||
u_int32_t waiting_time;
|
||||
|
||||
microtime(&now);
|
||||
waiting_time = dpt_time_delta(ccb->command_ended, now);
|
||||
waiting_time = dpt_time_delta(ccb->command_ended, microtime_now);
|
||||
|
||||
if (waiting_time != ~0) {
|
||||
if (dpt->performance.max_waiting_time < waiting_time)
|
||||
@ -3190,14 +3326,11 @@ dpt_Qremove_waiting(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
static INLINE_Q void
|
||||
dpt_Qadd_submitted(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
struct timeval junk;
|
||||
|
||||
TAILQ_INSERT_TAIL(&dpt->submitted_ccbs, ccb, links);
|
||||
++dpt->submitted_ccbs_count;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
microtime(&junk);
|
||||
ccb->command_ended = junk;
|
||||
ccb->command_ended = microtime_now;
|
||||
if (dpt->performance.max_submit_count < dpt->submitted_ccbs_count)
|
||||
dpt->performance.max_submit_count = dpt->submitted_ccbs_count;
|
||||
#endif
|
||||
@ -3212,14 +3345,11 @@ dpt_Qadd_submitted(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
static INLINE_Q void
|
||||
dpt_Qadd_completed(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
struct timeval junk;
|
||||
|
||||
TAILQ_INSERT_TAIL(&dpt->completed_ccbs, ccb, links);
|
||||
++dpt->completed_ccbs_count;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
microtime(&junk);
|
||||
ccb->command_ended = junk;
|
||||
ccb->command_ended = microtime_now;
|
||||
if (dpt->performance.max_complete_count < dpt->completed_ccbs_count)
|
||||
dpt->performance.max_complete_count =
|
||||
dpt->completed_ccbs_count;
|
||||
@ -3236,11 +3366,9 @@ static INLINE_Q void
|
||||
dpt_Qremove_submitted(dpt_softc_t * dpt, dpt_ccb_t * ccb)
|
||||
{
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
struct timeval now;
|
||||
u_int32_t submit_time;
|
||||
|
||||
microtime(&now);
|
||||
submit_time = dpt_time_delta(ccb->command_ended, now);
|
||||
submit_time = dpt_time_delta(ccb->command_ended, microtime_now);
|
||||
|
||||
if (submit_time != ~0) {
|
||||
ccb->submitted_time = submit_time;
|
||||
@ -3336,11 +3464,26 @@ checkit:
|
||||
/**
|
||||
* What we do for a shutdown, is give the DPT early power loss
|
||||
* warning
|
||||
. */
|
||||
*/
|
||||
#ifdef DPT_SHUTDOWN_SLEEP
|
||||
DELAY(DPT_SHUTDOWN_SLEEP * 1000);
|
||||
|
||||
if (dpt->state & DPT_HA_SHUTDOWN_ACTIVE) {
|
||||
ospl = splcam();
|
||||
dpt->state &= ~DPT_HA_SHUTDOWN_ACTIVE;
|
||||
splx(ospl);
|
||||
printf("dpt%d: WARNING: After sleeping for %d seconds, "
|
||||
"I am re-enabled\n",
|
||||
dpt->unit);
|
||||
printf(" Any further I/O is NOT guranteed to "
|
||||
"complete!\n");
|
||||
}
|
||||
#else
|
||||
(void) dpt_send_immediate(dpt, NULL, EATA_POWER_OFF_WARN, 0, 0);
|
||||
printf("dpt%d: Controller was warned of shutdown and is now "
|
||||
"disabled\n",
|
||||
dpt->unit);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
@ -3692,3 +3835,5 @@ scsi_cmd_name(u_int8_t cmd)
|
||||
* c++-friend-offset: 0
|
||||
* End:
|
||||
*/
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# LINT -- config file for checking all the sources, tries to pull in
|
||||
# as much of the source tree as it can.
|
||||
#
|
||||
# $Id: LINT,v 1.448 1998/08/03 19:14:31 msmith Exp $
|
||||
# $Id: LINT,v 1.449 1998/08/04 21:44:08 brian Exp $
|
||||
#
|
||||
# NB: You probably don't want to try running a kernel built from this
|
||||
# file. Instead, you should start from GENERIC, and add options from
|
||||
@ -1560,6 +1560,10 @@ options SPX_HACK
|
||||
|
||||
# The 'dpt' driver provides support for DPT controllers (http://www.dpt.com/).
|
||||
# These have hardware RAID-{0,1,5} support, and do multi-initiator I/O.
|
||||
# The DPT controllers are commonly re-licensed under other brand-names -
|
||||
# some controllers by Olivetti, Dec, HP, AT&T, SNI, AST, Alphatronic, NEC and
|
||||
# Compaq are actually DPT controllers.
|
||||
#
|
||||
# See sys/dev/dpt for debugging and other subtle options.
|
||||
# DPT_VERIFY_HINTR Performs some strict hardware interrupts testing.
|
||||
# Only use if you suspect PCI bus corruption problems
|
||||
@ -1569,9 +1573,9 @@ options SPX_HACK
|
||||
# slots to exactly what the DPT can hold at one time,
|
||||
# enable this option.
|
||||
# DPT_MEASURE_PERFORMANCE Enables a set of (semi)invasive metrics. Various
|
||||
# instruments are enabled. Assumed to be enabled by
|
||||
# /usr/sbin/dpt_* tools.
|
||||
# DPT_FREELIST_IS_STACK For optimat L{1,2} CPU cache utilization, enable
|
||||
# instruments are enabled. The tools in
|
||||
# /usr/sbin/dpt_* assume these to be enabled.
|
||||
# DPT_FREELIST_IS_STACK For optimal L{1,2} CPU cache utilization, enable
|
||||
# this option. Otherwise, the transaction queue is
|
||||
# a LIFO. I cannot measure the performance gain.
|
||||
# DPT_HANDLE_TIMEOUTS Normally device timeouts are handled by the DPT.
|
||||
@ -1585,6 +1589,15 @@ options SPX_HACK
|
||||
# any interrupt that got lost. Seems to help in some
|
||||
# DPT-firmware/Motherboard combinations. Minimal
|
||||
# cost, great benefit.
|
||||
# DPT_RESET_HBA Make "reset" actually reset the controller
|
||||
# instead of fudging it. Only enable this if you
|
||||
# are 100% certain you need it.
|
||||
# DPT_SHUTDOWN_SLEEP Reset controller if a request take more than
|
||||
# this number of seconds. Do NOT enable this
|
||||
# unless you are really, really, really certain
|
||||
# you need it. You are advised to call Simon (the
|
||||
# driver author) before setting it, and NEVER,
|
||||
# EVER set it to less than 300s (5 minutes).
|
||||
|
||||
controller dpt0
|
||||
|
||||
@ -1597,3 +1610,8 @@ options DPT_HANDLE_TIMEOUTS
|
||||
options DPT_TIMEOUT_FACTOR=4
|
||||
options DPT_INTR_DELAY=200 # Some motherboards need that
|
||||
options DPT_LOST_IRQ
|
||||
options DPT_RESET_HBA
|
||||
|
||||
# Don't EVER set this without having talked to Simon Shapiro on the phone
|
||||
# first.
|
||||
options DPT_SHUTDOWN_SLEEP=500
|
||||
|
@ -2,7 +2,7 @@
|
||||
# LINT -- config file for checking all the sources, tries to pull in
|
||||
# as much of the source tree as it can.
|
||||
#
|
||||
# $Id: LINT,v 1.448 1998/08/03 19:14:31 msmith Exp $
|
||||
# $Id: LINT,v 1.449 1998/08/04 21:44:08 brian Exp $
|
||||
#
|
||||
# NB: You probably don't want to try running a kernel built from this
|
||||
# file. Instead, you should start from GENERIC, and add options from
|
||||
@ -1560,6 +1560,10 @@ options SPX_HACK
|
||||
|
||||
# The 'dpt' driver provides support for DPT controllers (http://www.dpt.com/).
|
||||
# These have hardware RAID-{0,1,5} support, and do multi-initiator I/O.
|
||||
# The DPT controllers are commonly re-licensed under other brand-names -
|
||||
# some controllers by Olivetti, Dec, HP, AT&T, SNI, AST, Alphatronic, NEC and
|
||||
# Compaq are actually DPT controllers.
|
||||
#
|
||||
# See sys/dev/dpt for debugging and other subtle options.
|
||||
# DPT_VERIFY_HINTR Performs some strict hardware interrupts testing.
|
||||
# Only use if you suspect PCI bus corruption problems
|
||||
@ -1569,9 +1573,9 @@ options SPX_HACK
|
||||
# slots to exactly what the DPT can hold at one time,
|
||||
# enable this option.
|
||||
# DPT_MEASURE_PERFORMANCE Enables a set of (semi)invasive metrics. Various
|
||||
# instruments are enabled. Assumed to be enabled by
|
||||
# /usr/sbin/dpt_* tools.
|
||||
# DPT_FREELIST_IS_STACK For optimat L{1,2} CPU cache utilization, enable
|
||||
# instruments are enabled. The tools in
|
||||
# /usr/sbin/dpt_* assume these to be enabled.
|
||||
# DPT_FREELIST_IS_STACK For optimal L{1,2} CPU cache utilization, enable
|
||||
# this option. Otherwise, the transaction queue is
|
||||
# a LIFO. I cannot measure the performance gain.
|
||||
# DPT_HANDLE_TIMEOUTS Normally device timeouts are handled by the DPT.
|
||||
@ -1585,6 +1589,15 @@ options SPX_HACK
|
||||
# any interrupt that got lost. Seems to help in some
|
||||
# DPT-firmware/Motherboard combinations. Minimal
|
||||
# cost, great benefit.
|
||||
# DPT_RESET_HBA Make "reset" actually reset the controller
|
||||
# instead of fudging it. Only enable this if you
|
||||
# are 100% certain you need it.
|
||||
# DPT_SHUTDOWN_SLEEP Reset controller if a request take more than
|
||||
# this number of seconds. Do NOT enable this
|
||||
# unless you are really, really, really certain
|
||||
# you need it. You are advised to call Simon (the
|
||||
# driver author) before setting it, and NEVER,
|
||||
# EVER set it to less than 300s (5 minutes).
|
||||
|
||||
controller dpt0
|
||||
|
||||
@ -1597,3 +1610,8 @@ options DPT_HANDLE_TIMEOUTS
|
||||
options DPT_TIMEOUT_FACTOR=4
|
||||
options DPT_INTR_DELAY=200 # Some motherboards need that
|
||||
options DPT_LOST_IRQ
|
||||
options DPT_RESET_HBA
|
||||
|
||||
# Don't EVER set this without having talked to Simon Shapiro on the phone
|
||||
# first.
|
||||
options DPT_SHUTDOWN_SLEEP=500
|
||||
|
@ -34,7 +34,7 @@
|
||||
* caveats: We may need an eisa and an isa files too
|
||||
*/
|
||||
|
||||
#ident "$Id: dpt_pci.c,v 1.5 1998/03/11 00:30:16 julian Exp $"
|
||||
#ident "$Id: dpt_pci.c,v 1.6 1998/06/02 00:32:38 eivind Exp $"
|
||||
|
||||
#include "opt_devfs.h"
|
||||
#include "opt_dpt.h"
|
||||
@ -213,21 +213,7 @@ dpt_pci_attach(pcici_t config_id, int unit)
|
||||
dpt->commands_processed = 0;
|
||||
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
/* Zero out all command counters */
|
||||
bzero((void *)&dpt->performance, sizeof(dpt_perf_t));
|
||||
for ( ndx = 0; ndx < 256; ndx ++ )
|
||||
dpt->performance.min_command_time[ndx] = BIG_ENOUGH;
|
||||
|
||||
dpt->performance.min_intr_time = BIG_ENOUGH;
|
||||
dpt->performance.min_waiting_time = BIG_ENOUGH;
|
||||
dpt->performance.min_submit_time = BIG_ENOUGH;
|
||||
dpt->performance.min_complete_time = BIG_ENOUGH;
|
||||
dpt->performance.min_eata_tries = BIG_ENOUGH;
|
||||
|
||||
for (ndx = 0; ndx < 10; ndx++ ) {
|
||||
dpt->performance.read_by_size_min_time[ndx] = BIG_ENOUGH;
|
||||
dpt->performance.write_by_size_min_time[ndx] = BIG_ENOUGH;
|
||||
}
|
||||
dpt_reset_performance(dpt);
|
||||
#endif /* DPT_MEASURE_PERFORMANCE */
|
||||
|
||||
dpt->unit = unit;
|
||||
@ -481,14 +467,13 @@ dpt_pci_attach(pcici_t config_id, int unit)
|
||||
* We never get the entries made.
|
||||
*/
|
||||
#ifdef DEVFS
|
||||
dpt->devfs_data_token = devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d", dpt->unit);
|
||||
dpt->devfs_ctl_token = devfs_add_devswf(&dpt_cdevsw,
|
||||
dpt->unit | SCSI_CONTROL_MASK,
|
||||
DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d.ctl", dpt->unit);
|
||||
(void) devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d", dpt->unit);
|
||||
(void) devfs_add_devswf(&dpt_cdevsw, dpt->unit | SCSI_CONTROL_MASK,
|
||||
DV_CHR,
|
||||
UID_ROOT, GID_WHEEL, 0600,
|
||||
"dpt%d.ctl", dpt->unit);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
179
sys/sys/dpt.h
179
sys/sys/dpt.h
@ -40,7 +40,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#ident "$Id: dpt.h,v 1.2 1998/04/15 17:47:28 bde Exp $"
|
||||
#ident "$Id: dpt.h,v 1.3 1998/06/02 00:32:37 eivind Exp $"
|
||||
|
||||
#ifndef _DPT_H
|
||||
#define _DPT_H
|
||||
@ -63,14 +63,14 @@ extern u_long dpt_unit;
|
||||
|
||||
#define DPT_RELEASE 1
|
||||
#define DPT_VERSION 4
|
||||
#define DPT_PATCH 3
|
||||
#define DPT_MONTH 6
|
||||
#define DPT_DAY 1
|
||||
#define DPT_PATCH 5
|
||||
#define DPT_MONTH 8
|
||||
#define DPT_DAY 3
|
||||
#define DPT_YEAR 18 /* 1998 - 1980 */
|
||||
|
||||
#define DPT_CTL_RELEASE 1
|
||||
#define DPT_CTL_VERSION 0
|
||||
#define DPT_CTL_PATCH 5
|
||||
#define DPT_CTL_PATCH 6
|
||||
|
||||
#ifndef PAGESIZ
|
||||
#define PAGESIZ 4096
|
||||
@ -229,6 +229,8 @@ typedef void *physaddr;
|
||||
#define EATA_CMD_PIO_TRUNC 0xf4
|
||||
|
||||
#define EATA_CMD_RESET 0xf9
|
||||
#define EATA_COLD_BOOT 0x06 /* Last resort only! */
|
||||
|
||||
#define EATA_CMD_IMMEDIATE 0xfa
|
||||
|
||||
#define EATA_CMD_DMA_READ_CONFIG 0xfd
|
||||
@ -452,88 +454,88 @@ typedef struct eata_register { /* EATA register set */
|
||||
* Everything back.
|
||||
*/
|
||||
typedef struct get_conf { /* Read Configuration Array */
|
||||
union {
|
||||
struct {
|
||||
u_int8_t foo_DevType;
|
||||
u_int8_t foo_PageCode;
|
||||
u_int8_t foo_Reserved0;
|
||||
u_int8_t foo_len;
|
||||
} foo;
|
||||
u_int32_t foo_length; /* Should return 0x22, 0x24, etc */
|
||||
} bar;
|
||||
union {
|
||||
struct {
|
||||
u_int8_t foo_DevType;
|
||||
u_int8_t foo_PageCode;
|
||||
u_int8_t foo_Reserved0;
|
||||
u_int8_t foo_len;
|
||||
} foo;
|
||||
u_int32_t foo_length; /* Should return 0x22, 0x24, etc */
|
||||
} bar;
|
||||
|
||||
#define gcs_length bar.foo_length
|
||||
#define gcs_PageCode bar.foo.foo_DevType
|
||||
#define gcs_reserved0 bar.foo.foo_Reserved0
|
||||
#define gcs_len bar.foo.foo_len
|
||||
|
||||
u_int32_t signature; /* Signature MUST be "EATA". ntohl()`ed */
|
||||
u_int32_t signature; /* Signature MUST be "EATA". ntohl()`ed */
|
||||
|
||||
u_int8_t version2:4,
|
||||
version:4; /* EATA Version level */
|
||||
u_int8_t version2:4,
|
||||
version:4; /* EATA Version level */
|
||||
|
||||
u_int8_t OCS_enabled:1, /* Overlap Command Support enabled */
|
||||
TAR_support:1, /* SCSI Target Mode supported */
|
||||
TRNXFR:1, /*
|
||||
* Truncate Transfer Cmd not necessary Only
|
||||
* used in PIO Mode
|
||||
*/
|
||||
MORE_support:1, /* MORE supported (only PIO Mode) */
|
||||
DMA_support:1, /* DMA supported Driver uses only this mode */
|
||||
DMA_valid:1, /* DRQ value in Byte 30 is valid */
|
||||
ATA:1, /* ATA device connected (not supported) */
|
||||
HAA_valid:1; /* Hostadapter Address is valid */
|
||||
u_int8_t OCS_enabled:1, /* Overlap Command Support enabled */
|
||||
TAR_support:1, /* SCSI Target Mode supported */
|
||||
TRNXFR:1, /*
|
||||
* Truncate Transfer Cmd not necessary Only
|
||||
* used in PIO Mode
|
||||
*/
|
||||
MORE_support:1, /* MORE supported (only PIO Mode) */
|
||||
DMA_support:1, /* DMA supported Driver uses only this mode */
|
||||
DMA_valid:1, /* DRQ value in Byte 30 is valid */
|
||||
ATA:1, /* ATA device connected (not supported) */
|
||||
HAA_valid:1; /* Hostadapter Address is valid */
|
||||
|
||||
u_int16_t cppadlen; /*
|
||||
* Number of pad bytes send after CD data set
|
||||
* to zero for DMA commands. Ntohl()`ed
|
||||
*/
|
||||
u_int8_t scsi_idS; /* SCSI ID of controller 2-0 Byte 0 res. */
|
||||
u_int8_t scsi_id2; /* If not, zero is returned */
|
||||
u_int8_t scsi_id1;
|
||||
u_int8_t scsi_id0;
|
||||
u_int32_t cplen; /* CP length: number of valid cp bytes */
|
||||
u_int16_t cppadlen; /*
|
||||
* Number of pad bytes send after CD data set
|
||||
* to zero for DMA commands. Ntohl()`ed
|
||||
*/
|
||||
u_int8_t scsi_idS; /* SCSI ID of controller 2-0 Byte 0 res. */
|
||||
u_int8_t scsi_id2; /* If not, zero is returned */
|
||||
u_int8_t scsi_id1;
|
||||
u_int8_t scsi_id0;
|
||||
u_int32_t cplen; /* CP length: number of valid cp bytes */
|
||||
|
||||
u_int32_t splen; /*
|
||||
* Number of bytes returned after we receive
|
||||
* SP command
|
||||
*/
|
||||
u_int16_t queuesiz; /* max number of queueable CPs */
|
||||
u_int32_t splen; /*
|
||||
* Number of bytes returned after we receive
|
||||
* SP command
|
||||
*/
|
||||
u_int16_t queuesiz; /* max number of queueable CPs */
|
||||
|
||||
u_int16_t dummy;
|
||||
u_int16_t SGsiz; /* max number of SG table entrie */
|
||||
u_int16_t dummy;
|
||||
u_int16_t SGsiz; /* max number of SG table entrie */
|
||||
|
||||
u_int8_t IRQ:4, /* IRQ used this HBA */
|
||||
IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
|
||||
SECOND:1, /* This is a secondary controller */
|
||||
DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */
|
||||
u_int8_t IRQ:4, /* IRQ used this HBA */
|
||||
IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
|
||||
SECOND:1, /* This is a secondary controller */
|
||||
DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */
|
||||
|
||||
u_int8_t sync; /*
|
||||
* device at ID 7 tru 0 is running in
|
||||
* synchronous mode, this will disappear
|
||||
*/
|
||||
u_int8_t DSBLE:1, /* ISA i/o addressing is disabled */
|
||||
FORCADR:1, /* i/o address has been forced */
|
||||
SG_64K:1,
|
||||
SG_UAE:1,:4;
|
||||
u_int8_t sync; /*
|
||||
* device at ID 7 tru 0 is running in
|
||||
* synchronous mode, this will disappear
|
||||
*/
|
||||
u_int8_t DSBLE:1, /* ISA i/o addressing is disabled */
|
||||
FORCADR:1, /* i/o address has been forced */
|
||||
SG_64K:1,
|
||||
SG_UAE:1,:4;
|
||||
|
||||
u_int8_t MAX_ID:5, /* Max number of SCSI target IDs */
|
||||
MAX_CHAN:3; /* Number of SCSI busses on HBA */
|
||||
u_int8_t MAX_ID:5, /* Max number of SCSI target IDs */
|
||||
MAX_CHAN:3; /* Number of SCSI busses on HBA */
|
||||
|
||||
u_int8_t MAX_LUN; /* Max number of LUNs */
|
||||
u_int8_t :3,
|
||||
AUTOTRM:1,
|
||||
M1_inst:1,
|
||||
ID_qest:1, /* Raidnum ID is questionable */
|
||||
is_PCI:1, /* HBA is PCI */
|
||||
is_EISA:1; /* HBA is EISA */
|
||||
u_int8_t MAX_LUN; /* Max number of LUNs */
|
||||
u_int8_t :3,
|
||||
AUTOTRM:1,
|
||||
M1_inst:1,
|
||||
ID_qest:1, /* Raidnum ID is questionable */
|
||||
is_PCI:1, /* HBA is PCI */
|
||||
is_EISA:1; /* HBA is EISA */
|
||||
|
||||
u_int8_t RAIDNUM; /* unique HBA identifier */
|
||||
u_int8_t unused[4]; /* When doing PIO, you GET 512 bytes */
|
||||
u_int8_t RAIDNUM; /* unique HBA identifier */
|
||||
u_int8_t unused[4]; /* When doing PIO, you GET 512 bytes */
|
||||
|
||||
/* >>------>> End of The DPT structure <<------<< */
|
||||
/* >>------>> End of The DPT structure <<------<< */
|
||||
|
||||
u_int32_t length; /* True length, after ntohl conversion */
|
||||
u_int32_t length; /* True length, after ntohl conversion */
|
||||
} dpt_conf_t;
|
||||
|
||||
/* Scatter-Gather list entry */
|
||||
@ -1055,6 +1057,9 @@ typedef struct dpt_metrics {
|
||||
#define SIZE_OTHER 9
|
||||
|
||||
struct timeval intr_started;
|
||||
|
||||
u_int32_t warm_starts;
|
||||
u_int32_t cold_boots;
|
||||
} dpt_perf_t;
|
||||
#endif
|
||||
|
||||
@ -1186,14 +1191,13 @@ typedef struct dpt_softc {
|
||||
* This isi most visible with usr/sbin/dpt_softc(8)
|
||||
*/
|
||||
|
||||
#ifdef DEVFS
|
||||
void *devfs_data_token;
|
||||
void *devfs_ctl_token;
|
||||
#endif
|
||||
#ifdef DPT_MEASURE_PERFORMANCE
|
||||
dpt_perf_t performance;
|
||||
#endif
|
||||
|
||||
#ifdef DPT_RESET_HBA
|
||||
struct timeval last_contact;
|
||||
#endif
|
||||
} dpt_softc_t;
|
||||
|
||||
/* This structure is used to pass dpt_softc contents to userland via the
|
||||
@ -1268,6 +1272,31 @@ typedef struct dpt_user_softc {
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef KERNEL
|
||||
/* This function gets the current hi-res time and returns it to the caller */
|
||||
static __inline struct timeval
|
||||
dpt_time_now(void)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
microtime(&now);
|
||||
return(now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a minor device number, get its SCSI Unit.
|
||||
*/
|
||||
|
||||
static __inline int
|
||||
dpt_minor2unit(int minor)
|
||||
{
|
||||
return(minor2hba(minor & ~SCSI_CONTROL_MASK));
|
||||
}
|
||||
|
||||
dpt_softc_t *dpt_minor2softc(int minor_no);
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
/*
|
||||
* This function substracts one timval structure from another,
|
||||
* Returning the result in usec.
|
||||
@ -1288,11 +1317,13 @@ dpt_time_delta(struct timeval start,
|
||||
return ( (end.tv_sec - start.tv_sec) * 1000000 +
|
||||
(end.tv_usec - start.tv_usec) );
|
||||
}
|
||||
|
||||
#ifndef _DPT_C_
|
||||
|
||||
extern TAILQ_HEAD(, dpt_softc) dpt_softc_list;
|
||||
|
||||
extern int dpt_controllers_present;
|
||||
|
||||
extern void hex_dump(u_char * data, int length,
|
||||
char *name, int no);
|
||||
extern char *i2bin(unsigned int no, int length);
|
||||
@ -1336,5 +1367,7 @@ extern int dpt_send_buffer(int unit,
|
||||
|
||||
#endif /* _DPT_C_ */
|
||||
|
||||
void dpt_reset_performance(dpt_softc_t *dpt);
|
||||
|
||||
#endif /* _DPT_H */
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
/* dpt_ctlinfo.c: Dunp a DPT HBA Information Block */
|
||||
|
||||
#ident "$Id: dpt_ctlinfo.c,v 1.1 1998/01/22 23:32:27 ShimonR Exp ShimonR $"
|
||||
#ident "$Id: dpt_ctlinfo.c,v 1.1 1998/01/26 06:20:37 julian Exp $"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
@ -73,17 +73,19 @@ main(int argc, char **argv, char **argp)
|
||||
pass_thru.command_buffer = (u_int8_t *)&compat_softc;
|
||||
|
||||
if ( (result = ioctl(fd, DPT_IOCTL_SEND, &pass_thru)) != 0 ) {
|
||||
(void)fprintf(stderr, "%s ERROR: Failed to send IOCTL %x - %s\n",
|
||||
argv[0], DPT_IOCTL_SEND,
|
||||
strerror(errno));
|
||||
(void)fprintf(stderr, "%s ERROR: Failed to send IOCTL "
|
||||
"%lx - %s\n",
|
||||
argv[0], DPT_IOCTL_SEND,
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void)fprintf(stdout, "%x:", compat_softc.ha_state);
|
||||
|
||||
for (ndx = 0; ndx < MAX_CHANNELS; ndx++)
|
||||
(void)fprintf(stdout, (ndx == (MAX_CHANNELS - 1)) ? "%d:" : "%d,",
|
||||
compat_softc.ha_id[ndx]);
|
||||
(void)fprintf(stdout, (ndx == (MAX_CHANNELS - 1)) ? "%d:" :
|
||||
"%d,",
|
||||
compat_softc.ha_id[ndx]);
|
||||
|
||||
(void)fprintf(stdout, "%d:", compat_softc.ha_vect);
|
||||
(void)fprintf(stdout, "%x:", compat_softc.ha_base);
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
/* dpt_ctls.c: Dunp a the number of configured DPT HBAs */
|
||||
|
||||
#ident "$Id: dpt_ctls.c,v 1.1 1998/01/22 22:07:22 ShimonR Exp ShimonR $"
|
||||
#ident "$Id: dpt_ctls.c,v 1.1 1998/01/26 06:20:39 julian Exp $"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
@ -69,9 +69,10 @@ main(int argc, char **argv, char **argp)
|
||||
pass_thru.command_buffer = (u_int8_t *)&controllers_present;
|
||||
|
||||
if ( (result = ioctl(fd, DPT_IOCTL_SEND, &pass_thru)) != 0 ) {
|
||||
(void)fprintf(stderr, "%s ERROR: Failed to send IOCTL %x - %s\n",
|
||||
argv[0], DPT_IOCTL_SEND,
|
||||
strerror(errno));
|
||||
(void)fprintf(stderr, "%s ERROR: Failed to send IOCTL "
|
||||
"%lx - %s\n",
|
||||
argv[0], DPT_IOCTL_SEND,
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,13 @@
|
||||
|
||||
/* dpt_dm.c: Dump a DPT metrics structure */
|
||||
|
||||
#ident "$Id: dpt_dm.c,v 1.8 1998/01/21 17:38:32 ShimonR Exp ShimonR $"
|
||||
#ident "$Id: dpt_dm.c,v 1.1 1998/08/03 16:43:36 root Exp root $"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/queue.h>
|
||||
@ -231,6 +232,19 @@ scsi_cmd_name(u_int8_t cmd)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
tmpsprintf(int buffer, const char *format, ...)
|
||||
{
|
||||
static char buffers[16][16];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffers[buffer], 16, format, ap);
|
||||
va_end(ap);
|
||||
return buffers[buffer];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv, char **argp)
|
||||
{
|
||||
@ -246,27 +260,31 @@ main(int argc, char **argv, char **argp)
|
||||
}
|
||||
|
||||
if ( (result = ioctl(fd, DPT_IOCTL_INTERNAL_METRICS, &metrics)) != 0 ) {
|
||||
(void)fprintf(stderr, "%s ERROR: Failed to send IOCTL %x - %s\n",
|
||||
(void)fprintf(stderr, "%s ERROR: Failed to send IOCTL %lx - %s\n",
|
||||
argv[0], DPT_IOCTL_INTERNAL_METRICS,
|
||||
strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* Interrupt related measurements */
|
||||
(void)fprintf(stdout, "Interrupts:%d:%d:%d:%d\n\nCommands:\n",
|
||||
(void)fprintf(stdout, "Interrupts:%u:%u:%s:%u\n\nCommands:\n",
|
||||
metrics.aborted_interrupts,
|
||||
metrics.spurious_interrupts,
|
||||
metrics.min_intr_time,
|
||||
metrics.min_intr_time == BIG_ENOUGH ?
|
||||
"N/A" :
|
||||
tmpsprintf(0, "%u", metrics.min_intr_time),
|
||||
metrics.max_intr_time);
|
||||
|
||||
/* SCSI Commands, can be no more than 256 of them */
|
||||
for (ndx = 0; ndx < 256; ndx++) {
|
||||
if (metrics.command_count[ndx] != 0) {
|
||||
(void)fprintf(stdout, "%d:%s:%d:%d:%d\n",
|
||||
(void)fprintf(stdout, "%u:%s:%u:%s:%d\n",
|
||||
ndx,
|
||||
scsi_cmd_name((u_int8_t)ndx),
|
||||
metrics.command_count[ndx],
|
||||
metrics.min_command_time[ndx],
|
||||
metrics.min_command_time[ndx] == BIG_ENOUGH ?
|
||||
"N/A" :
|
||||
tmpsprintf(0, "%u", metrics.min_command_time[ndx]),
|
||||
metrics.max_command_time[ndx]);
|
||||
}
|
||||
}
|
||||
@ -370,22 +388,30 @@ main(int argc, char **argv, char **argp)
|
||||
|
||||
}
|
||||
|
||||
(void)fprintf(stdout, "\nQueues:%u:%u:%u:%u:%u:%u:%u:%u:%u\n",
|
||||
(void)fprintf(stdout, "\nQueues:%u:%s:%u:%u:%s:%u:%u:%s:%u\n",
|
||||
metrics.max_waiting_count,
|
||||
metrics.min_waiting_time,
|
||||
metrics.min_waiting_time == BIG_ENOUGH ?
|
||||
"N/A" :
|
||||
tmpsprintf(0, "%u", metrics.min_waiting_time),
|
||||
metrics.max_waiting_time,
|
||||
metrics.max_submit_count,
|
||||
metrics.min_submit_time,
|
||||
metrics.min_submit_time == BIG_ENOUGH ?
|
||||
"N/A" :
|
||||
tmpsprintf(1, "%u", metrics.min_submit_time),
|
||||
metrics.max_submit_time,
|
||||
metrics.max_complete_count,
|
||||
metrics.min_complete_time,
|
||||
metrics.min_complete_time == BIG_ENOUGH ?
|
||||
"N/A" :
|
||||
tmpsprintf(2, "%u", metrics.min_complete_time),
|
||||
metrics.max_complete_time);
|
||||
|
||||
(void)fprintf(stdout, "Hardware Ports:%u:%u:%u:%u\n",
|
||||
(void)fprintf(stdout, "Hardware Ports:%u:%u:%u:%s\n",
|
||||
metrics.command_collisions,
|
||||
metrics.command_too_busy,
|
||||
metrics.max_eata_tries,
|
||||
metrics.min_eata_tries);
|
||||
metrics.min_eata_tries == BIG_ENOUGH ?
|
||||
"N/A" :
|
||||
tmpsprintf(0, "%u", metrics.min_eata_tries));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user