Home | History | Annotate | Line # | Download | only in vax
      1 /*	$NetBSD: crl.c,v 1.34 2017/03/31 08:38:13 msaitoh Exp $	*/
      2 /*-
      3  * Copyright (c) 1982, 1986 The Regents of the University of California.
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the University nor the names of its contributors
     15  *    may be used to endorse or promote products derived from this software
     16  *    without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  *
     30  *	@(#)crl.c	7.5 (Berkeley) 5/9/91
     31  */
     32 
     33 /*
     34  * Bugfix by Johnny Billquist 2010
     35  */
     36 
     37 /*
     38  * TO DO (tef  7/18/85):
     39  *	1) change printf's to log() instead???
     40  */
     41 
     42 #include <sys/cdefs.h>
     43 __KERNEL_RCSID(0, "$NetBSD: crl.c,v 1.34 2017/03/31 08:38:13 msaitoh Exp $");
     44 
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/conf.h>
     48 #include <sys/cpu.h>
     49 #include <sys/device.h>
     50 #include <sys/proc.h>
     51 #include <sys/buf.h>
     52 
     53 #include <machine/sid.h>
     54 #include <machine/scb.h>
     55 
     56 #include <vax/vax/crl.h>
     57 
     58 struct {
     59 	short	crl_state;		/* open and busy flags */
     60 	short	crl_active;		/* driver state flag */
     61 	struct	buf *crl_buf;		/* buffer we're using */
     62 	ushort *crl_xaddr;		/* transfer address */
     63 	short	crl_errcnt;
     64 } crltab;
     65 
     66 struct {
     67 	int	crl_cs;		/* saved controller status */
     68 	int	crl_ds;		/* saved drive status */
     69 } crlstat;
     70 
     71 void	crlintr(void *);
     72 void	crlattach(void);
     73 
     74 static void crlstart(void);
     75 static dev_type_open(crlopen);
     76 static dev_type_close(crlclose);
     77 static dev_type_read(crlrw);
     78 
     79 const struct cdevsw crl_cdevsw = {
     80 	.d_open = crlopen,
     81 	.d_close = crlclose,
     82 	.d_read = crlrw,
     83 	.d_write = crlrw,
     84 	.d_ioctl = noioctl,
     85 	.d_stop = nostop,
     86 	.d_tty = notty,
     87 	.d_poll = nopoll,
     88 	.d_mmap = nommap,
     89 	.d_kqfilter = nokqfilter,
     90 	.d_discard = nodiscard,
     91 	.d_flag = 0
     92 };
     93 
     94 struct evcnt crl_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "crl", "intr");
     95 EVCNT_ATTACH_STATIC(crl_ev);
     96 
     97 void
     98 crlattach(void)
     99 {
    100 	scb_vecalloc(0xF0, crlintr, NULL, SCB_ISTACK, &crl_ev);
    101 }
    102 
    103 /*ARGSUSED*/
    104 int
    105 crlopen(dev_t dev, int flag, int mode, struct lwp *l)
    106 {
    107 	if (vax_cputype != VAX_8600)
    108 		return (ENXIO);
    109 	if (crltab.crl_state != CRL_IDLE)
    110 		return (EALREADY);
    111 	crltab.crl_state = CRL_OPEN;
    112 	crltab.crl_buf = geteblk(512);
    113 	return (0);
    114 }
    115 
    116 /*ARGSUSED*/
    117 int
    118 crlclose(dev_t dev, int flag, int mode, struct lwp *l)
    119 {
    120 	brelse(crltab.crl_buf, 0);
    121 	crltab.crl_state = CRL_IDLE;
    122 	return 0;
    123 }
    124 
    125 /*ARGSUSED*/
    126 int
    127 crlrw(dev_t dev, struct uio *uio, int flag)
    128 {
    129 	struct buf *bp;
    130 	int i;
    131 	int s;
    132 	int error;
    133 
    134 	if (uio->uio_resid == 0)
    135 		return (0);
    136 	s = splconsmedia();
    137 	while (crltab.crl_state & CRL_BUSY)
    138 		(void) tsleep(&crltab, PRIBIO, "crlbusy", 0);
    139 	crltab.crl_state |= CRL_BUSY;
    140 	splx(s);
    141 
    142 	bp = crltab.crl_buf;
    143 	error = 0;
    144 	while ((i = imin(CRLBYSEC, uio->uio_resid)) > 0) {
    145 		bp->b_blkno = uio->uio_offset>>9;
    146 		if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0x1FF) != 0) {
    147 			error = EIO;
    148 			break;
    149 		}
    150 		if (uio->uio_rw == UIO_WRITE) {
    151 			error = uiomove(bp->b_data, i, uio);
    152 			if (error)
    153 				break;
    154 		}
    155 		if (uio->uio_rw == UIO_WRITE) {
    156 			bp->b_oflags &= ~(BO_DONE);
    157 			bp->b_flags &= ~(B_READ);
    158 			bp->b_flags |= B_WRITE;
    159 		} else {
    160 			bp->b_oflags &= ~(BO_DONE);
    161 			bp->b_flags &= ~(B_WRITE);
    162 			bp->b_flags |= B_READ;
    163 		}
    164 		s = splconsmedia();
    165 		crlstart();
    166                 while ((bp->b_oflags & BO_DONE) == 0)
    167                   (void) tsleep(bp, PRIBIO, "crlxfer", 0);
    168 		splx(s);
    169 		if (bp->b_error != 0) {
    170 			error = bp->b_error;
    171 			break;
    172 		}
    173 		if (uio->uio_rw == UIO_READ) {
    174 			error = uiomove(bp->b_data, i, uio);
    175 			if (error)
    176 				break;
    177 		}
    178 	}
    179 	crltab.crl_state &= ~CRL_BUSY;
    180 	wakeup((void *)&crltab);
    181 	return (error);
    182 }
    183 
    184 void
    185 crlstart(void)
    186 {
    187 	struct buf *bp;
    188 
    189 	bp = crltab.crl_buf;
    190 	crltab.crl_errcnt = 0;
    191 	crltab.crl_xaddr = (ushort *) bp->b_data;
    192 	bp->b_resid = 0;
    193 
    194 	if ((mfpr(PR_STXCS) & STXCS_RDY) == 0)
    195 		/* not ready to receive order */
    196 		return;
    197 	if ((bp->b_flags&(B_READ|B_WRITE)) == B_READ) {
    198 		crltab.crl_active = CRL_F_READ;
    199 		mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_READ, PR_STXCS);
    200 	} else {
    201 		crltab.crl_active = CRL_F_WRITE;
    202 		mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE, PR_STXCS);
    203 	}
    204 #ifdef lint
    205 	crlintr(NULL);
    206 #endif
    207 }
    208 
    209 void
    210 crlintr(void *arg)
    211 {
    212 	struct buf *bp;
    213 	int i;
    214 
    215 	bp = crltab.crl_buf;
    216 	i = mfpr(PR_STXCS);
    217 	switch ((i>>24) & 0xFF) {
    218 
    219 	case CRL_S_XCMPLT:
    220 		switch (crltab.crl_active) {
    221 
    222 		case CRL_F_RETSTS:
    223 			{
    224 				char sbuf[256], sbuf2[256];
    225 
    226 				crlstat.crl_ds = mfpr(PR_STXDB);
    227 
    228 				snprintb(sbuf, sizeof(sbuf), CRLCS_BITS,
    229 				    crlstat.crl_cs);
    230 				snprintb(sbuf2, sizeof(sbuf2), CRLDS_BITS,
    231 				    crlstat.crl_ds);
    232 				printf("crlcs=%s, crlds=%s\n", sbuf, sbuf2);
    233 				break;
    234 			}
    235 
    236 		case CRL_F_READ:
    237 		case CRL_F_WRITE:
    238 			bp->b_oflags |= BO_DONE;
    239 		}
    240 		crltab.crl_active = 0;
    241 		wakeup(bp);
    242 		break;
    243 
    244 	case CRL_S_XCONT:
    245 		switch (crltab.crl_active) {
    246 
    247 		case CRL_F_WRITE:
    248 			mtpr(*crltab.crl_xaddr++, PR_STXDB);
    249 			mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE, PR_STXCS);
    250 			break;
    251 
    252 		case CRL_F_READ:
    253 			*crltab.crl_xaddr++ = mfpr(PR_STXDB);
    254 			mtpr(bp->b_blkno<<8 | STXCS_IE | CRL_F_READ, PR_STXCS);
    255 		}
    256 		break;
    257 
    258 	case CRL_S_ABORT:
    259 		crltab.crl_active = CRL_F_RETSTS;
    260 		mtpr(STXCS_IE | CRL_F_RETSTS, PR_STXCS);
    261 		bp->b_oflags |= BO_DONE;
    262 		bp->b_error = EIO;
    263 		break;
    264 
    265 	case CRL_S_RETSTS:
    266 		crlstat.crl_cs = mfpr(PR_STXDB);
    267 		mtpr(STXCS_IE | CRL_S_RETSTS, PR_STXCS);
    268 		break;
    269 
    270 	case CRL_S_HNDSHK:
    271 		printf("crl: hndshk error\n");	/* dump out some status too? */
    272 		crltab.crl_active = 0;
    273 		bp->b_oflags |= BO_DONE;
    274 		bp->b_error = EIO;
    275 		cv_broadcast(&bp->b_done);
    276 		break;
    277 
    278 	case CRL_S_HWERR:
    279 		printf("crl: hard error sn%" PRId64 "\n", bp->b_blkno);
    280 		crltab.crl_active = CRL_F_ABORT;
    281 		mtpr(STXCS_IE | CRL_F_ABORT, PR_STXCS);
    282 		break;
    283 	}
    284 }
    285