Add support for dynamic rescan of cache service logical drives, using

the ioctl issued by the ICP RAID management libraries (used by the
storcon and iirconfig tools).  This requires some infrastructure changes:
* Add a "service callback" mechanism that the ld driver (cache service)
  and the iopsp driver (raw service) can register with the icp parent.
  Right now this callback allows the children to adjust their notion of
  how many command openings are available.
* Add a mutex around the icp ioctl handler, allowing only one thread
  to execute an ioctl at a time.
* Add a way to freeze the controller command queue.  We stop all I/O
  while processing rescans (due to the semantics of icp_cmd()).
* Make icp_cmd() work when !cold.
* Add detach support to ld@icp.
This commit is contained in:
thorpej 2003-06-13 05:57:30 +00:00
parent f7f6440dff
commit 3178a4f415
7 changed files with 399 additions and 49 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: icp.c,v 1.9 2003/05/17 15:34:12 thorpej Exp $ */
/* $NetBSD: icp.c,v 1.10 2003/06/13 05:57:30 thorpej Exp $ */
/*-
* Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@ -76,11 +76,14 @@
*
* Support for the ICP-Vortex management tools added by
* Jason R. Thorpe of Wasabi Systems, Inc., based on code
* provided by Achim Leubner <achim.leubner@intel.com>
* provided by Achim Leubner <achim.leubner@intel.com>.
*
* Additional support for dynamic rescan of cacheservice drives by
* Jason R. Thorpe of Wasabi Systems, Inc.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: icp.c,v 1.9 2003/05/17 15:34:12 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: icp.c,v 1.10 2003/06/13 05:57:30 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -115,6 +118,7 @@ int icp_print(void *, const char *);
int icp_submatch(struct device *, struct cfdata *, void *);
void icp_watchdog(void *);
void icp_ucmd_intr(struct icp_ccb *);
void icp_recompute_openings(struct icp_softc *);
int icp_count; /* total # of controllers, for ioctl interface */
@ -133,11 +137,9 @@ icp_init(struct icp_softc *icp, const char *intrstr)
struct icp_binfo binfo;
struct icp_ccb *ic;
u_int16_t cdev_cnt;
int i, j, state, feat, nsegs, rv, noscsi, nocache;
int i, j, state, feat, nsegs, rv;
state = 0;
noscsi = 0;
nocache = 0;
if (intrstr != NULL)
aprint_normal("%s: interrupting at %s\n", icp->icp_dv.dv_xname,
@ -267,8 +269,8 @@ icp_init(struct icp_softc *icp, const char *intrstr)
"%s: scatter/gather not supported (raw service)\n",
icp->icp_dv.dv_xname);
#endif
noscsi = 1;
}
} else
icp->icp_features |= ICP_FEAT_RAWSERVICE;
/*
* Set/get cache service features (scatter/gather).
@ -285,8 +287,8 @@ icp_init(struct icp_softc *icp, const char *intrstr)
"%s: scatter/gather not supported (cache service)\n",
icp->icp_dv.dv_xname);
#endif
nocache = 1;
}
} else
icp->icp_features |= ICP_FEAT_CACHESERVICE;
/*
* Pull some information from the board and dump.
@ -308,14 +310,15 @@ icp_init(struct icp_softc *icp, const char *intrstr)
* Determine the number of devices, and number of openings per
* device.
*/
if (!nocache) {
if (icp->icp_features & ICP_FEAT_CACHESERVICE) {
for (j = 0; j < cdev_cnt && j < ICP_MAX_HDRIVES; j++) {
if (!icp_cmd(icp, ICP_CACHESERVICE, ICP_INFO, j, 0,
0))
continue;
icp->icp_cdr[j].cd_size = icp->icp_info;
icp->icp_ndevs++;
if (icp->icp_cdr[j].cd_size != 0)
icp->icp_ndevs++;
if (icp_cmd(icp, ICP_CACHESERVICE, ICP_DEVTYPE, j, 0,
0))
@ -323,21 +326,17 @@ icp_init(struct icp_softc *icp, const char *intrstr)
}
}
if (!noscsi)
icp->icp_ndevs += binfo.bi_chan_count;
if (icp->icp_features & ICP_FEAT_RAWSERVICE) {
icp->icp_nchan = binfo.bi_chan_count;
icp->icp_ndevs += icp->icp_nchan;
}
if (icp->icp_ndevs != 0)
icp->icp_openings =
(icp->icp_nccbs - ICP_NCCB_RESERVE) / icp->icp_ndevs;
#ifdef ICP_DEBUG
aprint_debug("%s: %d openings per device\n", icp->icp_dv.dv_xname,
icp->icp_openings);
#endif
icp_recompute_openings(icp);
/*
* Attach SCSI channels.
*/
if (!noscsi) {
if (icp->icp_features & ICP_FEAT_RAWSERVICE) {
struct icp_ioc_version *iv;
struct icp_rawioc *ri;
struct icp_getch *gc;
@ -380,7 +379,8 @@ icp_init(struct icp_softc *icp, const char *intrstr)
icp->icp_bus_id[j] = ICP_MAXID_FC;
icpa.icpa_unit = j + ICPA_UNIT_SCSI;
config_found_sm(&icp->icp_dv, &icpa, icp_print,
icp->icp_children[icpa.icpa_unit] =
config_found_sm(&icp->icp_dv, &icpa, icp_print,
icp_submatch);
}
}
@ -388,13 +388,14 @@ icp_init(struct icp_softc *icp, const char *intrstr)
/*
* Attach cache devices.
*/
if (!nocache) {
if (icp->icp_features & ICP_FEAT_CACHESERVICE) {
for (j = 0; j < cdev_cnt && j < ICP_MAX_HDRIVES; j++) {
if (icp->icp_cdr[j].cd_size == 0)
continue;
icpa.icpa_unit = j;
config_found_sm(&icp->icp_dv, &icpa, icp_print,
icp->icp_children[icpa.icpa_unit] =
config_found_sm(&icp->icp_dv, &icpa, icp_print,
icp_submatch);
}
}
@ -430,6 +431,165 @@ icp_init(struct icp_softc *icp, const char *intrstr)
return (1);
}
void
icp_register_servicecb(struct icp_softc *icp, int unit,
const struct icp_servicecb *cb)
{
icp->icp_servicecb[unit] = cb;
}
void
icp_rescan(struct icp_softc *icp, int unit)
{
struct icp_attach_args icpa;
u_int newsize, newtype;
/*
* NOTE: It is very important that the queue be frozen and not
* commands running when this is called. The ioctl mutex must
* also be held.
*/
KASSERT(icp->icp_qfreeze != 0);
KASSERT(icp->icp_running == 0);
KASSERT(unit < ICP_MAX_HDRIVES);
if (!icp_cmd(icp, ICP_CACHESERVICE, ICP_INFO, unit, 0, 0)) {
#ifdef ICP_DEBUG
printf("%s: rescan: unit %d ICP_INFO failed -> 0x%04x\n",
icp->icp_dv.dv_xname, unit, icp->icp_status);
#endif
goto gone;
}
if ((newsize = icp->icp_info) == 0) {
#ifdef ICP_DEBUG
printf("%s: rescan: unit %d has zero size\n",
icp->icp_dv.dv_xname, unit);
#endif
gone:
/*
* Host drive is no longer present; detach if a child
* is currently there.
*/
if (icp->icp_cdr[unit].cd_size != 0)
icp->icp_ndevs--;
icp->icp_cdr[unit].cd_size = 0;
if (icp->icp_children[unit] != NULL) {
(void) config_detach(icp->icp_children[unit],
DETACH_FORCE);
icp->icp_children[unit] = NULL;
}
return;
}
if (icp_cmd(icp, ICP_CACHESERVICE, ICP_DEVTYPE, unit, 0, 0))
newtype = icp->icp_info;
else {
#ifdef ICP_DEBUG
printf("%s: rescan: unit %d ICP_DEVTYPE failed\n",
icp->icp_dv.dv_xname, unit);
#endif
newtype = 0; /* XXX? */
}
#ifdef ICP_DEBUG
printf("%s: rescan: unit %d old %u/%u, new %u/%u\n",
icp->icp_dv.dv_xname, unit, icp->icp_cdr[unit].cd_size,
icp->icp_cdr[unit].cd_type, newsize, newtype);
#endif
/*
* If the type or size changed, detach any old child (if it exists)
* and attach a new one.
*/
if (icp->icp_children[unit] == NULL ||
newsize != icp->icp_cdr[unit].cd_size ||
newtype != icp->icp_cdr[unit].cd_type) {
if (icp->icp_cdr[unit].cd_size == 0)
icp->icp_ndevs++;
icp->icp_cdr[unit].cd_size = newsize;
icp->icp_cdr[unit].cd_type = newtype;
if (icp->icp_children[unit] != NULL)
(void) config_detach(icp->icp_children[unit],
DETACH_FORCE);
icpa.icpa_unit = unit;
icp->icp_children[unit] = config_found_sm(&icp->icp_dv, &icpa,
icp_print, icp_submatch);
}
icp_recompute_openings(icp);
}
void
icp_rescan_all(struct icp_softc *icp)
{
int unit;
u_int16_t cdev_cnt;
/*
* This is the old method of rescanning the host drives. We
* start by reinitializing the cache service.
*/
if (!icp_cmd(icp, ICP_CACHESERVICE, ICP_INIT, ICP_LINUX_OS, 0, 0)) {
printf("%s: unable to re-initialize cache service for rescan\n",
icp->icp_dv.dv_xname);
return;
}
cdev_cnt = (u_int16_t) icp->icp_info;
/* For each host drive, do the new-style rescan. */
for (unit = 0; unit < cdev_cnt && unit < ICP_MAX_HDRIVES; unit++)
icp_rescan(icp, unit);
/* Now detach anything in the slots after cdev_cnt. */
for (; unit < ICP_MAX_HDRIVES; unit++) {
if (icp->icp_cdr[unit].cd_size != 0) {
#ifdef ICP_DEBUG
printf("%s: rescan all: unit %d < new cdev_cnt (%d)\n",
icp->icp_dv.dv_xname, unit, cdev_cnt);
#endif
icp->icp_ndevs--;
icp->icp_cdr[unit].cd_size = 0;
if (icp->icp_children[unit] != NULL) {
(void) config_detach(icp->icp_children[unit],
DETACH_FORCE);
icp->icp_children[unit] = NULL;
}
}
}
icp_recompute_openings(icp);
}
void
icp_recompute_openings(struct icp_softc *icp)
{
int unit, openings;
if (icp->icp_ndevs != 0)
openings =
(icp->icp_nccbs - ICP_NCCB_RESERVE) / icp->icp_ndevs;
else
openings = 0;
if (openings == icp->icp_openings)
return;
icp->icp_openings = openings;
#ifdef ICP_DEBUG
printf("%s: %d device%s, %d openings per device\n",
icp->icp_dv.dv_xname, icp->icp_ndevs,
icp->icp_ndevs == 1 ? "" : "s", icp->icp_openings);
#endif
for (unit = 0; unit < ICP_MAX_HDRIVES + ICP_MAXBUS; unit++) {
if (icp->icp_children[unit] != NULL)
(*icp->icp_servicecb[unit]->iscb_openings)(
icp->icp_children[unit], icp->icp_openings);
}
}
void
icp_watchdog(void *cookie)
{
@ -564,6 +724,17 @@ icp_intr(void *cookie)
panic("icp_intr: inactive CCB identified");
}
/*
* Try to protect ourselves from the running command count already
* being 0 (e.g. if a polled command times out).
*/
KDASSERT(icp->icp_running != 0);
if (--icp->icp_running == 0 &&
(icp->icp_flags & ICP_F_WAIT_FREEZE) != 0) {
icp->icp_flags &= ~ICP_F_WAIT_FREEZE;
wakeup(&icp->icp_qfreeze);
}
switch (icp->icp_status) {
case ICP_S_BSY:
#ifdef ICP_DEBUG
@ -873,7 +1044,7 @@ icp_ccb_enqueue(struct icp_softc *icp, struct icp_ccb *ic)
SIMPLEQ_INSERT_TAIL(&icp->icp_ccb_queue, ic, ic_chain);
}
for (;;) {
for (; icp->icp_qfreeze == 0;) {
if (__predict_false((ic =
SIMPLEQ_FIRST(&icp->icp_ucmd_queue)) != NULL)) {
struct icp_ucmd_ctx *iu = ic->ic_context;
@ -973,7 +1144,9 @@ icp_ccb_unmap(struct icp_softc *icp, struct icp_ccb *ic)
int
icp_ccb_poll(struct icp_softc *icp, struct icp_ccb *ic, int timo)
{
int rv;
int s, rv;
s = splbio();
for (timo = ICP_BUSY_WAIT_MS * 100; timo != 0; timo--) {
if (!(*icp->icp_test_busy)(icp))
@ -987,11 +1160,22 @@ icp_ccb_poll(struct icp_softc *icp, struct icp_ccb *ic, int timo)
icp_ccb_submit(icp, ic);
for (timo *= 10; timo != 0; timo--) {
DELAY(100);
icp_intr(icp);
if ((ic->ic_flags & IC_COMPLETE) != 0)
break;
if (cold) {
for (timo *= 10; timo != 0; timo--) {
DELAY(100);
icp_intr(icp);
if ((ic->ic_flags & IC_COMPLETE) != 0)
break;
}
} else {
ic->ic_flags |= IC_WAITING;
while ((ic->ic_flags & IC_COMPLETE) == 0) {
if ((rv = tsleep(ic, PRIBIO, "icpwccb",
mstohz(timo))) != 0) {
timo = 0;
break;
}
}
}
if (timo != 0) {
@ -1011,6 +1195,8 @@ icp_ccb_poll(struct icp_softc *icp, struct icp_ccb *ic, int timo)
while ((*icp->icp_test_busy)(icp) != 0)
DELAY(10);
splx(s);
return (rv);
}
@ -1074,10 +1260,47 @@ icp_ccb_submit(struct icp_softc *icp, struct icp_ccb *ic)
ic->ic_cmd.cmd_boardnode = htole32(ICP_LOCALBOARD);
ic->ic_cmd.cmd_cmdindex = htole32(ic->ic_ident);
icp->icp_running++;
(*icp->icp_copy_cmd)(icp, ic);
(*icp->icp_release_event)(icp, ic);
}
int
icp_freeze(struct icp_softc *icp)
{
int s, error = 0;
s = splbio();
if (icp->icp_qfreeze++ == 0) {
while (icp->icp_running != 0) {
icp->icp_flags |= ICP_F_WAIT_FREEZE;
error = tsleep(&icp->icp_qfreeze, PRIBIO|PCATCH,
"icpqfrz", 0);
if (error != 0 && --icp->icp_qfreeze == 0 &&
ICP_HAS_WORK(icp)) {
icp_ccb_enqueue(icp, NULL);
break;
}
}
}
splx(s);
return (error);
}
void
icp_unfreeze(struct icp_softc *icp)
{
int s;
s = splbio();
KDASSERT(icp->icp_qfreeze != 0);
if (--icp->icp_qfreeze == 0 && ICP_HAS_WORK(icp))
icp_ccb_enqueue(icp, NULL);
splx(s);
}
/* XXX Global - should be per-controller? XXX */
static gdt_evt_str icp_event_buffer[ICP_MAX_EVENTS];
static int icp_event_oldidx;

View File

@ -1,4 +1,4 @@
/* $NetBSD: icp_ioctl.c,v 1.2 2003/05/18 06:18:25 thorpej Exp $ */
/* $NetBSD: icp_ioctl.c,v 1.3 2003/06/13 05:57:30 thorpej Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: icp_ioctl.c,v 1.2 2003/05/18 06:18:25 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: icp_ioctl.c,v 1.3 2003/06/13 05:57:30 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -105,6 +105,9 @@ const struct cdevsw icp_cdevsw = {
extern struct cfdriver icp_cd;
static struct lock icp_ioctl_mutex =
LOCK_INITIALIZER(PRIBIO|PCATCH, "icplk", 0, 0);
static int
icpopen(dev_t dev, int flag, int mode, struct proc *p)
{
@ -120,7 +123,10 @@ icpopen(dev_t dev, int flag, int mode, struct proc *p)
static int
icpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
int error = 0;
int error;
if ((error = lockmgr(&icp_ioctl_mutex, LK_EXCLUSIVE, NULL)) != 0)
return (error);
switch (cmd) {
case GDT_IOCTL_GENERAL:
@ -129,8 +135,10 @@ icpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
gdt_ucmd_t *ucmd = (void *) data;
icp = device_lookup(&icp_cd, ucmd->io_node);
if (icp == NULL)
return (ENXIO);
if (icp == NULL) {
error = ENXIO;
break;
}
error = icp_ucmd(icp, ucmd);
break;
@ -147,8 +155,10 @@ icpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
gdt_ctrt_t *p = (void *) data;
icp = device_lookup(&icp_cd, p->io_node);
if (icp == NULL)
return (ENXIO);
if (icp == NULL) {
error = ENXIO;
break;
}
/* XXX magic numbers */
p->oem_id = 0x8000;
@ -253,9 +263,34 @@ icpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
memcpy(&icp_stats, data, sizeof(gdt_statist_t));
break;
case GDT_IOCTL_RESCAN:
{
struct icp_softc *icp;
gdt_rescan_t *rsc = (void *) data;
icp = device_lookup(&icp_cd, rsc->io_node);
if (icp == NULL) {
error = ENXIO;
break;
}
error = icp_freeze(icp);
if (error)
break;
if (rsc->flag == 0)
icp_rescan_all(icp);
else
icp_rescan(icp, rsc->hdr_no);
icp_unfreeze(icp);
break;
}
default:
return (ENOTTY);
error = ENOTTY;
}
(void) lockmgr(&icp_ioctl_mutex, LK_RELEASE, NULL);
return (error);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: icp_ioctl.h,v 1.1 2003/05/13 15:42:34 thorpej Exp $ */
/* $NetBSD: icp_ioctl.h,v 1.2 2003/06/13 05:57:30 thorpej Exp $ */
/*
* Copyright (c) 2000-03 Intel Corporation
@ -171,4 +171,18 @@ typedef struct gdt_statist {
} __attribute__((__packed__)) gdt_statist_t;
#define GDT_IOCTL_STATIST _IOR('J', 9, gdt_statist_t)
/* rescan host drives */
typedef struct gdt_rescan {
u_int16_t io_node;
u_int8_t flag;
u_int16_t hdr_no;
struct {
u_int8_t bus;
u_int8_t target;
u_int8_t lun;
u_int8_t cluster_type;
} __attribute__((__packed__)) hdr_list[ICP_MAX_HDRIVES];
} __attribute__((__packed__)) gdt_rescan_t;
#define GDT_IOCTL_RESCAN _IOWR('J', 11, gdt_rescan_t)
#endif /* _DEV_IC_ICP_IOCTL_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: icpreg.h,v 1.2 2003/05/13 15:42:34 thorpej Exp $ */
/* $NetBSD: icpreg.h,v 1.3 2003/06/13 05:57:30 thorpej Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -71,7 +71,8 @@
#define _IC_ICPREG_H_
#define ICP_MAXBUS 6 /* XXX Why not 5? */
#define ICP_MAX_HDRIVES 35 /* 5 busses * 7 targets XXX correct? */
#define ICP_MAX_LDRIVES 255 /* max logical drive count */
#define ICP_MAX_HDRIVES 100 /* max host drive count */
#define ICP_MAXID_FC 127 /* Fibre-channel maximum ID */
#define ICP_MAXOFFSETS 128
#define ICP_MAXSG 17 /* Max. s/g elements; actually 128 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: icpsp.c,v 1.7 2003/05/13 15:42:34 thorpej Exp $ */
/* $NetBSD: icpsp.c,v 1.8 2003/06/13 05:57:31 thorpej Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: icpsp.c,v 1.7 2003/05/13 15:42:34 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: icpsp.c,v 1.8 2003/06/13 05:57:31 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -70,6 +70,7 @@ struct icpsp_softc {
struct scsipi_adapter sc_adapter;
struct scsipi_channel sc_channel;
int sc_busno;
int sc_openings;
};
void icpsp_attach(struct device *, struct device *, void *);
@ -78,9 +79,15 @@ int icpsp_match(struct device *, struct cfdata *, void *);
void icpsp_scsipi_request(struct scsipi_channel *, scsipi_adapter_req_t,
void *);
void icpsp_adjqparam(struct device *, int);
CFATTACH_DECL(icpsp, sizeof(struct icpsp_softc),
icpsp_match, icpsp_attach, NULL, NULL);
static const struct icp_servicecb icpsp_servicecb = {
icpsp_adjqparam,
};
int
icpsp_match(struct device *parent, struct cfdata *match, void *aux)
{
@ -103,8 +110,11 @@ icpsp_attach(struct device *parent, struct device *self, void *aux)
icp = (struct icp_softc *)parent;
sc->sc_busno = icpa->icpa_unit - ICPA_UNIT_SCSI;
sc->sc_openings = icp->icp_openings;
printf(": physical SCSI channel %d\n", sc->sc_busno);
icp_register_servicecb(icp, icpa->icpa_unit, &icpsp_servicecb);
sc->sc_adapter.adapt_dev = &sc->sc_dv;
sc->sc_adapter.adapt_nchannels = 1;
sc->sc_adapter.adapt_openings = icp->icp_openings;
@ -320,3 +330,15 @@ icpsp_intr(struct icp_ccb *ic)
icp_ccb_free(icp, ic);
scsipi_done(xs);
}
void
icpsp_adjqparam(struct device *dv, int openings)
{
struct icpsp_softc *sc = (struct icpsp_softc *) dv;
int s;
s = splbio();
sc->sc_adapter.adapt_openings += openings - sc->sc_openings;
sc->sc_openings = openings;
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: icpvar.h,v 1.2 2003/05/13 15:42:34 thorpej Exp $ */
/* $NetBSD: icpvar.h,v 1.3 2003/06/13 05:57:31 thorpej Exp $ */
/*-
* Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@ -104,6 +104,14 @@ struct icp_cachedrv {
u_int cd_type;
};
/*
* Call-backs into the service back-ends (ld for cache service,
* icpsp for raw service).
*/
struct icp_servicecb {
void (*iscb_openings)(struct device *, int);
};
/*
* Per-controller context.
*/
@ -124,8 +132,12 @@ struct icp_softc {
u_int8_t icp_bus_cnt;
u_int8_t icp_bus_id[ICP_MAXBUS];
struct icp_cachedrv icp_cdr[ICP_MAX_HDRIVES];
const struct icp_servicecb *icp_servicecb[ICP_MAX_HDRIVES + ICP_MAXBUS];
struct device *icp_children[ICP_MAX_HDRIVES + ICP_MAXBUS];
int icp_ndevs;
int icp_openings;
int icp_features;
int icp_nchan;
u_int32_t icp_info;
u_int32_t icp_info2;
@ -139,6 +151,8 @@ struct icp_softc {
struct icp_ccb *icp_ccbs;
u_int icp_nccbs;
u_int icp_flags;
u_int icp_qfreeze;
u_int icp_running;
SIMPLEQ_HEAD(,icp_ccb) icp_ccb_freelist;
SIMPLEQ_HEAD(,icp_ccb) icp_ccb_queue;
SIMPLEQ_HEAD(,icp_ccb) icp_ucmd_queue;
@ -167,8 +181,13 @@ struct icp_softc {
int icp_pci_subdevice_id;
};
/* icp_features */
#define ICP_FEAT_CACHESERVICE 0x01 /* cache service usable */
#define ICP_FEAT_RAWSERVICE 0x02 /* raw service usable */
/* icp_flags */
#define ICP_F_WAIT_CCB 0x01 /* someone waiting for CCBs */
#define ICP_F_WAIT_FREEZE 0x02 /* someone waiting for qfreeze */
#define ICP_HAS_WORK(icp) \
(! SIMPLEQ_EMPTY(&(icp)->icp_ccb_queue) || \
@ -234,6 +253,14 @@ int icp_ccb_wait_user(struct icp_softc *, struct icp_ccb *, int);
int icp_cmd(struct icp_softc *, u_int8_t, u_int16_t, u_int32_t, u_int32_t,
u_int32_t);
int icp_ucmd(struct icp_softc *, gdt_ucmd_t *);
int icp_freeze(struct icp_softc *);
void icp_unfreeze(struct icp_softc *);
void icp_rescan(struct icp_softc *, int);
void icp_rescan_all(struct icp_softc *);
void icp_register_servicecb(struct icp_softc *, int,
const struct icp_servicecb *);
gdt_evt_str *icp_store_event(struct icp_softc *, u_int16_t, u_int16_t,
gdt_evt_data *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ld_icp.c,v 1.7 2003/06/07 23:37:25 thorpej Exp $ */
/* $NetBSD: ld_icp.c,v 1.8 2003/06/13 05:57:31 thorpej Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ld_icp.c,v 1.7 2003/06/07 23:37:25 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: ld_icp.c,v 1.8 2003/06/13 05:57:31 thorpej Exp $");
#include "rnd.h"
@ -72,6 +72,7 @@ struct ld_icp_softc {
};
void ld_icp_attach(struct device *, struct device *, void *);
int ld_icp_detach(struct device *, int);
int ld_icp_dobio(struct ld_icp_softc *, void *, int, int, int,
struct buf *);
int ld_icp_dump(struct ld_softc *, void *, int, int);
@ -80,8 +81,14 @@ void ld_icp_intr(struct icp_ccb *);
int ld_icp_match(struct device *, struct cfdata *, void *);
int ld_icp_start(struct ld_softc *, struct buf *);
void ld_icp_adjqparam(struct device *, int);
CFATTACH_DECL(ld_icp, sizeof(struct ld_icp_softc),
ld_icp_match, ld_icp_attach, NULL, NULL);
ld_icp_match, ld_icp_attach, ld_icp_detach, NULL);
static const struct icp_servicecb ld_icp_servicecb = {
ld_icp_adjqparam,
};
int
ld_icp_match(struct device *parent, struct cfdata *match, void *aux)
@ -111,6 +118,8 @@ ld_icp_attach(struct device *parent, struct device *self, void *aux)
icpa = aux;
cd = &icp->icp_cdr[icpa->icpa_unit];
icp_register_servicecb(icp, icpa->icpa_unit, &ld_icp_servicecb);
sc->sc_hwunit = icpa->icpa_unit;
ld->sc_maxxfer = ICP_MAX_XFER;
ld->sc_secsize = ICP_SECTOR_SIZE;
@ -169,6 +178,18 @@ ld_icp_attach(struct device *parent, struct device *self, void *aux)
ldattach(ld);
}
int
ld_icp_detach(struct device *dv, int flags)
{
int rv;
if ((rv = ldbegindetach((struct ld_softc *)dv, flags)) != 0)
return (rv);
ldenddetach((struct ld_softc *) dv);
return (0);
}
int
ld_icp_dobio(struct ld_icp_softc *sc, void *data, int datasize, int blkno,
int dowrite, struct buf *bp)
@ -315,3 +336,10 @@ ld_icp_intr(struct icp_ccb *ic)
icp_ccb_free(icp, ic);
lddone(&sc->sc_ld, bp);
}
void
ld_icp_adjqparam(struct device *dv, int openings)
{
ldadjqparam((struct ld_softc *) dv, openings);
}