Subject: Re: control tool for amr(4)
To: Manuel Bouyer <bouyer@antioche.eu.org>
From: Andrew Doran <andrew@hairylemon.org>
List: tech-kern
Date: 06/28/2006 11:18:59
--TRYliJ5NKNqkz5bu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I made a few more changes.. An uncompiled & untested diff is attached:

- pass l->l_proc to bus_dmamap_load() so we don't need to double buffer
- remove spl calls in amr_ioctl()
- pass transfer direction in ld_amr_dobio()

Andrew

--TRYliJ5NKNqkz5bu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=newdiff

Index: Makefile
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/Makefile,v
retrieving revision 1.11
diff -u -r1.11 Makefile
--- Makefile	6 Dec 2005 11:53:56 -0000	1.11
+++ Makefile	28 Jun 2006 10:14:52 -0000
@@ -5,7 +5,7 @@
 INCSDIR= /usr/include/dev/pci
 
 # Only install includes which are used by userland
-INCS=	if_lmc.h mlyio.h mlyreg.h \
+INCS=	amrreg.h amrio.h if_lmc.h mlyio.h mlyreg.h \
 	pcidevs.h pcidevs_data.h pciio.h pcireg.h \
 	tgareg.h twereg.h tweio.h
 
Index: amr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/amr.c,v
retrieving revision 1.35
diff -u -r1.35 amr.c
--- amr.c	7 Jun 2006 22:33:36 -0000	1.35
+++ amr.c	28 Jun 2006 10:14:52 -0000
@@ -81,6 +81,7 @@
 #include <sys/proc.h>
 #include <sys/buf.h>
 #include <sys/malloc.h>
+#include <sys/conf.h>
 #include <sys/kthread.h>
 
 #include <uvm/uvm_extern.h>
@@ -92,6 +93,7 @@
 #include <dev/pci/pcivar.h>
 #include <dev/pci/amrreg.h>
 #include <dev/pci/amrvar.h>
+#include <dev/pci/amrio.h>
 
 #include "locators.h"
 
@@ -115,9 +117,20 @@
 static int	amr_std_get_work(struct amr_softc *, struct amr_mailbox_resp *);
 static int	amr_std_submit(struct amr_softc *, struct amr_ccb *);
 
+static dev_type_open(amropen);
+static dev_type_close(amrclose);
+static dev_type_ioctl(amrioctl);
+
 CFATTACH_DECL(amr, sizeof(struct amr_softc),
     amr_match, amr_attach, NULL, NULL);
 
+const struct cdevsw amr_cdevsw = {
+	amropen, amrclose, noread, nowrite, amrioctl,
+	nostop, notty, nopoll, nommap,
+};      
+
+extern struct   cfdriver amr_cd;
+
 #define AT_QUARTZ	0x01	/* `Quartz' chipset */
 #define	AT_SIG		0x02	/* Check for signature */
 
@@ -260,7 +273,7 @@
 	const char *intrstr;
 	pcireg_t reg;
 	int rseg, i, j, size, rv, memreg, ioreg;
-        struct amr_ccb *ac;
+	struct amr_ccb *ac;
 	int locs[AMRCF_NLOCS];
 
 	aprint_naive(": RAID controller\n");
