1 /* $NetBSD: hp.c,v 1.1 1995/02/13 00:43:59 ragge Exp $ */ 2 /* 3 * Copyright (c) 1994 Ludd, University of Lule}, Sweden. 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. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed at Ludd, University of Lule}. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* All bugs are subject to removal without further notice */ 33 34 35 36 /* hp.c - drivrutiner f|r massbussdiskar 940325/ragge */ 37 38 #include "param.h" 39 #include "types.h" 40 #include "fcntl.h" 41 #include "syslog.h" 42 #include "disklabel.h" 43 #include "buf.h" 44 #include "vax/mba/mbareg.h" 45 #include "vax/mba/mbavar.h" 46 #include "vax/mba/hpdefs.h" 47 #include "hp.h" 48 49 struct mba_device *hpinfo[NHP]; 50 struct hp_info hp_info[NHP]; 51 struct disklabel hplabel[NHP]; 52 int hpslave(), hpattach(); 53 54 char hptypes[]={ 55 0x22,0 56 }; 57 58 struct mba_driver hpdriver={ 59 hpslave, 0, "hp", hptypes, hpattach, hpinfo 60 }; 61 62 hpslave(){ 63 printf("Hpslave.\n"); 64 asm("halt"); 65 }; 66 67 hpopen(){ 68 printf("hpopen"); 69 asm("halt"); 70 }; 71 72 hpclose(){ 73 printf("hpclose\n"); 74 asm("halt"); 75 }; 76 77 hpioctl(){ 78 printf("hpioctl\n"); 79 asm("halt"); 80 } 81 82 hpdump(){ 83 printf("hpdump\n"); 84 asm("halt"); 85 }; 86 87 hpsize(){ 88 printf("hpsize"); 89 asm("halt"); 90 }; 91 92 93 94 hpattach(mi) 95 struct mba_device *mi; 96 { 97 struct mba_drv *md; 98 99 /* 100 * We check status of the drive first; to see if there is any idea 101 * to try to read the label. 102 */ 103 md=&(mi->mi_mba->mba_drv[mi->drive]); 104 if(!md->rmcs1&HPCS1_DVA){ 105 printf(": Drive not available"); 106 return; 107 } 108 if(!md->rmds&HPDS_MOL){ 109 printf(": Drive offline"); 110 return; 111 } 112 if (hpinit(mi, 0)) 113 printf(": offline"); 114 /* else if (ra_info[unit].ra_state == OPEN) { 115 printf(": %s, size = %d sectors", 116 udalabel[unit].d_typename, ra_info[unit].ra_dsize); 117 */ 118 printf("rmcs1: %x, rmds: %x, rmdt: %x rmsn: %x\n", 119 md->rmcs1, md->rmds, md->rmdt, md->rmsn); 120 121 122 /* asm("halt"); */ 123 /* 124 if (MSCP_MID_ECH(1, ra_info[unit].ra_mediaid) == 'X' - '@') { 125 printf(": floppy"); 126 return; 127 } 128 if (ui->ui_dk >= 0) 129 dk_wpms[ui->ui_dk] = (60 * 31 * 256); 130 udaip[ui->ui_ctlr][ui->ui_slave] = ui; 131 132 if (uda_rainit(ui, 0)) 133 printf(": offline"); 134 else if (ra_info[unit].ra_state == OPEN) { 135 printf(": %s, size = %d sectors", 136 udalabel[unit].d_typename, ra_info[unit].ra_dsize); 137 }*/ 138 } 139 140 141 /* 142 * Initialise a drive. If it is not already, bring it on line, 143 * and set a timeout on it in case it fails to respond. 144 * When on line, read in the pack label. 145 */ 146 hpinit(mi, flags) 147 struct mba_device *mi; 148 { 149 /* struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; */ 150 struct disklabel *lp; 151 struct hp_info *hp; 152 /* struct mscp *mp; */ 153 int unit = mi->unit; 154 char *msg, *readdisklabel(); 155 int s, i, hpstrategy(); 156 extern int cold; 157 158 hp = &hp_info[unit]; 159 /* 160 if ((ui->ui_flags & UNIT_ONLINE) == 0) { 161 mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); 162 mp->mscp_opcode = M_OP_ONLINE; 163 mp->mscp_unit = ui->ui_slave; 164 mp->mscp_cmdref = (long)&ui->ui_flags; 165 *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 166 ra->ra_state = WANTOPEN; 167 if (!cold) 168 s = spl5(); 169 i = ((struct udadevice *)ui->ui_addr)->udaip; 170 171 if (cold) { 172 i = todr() + 1000; 173 while ((ui->ui_flags & UNIT_ONLINE) == 0) 174 if (todr() > i) 175 break; 176 } else { 177 timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); 178 sleep((caddr_t)&ui->ui_flags, PSWP + 1); 179 splx(s); 180 untimeout(wakeup, (caddr_t)&ui->ui_flags); 181 } 182 if (ra->ra_state != OPENRAW) { 183 ra->ra_state = CLOSED; 184 wakeup((caddr_t)ra); 185 return (EIO); 186 } 187 } 188 */ 189 lp = &hplabel[unit]; 190 lp->d_secsize = DEV_BSIZE; 191 192 lp->d_secsize = DEV_BSIZE; 193 lp->d_secperunit = 15 /*ra->ra_dsize*/; 194 195 if (flags & O_NDELAY) 196 return (0); 197 hp->hp_state = RDLABEL; 198 /* 199 * Set up default sizes until we have the label, or longer 200 * if there is none. Set secpercyl, as readdisklabel wants 201 * to compute b_cylin (although we do not need it), and set 202 * nsectors in case diskerr is called. 203 */ 204 lp->d_secpercyl = 1; 205 lp->d_npartitions = 1; 206 lp->d_secsize = 512; 207 /* lp->d_secperunit = ra->ra_dsize; */ 208 lp->d_nsectors = 15 /*ra->ra_geom.rg_nsectors*/; 209 lp->d_partitions[0].p_size = lp->d_secperunit; 210 lp->d_partitions[0].p_offset = 0; 211 212 /* 213 * Read pack label. 214 */ 215 if ((msg = readdisklabel(hpminor(unit, 0), hpstrategy, lp)) != NULL) { 216 if (cold) 217 printf(": %s", msg); 218 else 219 log(LOG_ERR, "hp%d: %s", unit, msg); 220 /* ra->ra_state = OPENRAW; */ 221 /* uda_makefakelabel(ra, lp); */ 222 } else 223 /* ra->ra_state = OPEN; */ 224 /* wakeup((caddr_t)hp); */ 225 return (0); 226 } 227 228 /* 229 * Queue a transfer request, and if possible, hand it to the controller. 230 * 231 * This routine is broken into two so that the internal version 232 * udastrat1() can be called by the (nonexistent, as yet) bad block 233 * revectoring routine. 234 */ 235 hpstrategy(bp) 236 register struct buf *bp; 237 { 238 register int unit; 239 register struct uba_device *ui; 240 register struct hp_info *hp; 241 struct partition *pp; 242 int p; 243 daddr_t sz, maxsz; 244 245 /* 246 * Make sure this is a reasonable drive to use. 247 */ 248 /* bp->b_error = ENXIO; 249 goto bad; 250 */ 251 unit = hpunit(bp->b_dev); 252 253 /* 254 * If drive is open `raw' or reading label, let it at it. 255 */ 256 257 if (hp->hp_state < OPEN) { 258 hpstrat1(bp); 259 return; 260 } 261 262 263 /* if ((unit = udaunit(bp->b_dev)) >= NRA || 264 (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || 265 (ra = &ra_info[unit])->ra_state == CLOSED) { 266 bp->b_error = ENXIO; 267 goto bad; 268 } 269 */ 270 /* 271 * If drive is open `raw' or reading label, let it at it. 272 */ 273 /* 274 if (ra->ra_state < OPEN) { 275 udastrat1(bp); 276 return; 277 } 278 p = udapart(bp->b_dev); 279 if ((ra->ra_openpart & (1 << p)) == 0) { 280 bp->b_error = ENODEV; 281 goto bad; 282 } 283 */ 284 /* 285 * Determine the size of the transfer, and make sure it is 286 * within the boundaries of the partition. 287 */ 288 /* 289 pp = &udalabel[unit].d_partitions[p]; 290 maxsz = pp->p_size; 291 if (pp->p_offset + pp->p_size > ra->ra_dsize) 292 maxsz = ra->ra_dsize - pp->p_offset; 293 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 294 if (bp->b_blkno + pp->p_offset <= LABELSECTOR && 295 #if LABELSECTOR != 0 296 bp->b_blkno + pp->p_offset + sz > LABELSECTOR && 297 #endif 298 (bp->b_flags & B_READ) == 0 && ra->ra_wlabel == 0) { 299 bp->b_error = EROFS; 300 goto bad; 301 } 302 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 303 /* if exactly at end of disk, return an EOF */ 304 /* 305 if (bp->b_blkno == maxsz) { 306 bp->b_resid = bp->b_bcount; 307 biodone(bp); 308 return; 309 } 310 /* or truncate if part of it fits */ 311 /* 312 sz = maxsz - bp->b_blkno; 313 if (sz <= 0) { 314 bp->b_error = EINVAL; /* or hang it up */ 315 /* 316 goto bad; 317 } 318 bp->b_bcount = sz << DEV_BSHIFT; 319 } 320 udastrat1(bp); 321 return; 322 */ 323 bad: 324 bp->b_flags |= B_ERROR; 325 biodone(bp); 326 } 327 328 /* 329 * Work routine for udastrategy. 330 */ 331 hpstrat1(bp) 332 register struct buf *bp; 333 { 334 register int unit = hpunit(bp->b_dev); 335 register struct hp_ctlr *um; 336 register struct buf *dp; 337 struct hp_device *ui; 338 /* int s = spl5(); */ 339 340 asm("halt"); 341 /* 342 * Append the buffer to the drive queue, and if it is not 343 * already there, the drive to the controller queue. (However, 344 * if the drive queue is marked to be requeued, we must be 345 * awaiting an on line or get unit status command; in this 346 * case, leave it off the controller queue.) 347 */ 348 /* 349 um = (ui = udadinfo[unit])->ui_mi; 350 dp = &udautab[unit]; 351 APPEND(bp, dp, av_forw); 352 if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { 353 APPEND(dp, &um->um_tab, b_forw); 354 dp->b_active++; 355 } 356 357 /* 358 * Start activity on the controller. Note that unlike other 359 * Unibus drivers, we must always do this, not just when the 360 * controller is not active. 361 */ 362 /* 363 udastart(um); 364 splx(s); 365 */ 366 } 367