or if it should be used in conjunction with that... */
* or if it should be used in conjunction with that... */
RF_DECLARE_STATIC_MUTEX(rf_sparet_wait_mutex)/* requests to install a spare table */static RF_SparetWait_t *rf_sparet_wait_queue;/* responses from installation process */static RF_SparetWait_t *rf_sparet_resp_queue;/* prototypes */void	rf_KernelWakeupFunc __P((struct buf *));void	rf_InitBP __P((struct buf *, struct vnode *, unsigned, dev_t,	    RF_SectorNum_t, RF_SectorCount_t, caddr_t, void (*)(struct buf *),	    void *, int, struct proc *));static void raidinit __P((RF_Raid_t *));void	raidattach __P((int));int	raidsize __P((dev_t));int	raidopen __P((dev_t, int, int, struct proc *));int	raidclose __P((dev_t, int, int, struct proc *));int	raidioctl __P((dev_t, u_long, caddr_t, int, struct proc *));int	raidwrite __P((dev_t, struct uio *, int));int	raidread __P((dev_t, struct uio *, int));void	raidstrategy __P((struct buf *));int	raiddump __P((dev_t, daddr_t, caddr_t, size_t));/* * Pilfered from ccd.c */struct raidbuf {	struct buf rf_buf;	/* new I/O buf.	 MUST BE FIRST!!! */	struct buf *rf_obp;	/* ptr. to original I/O buf */	int	rf_flags;	/* misc. flags */	RF_DiskQueueData_t *req;/* the request that this was part of.. */};#define RAIDGETBUF() malloc(sizeof (struct raidbuf), M_RAIDFRAME, M_NOWAIT)#define	RAIDPUTBUF(buf) free(buf, M_RAIDFRAME)/* * XXX Not sure if the following should be replacing the raidPtrs above,   or if it should be used in conjunction with that... */struct raid_softc {	int	 sc_flags;		/* flags */	int	 sc_cflags;		/* configuration flags */	size_t	 sc_size;		/* size of the raid device */	char	 sc_xname[20];		/* XXX external name */	struct disk sc_dkdev;		/* generic disk device info */	struct buf sc_q;		/* used for the device queue */};/* sc_flags */#define RAIDF_INITED	0x01	/* unit has been initialized */#define RAIDF_WLABEL	0x02	/* label area is writable */#define RAIDF_LABELLING	0x04	/* unit is currently being labelled */#define RAIDF_WANTED	0x40	/* someone is waiting to obtain a lock */#define RAIDF_LOCKED	0x80	/* unit is locked */#define	raidunit(x)	DISKUNIT(x)int numraid = 0;/* * Allow RAIDOUTSTANDING number of simultaneous IO's to this RAID device. * Be aware that large numbers can allow the driver to consume a lot of * kernel memory, especially on writes, and in degraded mode reads. *  * For example: with a stripe width of 64 blocks (32k) and 5 disks,  * a single 64K write will typically require 64K for the old data,  * 64K for the old parity, and 64K for the new parity, for a total  * of 192K (if the parity buffer is not re-used immediately). * Even it if is used immedately, that's still 128K, which when multiplied * by say 10 requests, is 1280K, *on top* of the 640K of incoming data. *  * Now in degraded mode, for example, a 64K read on the above setup may * require data reconstruction, which will require *all* of the 4 remaining  * disks to participate -- 4 * 32K/disk == 128K again. */#ifndef RAIDOUTSTANDING#define RAIDOUTSTANDING   6#endif#define RAIDLABELDEV(dev)	\	(MAKEDISKDEV(major((dev)), raidunit((dev)), RAW_PART))/* declared here, and made public, for the benefit of KVM stuff.. */struct raid_softc *raid_softc;void	raidgetdefaultlabel	     __P((RF_Raid_t *, struct raid_softc *, struct disklabel *));void	raidgetdisklabel __P((dev_t));void	raidmakedisklabel __P((struct raid_softc *));int	raidlock __P((struct raid_softc *));void	raidunlock __P((struct raid_softc *));void	rf_markalldirty __P((RF_Raid_t *));void rf_mountroot_hook __P((struct device *));struct device *raidrootdev;void rf_ReconThread __P((struct rf_recon_req *));/* XXX what I want is: *//*void rf_ReconThread __P((RF_Raid_t *raidPtr));  */void rf_RewriteParityThread __P((RF_Raid_t *raidPtr));void rf_CopybackThread __P((RF_Raid_t *raidPtr));void rf_ReconstructInPlaceThread __P((struct rf_recon_req *));#ifdef RAID_AUTOCONFIGvoid rf_buildroothack __P((void *));static int rf_reasonable_label __P((RF_ComponentLabel_t *));#endifRF_AutoConfig_t *rf_find_raid_components __P((void));RF_ConfigSet_t *rf_create_auto_sets __P((RF_AutoConfig_t *));static int rf_does_it_fit __P((RF_ConfigSet_t *,RF_AutoConfig_t *));void rf_create_configuration __P((RF_AutoConfig_t *,RF_Config_t *,				  RF_Raid_t *));int rf_set_autoconfig __P((RF_Raid_t *, int));int rf_set_rootpartition __P((RF_Raid_t *, int));void rf_release_all_vps __P((RF_ConfigSet_t *));void rf_cleanup_config_set __P((RF_ConfigSet_t *));int rf_have_enough_components __P((RF_ConfigSet_t *));int rf_auto_config_set __P((RF_ConfigSet_t *, int *));#ifdef RAID_AUTOCONFIGstatic int raidautoconfig = 0; /* Debugging, mostly.  Set to 0 to not				  allow autoconfig to take place.			          Note that this is overridden by having			          RAID_AUTOCONFIG as an option in the 			          kernel config file.  */#endifvoidraidattach(num)	int num;{	int raidID;	int i, rc;#ifdef RAID_AUTOCONFIG	RF_AutoConfig_t *ac_list; /* autoconfig list */	RF_ConfigSet_t *config_sets;#endif	db1_printf(("raidattach: Asked for %d units\n", num));	if (num <= 0) {#ifdef DIAGNOSTIC		panic("raidattach: count <= 0");#endif		return;	}	/* This is where all the initialization stuff gets done. */	numraid = num;	/* Make some space for requested number of units... */	RF_Calloc(raidPtrs, num, sizeof(RF_Raid_t *), (RF_Raid_t **));	if (raidPtrs == NULL) {		panic("raidPtrs is NULL!!\n");	}	rc = rf_mutex_init(&rf_sparet_wait_mutex);	if (rc) {	        RF_PANIC();        }	rf_sparet_wait_queue = rf_sparet_resp_queue = NULL;	for (i = 0; i < num; i++)	        raidPtrs[i] = NULL;	rc = rf_BootRaidframe();	if (rc == 0)	        printf("Kernelized RAIDframe activated\n");	else	        panic("Serious error booting RAID!!\n");		/*	 * Put together some datastructures like the CCD device does..	 * This lets us lock the device and what-not when it gets opened.	 */		raid_softc = (struct raid_softc *)		malloc(num * sizeof(struct raid_softc),		       M_RAIDFRAME, M_NOWAIT);	if (raid_softc == NULL) {		printf("WARNING: no memory for RAIDframe driver\n");		return;	}	bzero(raid_softc, num * sizeof (struct raid_softc));	raidrootdev = (struct device *)malloc(num * sizeof(struct device),					      M_RAIDFRAME, M_NOWAIT);	if (raidrootdev == NULL) {		panic("No memory for RAIDframe driver!!?!?!\n");	}	for (raidID = 0; raidID < num; raidID++) {#if 0		SIMPLEQ_INIT(&raid_softc[raidID].sc_q);#endif		raidrootdev[raidID].dv_class  = DV_DISK;		raidrootdev[raidID].dv_cfdata = NULL;		raidrootdev[raidID].dv_unit   = raidID;		raidrootdev[raidID].dv_parent = NULL;		raidrootdev[raidID].dv_flags  = 0;		sprintf(raidrootdev[raidID].dv_xname,"raid%d",raidID);		RF_Calloc(raidPtrs[raidID], 1, sizeof (RF_Raid_t),		    (RF_Raid_t *));		if (raidPtrs[raidID] == NULL) {			printf("WARNING: raidPtrs[%d] is NULL\n", raidID);			numraid = raidID;			return;		}	}#if RAID_AUTOCONFIG	raidautoconfig = 1;if (raidautoconfig) {	/* 1. locate all RAID components on the system */#if DEBUG	printf("Searching for raid components...\n");#endif	ac_list = rf_find_raid_components();	/* 2. sort them into their respective sets */	config_sets = rf_create_auto_sets(ac_list);	/* 3. evaluate each set and configure the valid ones	   This gets done in rf_buildroothack() */	/* schedule the creation of the thread to do the 	   "/ on RAID" stuff */	kthread_create(rf_buildroothack, config_sets, NULL, "raidauto");#if 0	mountroothook_establish(rf_mountroot_hook, &raidrootdev[0]);#endif}#endif}