@@ -719,7 +732,7 @@
 static void
 amr_shutdown(void *cookie)
 {
-        extern struct cfdriver amr_cd;
+	extern struct cfdriver amr_cd;
 	struct amr_softc *amr;
 	struct amr_ccb *ac;
 	int i, rv, s;
@@ -872,7 +885,7 @@
 		ac->ac_cmd.mb_command = AMR_CMD_ENQUIRY;
 
 		rv = amr_ccb_map(amr, ac, amr->amr_enqbuf,
-		    AMR_ENQUIRY_BUFSIZE, 0);
+		    AMR_ENQUIRY_BUFSIZE, AC_XFER_IN, NULL);
 		if (rv != 0) {
 			printf("%s: ccb_map failed (%d)\n",
  			    amr->amr_dv.dv_xname, rv);
@@ -948,7 +961,8 @@
 	mb[2] = cmdsub;
 	mb[3] = cmdqual;
 
-	rv = amr_ccb_map(amr, ac, sbuf, AMR_ENQUIRY_BUFSIZE, 0);
+	rv = amr_ccb_map(amr, ac, sbuf, AMR_ENQUIRY_BUFSIZE, AC_XFER_IN,
+	    NULL);
 	if (rv == 0) {
 		rv = amr_ccb_poll(amr, ac, 2000);
 		amr_ccb_unmap(amr, ac);
@@ -1027,25 +1041,31 @@
  */
 int
 amr_ccb_map(struct amr_softc *amr, struct amr_ccb *ac, void *data, int size,
-	    int out)
+	    int tflag, struct proc *p)
 {
 	struct amr_sgentry *sge;
 	struct amr_mailbox_cmd *mb;
 	int nsegs, i, rv, sgloff;
 	bus_dmamap_t xfer;
+	int dmaflag = 0;
 
 	xfer = ac->ac_xfer_map;
 
-	rv = bus_dmamap_load(amr->amr_dmat, xfer, data, size, NULL,
-	    BUS_DMA_NOWAIT);
+	rv = bus_dmamap_load(amr->amr_dmat, xfer, data, size, p,
+	    (p != NULL ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT));
 	if (rv != 0)
 		return (rv);
 
 	mb = &ac->ac_cmd;
 	ac->ac_xfer_size = size;
-	ac->ac_flags |= (out ? AC_XFER_OUT : AC_XFER_IN);
+	ac->ac_flags |= (tflag & (AC_XFER_OUT | AC_XFER_IN));
 	sgloff = AMR_SGL_SIZE * ac->ac_ident;
 
+	if (tflag & AC_XFER_OUT)
+		dmaflag |= BUS_DMASYNC_PREWRITE;
+	if (tflag & AC_XFER_IN)
+		dmaflag |= BUS_DMASYNC_PREREAD;
+
 	/* We don't need to use a scatter/gather list for just 1 segment. */
 	nsegs = xfer->dm_nsegs;
 	if (nsegs == 1) {
@@ -1063,8 +1083,7 @@
 		}
 	}
 
-	bus_dmamap_sync(amr->amr_dmat, xfer, 0, ac->ac_xfer_size,
-	    out ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
+	bus_dmamap_sync(amr->amr_dmat, xfer, 0, ac->ac_xfer_size, dmaflag);
 
 	if ((ac->ac_flags & AC_NOSGL) == 0)
 		bus_dmamap_sync(amr->amr_dmat, amr->amr_dmamap, sgloff,
@@ -1079,14 +1098,19 @@
 void
 amr_ccb_unmap(struct amr_softc *amr, struct amr_ccb *ac)
 {
+	int dmaflag = 0;
+
+	if (ac->ac_flags & AC_XFER_IN)
+		dmaflag |= BUS_DMASYNC_POSTREAD;
+	if (ac->ac_flags & AC_XFER_OUT)
+		dmaflag |= BUS_DMASYNC_POSTWRITE;
 
 	if ((ac->ac_flags & AC_NOSGL) == 0)
 		bus_dmamap_sync(amr->amr_dmat, amr->amr_dmamap,
 		    AMR_SGL_SIZE * ac->ac_ident, AMR_SGL_SIZE,
 		    BUS_DMASYNC_POSTWRITE);
 	bus_dmamap_sync(amr->amr_dmat, ac->ac_xfer_map, 0, ac->ac_xfer_size,
-	    (ac->ac_flags & AC_XFER_IN) != 0 ?
-	    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+	    dmaflag);
 	bus_dmamap_unload(amr->amr_dmat, ac->ac_xfer_map);
 }
 
@@ -1305,3 +1329,93 @@
 		printf("%08x ", ((u_int32_t *)&ac->ac_cmd)[i]);
 	printf("\n");
 }
+
+static int
+amropen(dev_t dev, int flag, int mode, struct lwp *l)
+{
+	struct amr_softc *amr;
+	 
+	if ((amr = device_lookup(&amr_cd, minor(dev))) == NULL)
+		return (ENXIO);
+	if ((amr->amr_flags & AMRF_OPEN) != 0)
+		return (EBUSY);
+							  
+	amr->amr_flags |= AMRF_OPEN;
+	return (0);
+}
+
+static int
+amrclose(dev_t dev, int flag, int mode, struct lwp *l)
+{
+	struct amr_softc *amr;
+
+	amr = device_lookup(&amr_cd, minor(dev));
+	amr->amr_flags &= ~AMRF_OPEN;
+	return (0);
+}
+
+static int
+amrioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
+{
+	struct amr_softc *amr;
+	struct amr_user_ioctl *au;
+	struct amr_ccb *ac;
+	struct amr_mailbox_ioctl *mbi;
+	unsigned long au_length;
+	uint8_t *au_cmd;
+	int error;
+
+	if (securelevel >= 2)
+		return (EPERM);
+
+	amr = device_lookup(&amr_cd, minor(dev));
+
+	/* This should be compatible with the FreeBSD interface */
+
+	switch (cmd) {
+	case AMR_IO_VERSION:
+		*(int *)data = AMR_IO_VERSION_NUMBER;
+		return 0;
+	case AMR_IO_COMMAND:
+		au = (struct amr_user_ioctl *)data;
+		au_cmd = au->au_cmd;
+		au_length = au->au_length;
+		break;
+	default:
+		return ENOTTY;
+	}
+
+	if (au_cmd[0] == AMR_CMD_PASS) {
+		/* not yet */
+		return EOPNOTSUPP;
+	}
+
+	if (au_cmd[0] == 0x06)
+		au_length = 0;
+	else if (au_length < 0 || au_length > MAXPHYS)
+		return (EINVAL);
+
+	/* direct command to controller */
+	while (amr_ccb_alloc(amr, &ac) != 0) {
+		error = tsleep(NULL, PRIBIO | PCATCH, "armmbx", hz);
+		if (error == EINTR)
+			return (error);
+	}
+			
+	mbi = (struct amr_mailbox_ioctl *)&ac->ac_cmd;
+	mbi->mb_command = au_cmd[0];
+	mbi->mb_channel = au_cmd[1];
+	mbi->mb_param = au_cmd[2];
+	mbi->mb_pad[0] = au_cmd[3];
+	mbi->mb_drive = au_cmd[4];
+	if (au_length != 0)
+		error = amr_ccb_map(amr, ac, au->au_buffer, (int)au_length,
+		    AC_XFER_IN | AC_XFER_OUT, l->l_proc);
+	if (error == 0) {
+		error = amr_ccb_wait(amr, ac);
+		if (au_length != 0)
+			amr_ccb_unmap(amr, ac);
+	}
+	amr_ccb_free(amr, ac);
+	return error;
+}
Index: amrreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/amrreg.h,v
retrieving revision 1.2
diff -u -r1.2 amrreg.h
--- amrreg.h	4 May 2003 16:15:36 -0000	1.2
+++ amrreg.h	28 Jun 2006 10:14:53 -0000
@@ -319,6 +319,7 @@
 	u_int32_t	ae_drivesize[AMR_40LD_MAXDRIVES];	/* logical drive size */
 	u_int8_t	ae_driveprop[AMR_40LD_MAXDRIVES];	/* logical drive properties */
 	u_int8_t	ae_drivestate[AMR_40LD_MAXDRIVES];	/* physical drive state */
+	u_int8_t	ae_pdrivestate[AMR_40LD_MAXPHYSDRIVES]; /* physical drive state */
 	u_int16_t	ae_driveformat[AMR_40LD_MAXPHYSDRIVES];
 	u_int8_t	ae_targxfer[80];			/* physical drive transfer rates */
 
Index: amrvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/amrvar.h,v
retrieving revision 1.5
diff -u -r1.5 amrvar.h
--- amrvar.h	11 Dec 2005 12:22:48 -0000	1.5
+++ amrvar.h	28 Jun 2006 10:14:53 -0000
@@ -107,6 +107,7 @@
 
 /* General flags. */
 #define	AMRF_THREAD_EXIT	0x00010000
+#define	AMRF_OPEN		0x00020000
 
 /*
  * Command control block.
@@ -143,7 +144,8 @@
 int	amr_ccb_alloc(struct amr_softc *, struct amr_ccb **);
 void	amr_ccb_enqueue(struct amr_softc *, struct amr_ccb *);
 void	amr_ccb_free(struct amr_softc *, struct amr_ccb *);
-int	amr_ccb_map(struct amr_softc *, struct amr_ccb *, void *, int, int);
+int	amr_ccb_map(struct amr_softc *, struct amr_ccb *, void *, int, int,
+		    struct proc *);
 int	amr_ccb_poll(struct amr_softc *, struct amr_ccb *, int);
 void	amr_ccb_unmap(struct amr_softc *, struct amr_ccb *);
 int	amr_ccb_wait(struct amr_softc *, struct amr_ccb *);
Index: ld_amr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/ld_amr.c,v
retrieving revision 1.9
diff -u -r1.9 ld_amr.c
--- ld_amr.c	25 Mar 2006 04:12:36 -0000	1.9
+++ ld_amr.c	28 Jun 2006 10:14:53 -0000
@@ -151,7 +151,9 @@
 	mb->mb_blkcount = htole16(datasize / AMR_SECTOR_SIZE);
 	mb->mb_lba = htole32(blkno);
 
-	if ((rv = amr_ccb_map(amr, ac, data, datasize, dowrite)) != 0) {
+	rv = amr_ccb_map(amr, ac, data, datasize,
+	    (dowrite ? AC_XFER_OUT : AC_XFER_IN), NULL)
+	if (rv != 0) {
 		amr_ccb_free(amr, ac);
 		return (rv);
 	}

--TRYliJ5NKNqkz5bu--