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 58struct { 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 66struct { 67 int crl_cs; /* saved controller status */ 68 int crl_ds; /* saved drive status */ 69} crlstat; 70 71void crlintr(void *); 72void crlattach(void); 73 74static void crlstart(void); 75static dev_type_open(crlopen); 76static dev_type_close(crlclose); 77static dev_type_read(crlrw); 78 79const 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 94struct evcnt crl_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "crl", "intr"); 95EVCNT_ATTACH_STATIC(crl_ev); 96 97void 98crlattach(void) 99{ 100 scb_vecalloc(0xF0, crlintr, NULL, SCB_ISTACK, &crl_ev); 101} 102 103/*ARGSUSED*/ 104int 105crlopen(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*/ 117int 118crlclose(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*/ 126int 127crlrw(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 184void 185crlstart(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 209void 210crlintr(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