Subject: Disklabels arrive for 2.11BSD (#263 part 14 of 18) Index: sys,bin,usr.lib,(many more)/ 2.11BSD Description: The moving the partitions tables out of the disk drivers and to a disklabel residing on the media has been on the wish list for many many years. Disklabels have finally arrived for 2.11BSD! Repeat-By: Observation. Also a reading of the setup and installation documentation for previous 2BSD releases (2.9, 2.10, 2.11) all have a paragraph similar to this present: "It is possible to change the partitions by changing the code for the table in the disk driver. Since it's desirable to do this, these tables really should be read off each pack...." Fix: This is part 14 of 18. Gather all parts before doing anything except reading the instructions which are in #250 (part 1). Updated by this part are: /usr/src/sys/pdpuba/xp.c /usr/src/sys/pdpuba/si.c /usr/src/sys/pdpuba/ra.c /usr/src/sys/pdpuba/hk.c /usr/src/sys/pdpuba/br.c /usr/src/sys/pdpuba/rl.c Essentially all of the disk drivers were modified (except the RX driver - does anyone have one running under 2.11?). The RA and RL drivers have had label support added. The other drivers have had small changes made because a couple macros in buf.h have changed (those defines/macros were an ungood idea anyways - good riddance). NO major changes were made to any drivers except ra.c and rl.c - both of those underwent a rewrite. Adding label support to a driver which previously had hardcoded partition tables changes the complexion of a driver - it adds a _lot_ of code but removes the D-space partition tables. On a pdp-11 that's a *win* :-) Cut where indicated and save to a file (/tmp/263). Then: patch -p0 < /tmp/263 rm /tmp/263 -----------------------cut here------------------------------- *** /usr/src/sys/pdpuba/xp.c.old Thu Jul 1 20:04:15 1993 --- /usr/src/sys/pdpuba/xp.c Thu Apr 13 22:41:12 1995 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)xp.c 1.7 (2.11BSD GTE) 7/1/93 */ /* --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)xp.c 1.8 (2.11BSD GTE) 1995/04/13 */ /* *************** *** 31,36 **** --- 31,38 ---- #include "hpreg.h" #include "dkbad.h" #include "dk.h" + #include "disklabel.h" + #include "disk.h" #include "map.h" #include "uba.h" *************** *** 500,507 **** int s; long bn; ! unit = dkunit(bp); ! pseudo_unit = minor(bp->b_dev) & 07; if ((unit >= NXPD) || ((xd = &xp_drive[unit])->xp_ctlr == 0) || (xd->xp_ctlr->xp_addr == 0)) { --- 502,509 ---- int s; long bn; ! unit = dkunit(bp->b_dev); ! pseudo_unit = dkpart(bp->b_dev); if ((unit >= NXPD) || ((xd = &xp_drive[unit])->xp_ctlr == 0) || (xd->xp_ctlr->xp_addr == 0)) { *************** *** 508,514 **** bp->b_error = ENXIO; goto errexit; } ! if ((bp->b_blkno < 0) || ((bn = dkblock(bp)) + ((bp->b_bcount + 511) >> 9) > xd->xp_sizes[pseudo_unit].nblocks)) { bp->b_error = EINVAL; errexit: --- 510,516 ---- bp->b_error = ENXIO; goto errexit; } ! if ((bp->b_blkno < 0) || ((bn = bp->b_blkno) + ((bp->b_bcount + 511) >> 9) > xd->xp_sizes[pseudo_unit].nblocks)) { bp->b_error = EINVAL; errexit: *************** *** 611,617 **** * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ ! bn = dkblock(bp); cn = bp->b_cylin; sn = bn % xd->xp_nspc; sn += xd->xp_nsect - XP_SDIST; --- 613,619 ---- * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ ! bn = bp->b_blkno; cn = bp->b_cylin; sn = bn % xd->xp_nspc; sn += xd->xp_nsect - XP_SDIST; *************** *** 688,697 **** * Mark controller busy and determine destination of this request. */ xc->xp_active++; ! pseudo_unit = minor(bp->b_dev) & 07; ! unit = dkunit(bp); xd = &xp_drive[unit]; ! bn = dkblock(bp); cn = xd->xp_sizes[pseudo_unit].cyloff; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; --- 690,699 ---- * Mark controller busy and determine destination of this request. */ xc->xp_active++; ! pseudo_unit = dkpart(bp->b_dev); ! unit = dkunit(bp->b_dev); xd = &xp_drive[unit]; ! bn = bp->b_blkno; cn = xd->xp_sizes[pseudo_unit].cyloff; cn += bn / xd->xp_nspc; sn = bn % xd->xp_nspc; *************** *** 782,788 **** if (xpecc(bp, CONT)) return; #endif ! unit = dkunit(bp); xd = &xp_drive[unit]; xpaddr->hpcs2.c[0] = xd->xp_unit; /* --- 784,790 ---- if (xpecc(bp, CONT)) return; #endif ! unit = dkunit(bp->b_dev); xd = &xp_drive[unit]; xpaddr->hpcs2.c[0] = xd->xp_unit; /* *************** *** 908,914 **** * ndone is #bytes including the error which is assumed to be in the * last disk page transferred. */ ! unit = dkunit(bp); xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; #ifdef BADSECT --- 910,916 ---- * ndone is #bytes including the error which is assumed to be in the * last disk page transferred. */ ! unit = dkunit(bp->b_dev); xd = &xp_drive[unit]; xpaddr = xd->xp_ctlr->xp_addr; #ifdef BADSECT *************** *** 928,934 **** #endif ocmd = (xpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; bb = exadr(bp->b_xmem, bp->b_un.b_addr); ! bn = dkblock(bp); cn = bp->b_cylin - (bn / xd->xp_nspc); bn += npx; cn += bn / xd->xp_nspc; --- 930,936 ---- #endif ocmd = (xpaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO; bb = exadr(bp->b_xmem, bp->b_un.b_addr); ! bn = bp->b_blkno; cn = bp->b_cylin - (bn / xd->xp_nspc); bn += npx; cn += bn / xd->xp_nspc; *** /usr/src/sys/pdpuba/si.c.old Sat Jan 2 23:24:21 1993 --- /usr/src/sys/pdpuba/si.c Thu Apr 13 23:15:53 1995 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)si.c 1.4 (2.11BSD GTE) 1/2/93 */ /* --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)si.c 1.5 (2.11BSD GTE) 1995/04/13 */ /* *************** *** 22,27 **** --- 22,29 ---- #include "map.h" #include "uba.h" #include "dk.h" + #include "disklabel.h" + #include "disk.h" #include "xp.h" #include "errno.h" *************** *** 126,132 **** goto errexit; } if (bp->b_blkno < 0 || ! (bn = dkblock(bp)) + (long) ((bp->b_bcount + 511) >> 9) > rm5_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: --- 128,134 ---- goto errexit; } if (bp->b_blkno < 0 || ! (bn = bp->b_blkno) + (long) ((bp->b_bcount + 511) >> 9) > rm5_sizes[unit & 07].nblocks) { bp->b_error = EINVAL; errexit: *************** *** 136,142 **** } mapalloc(bp); bp->b_cylin = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff; ! unit = dkunit(bp); dp = &siutab[unit]; s = splbio(); disksort(dp, bp); --- 138,144 ---- } mapalloc(bp); bp->b_cylin = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff; ! unit = dkunit(bp->b_dev); dp = &siutab[unit]; s = splbio(); disksort(dp, bp); *************** *** 199,205 **** * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ ! bn = dkblock(bp); cn = bp->b_cylin; sn = bn % (SI_NSECT * SI_NTRAC); sn = (sn + SI_NSECT) % SI_NSECT; --- 201,207 ---- * Figure out where this transfer is going to * and see if we are close enough to justify not searching. */ ! bn = bp->b_blkno; cn = bp->b_cylin; sn = bn % (SI_NSECT * SI_NTRAC); sn = (sn + SI_NSECT) % SI_NSECT; *************** *** 268,275 **** */ sitab.b_active++; unit = minor(bp->b_dev) & 077; ! dn = dkunit(bp); ! bn = dkblock(bp); cn = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff; sn = bn % (SI_NSECT * SI_NTRAC); tn = sn / SI_NSECT; --- 270,277 ---- */ sitab.b_active++; unit = minor(bp->b_dev) & 077; ! dn = dkunit(bp->b_dev); ! bn = bp->b_blkno; cn = bn / (SI_NSECT * SI_NTRAC) + rm5_sizes[unit & 07].cyloff; sn = bn % (SI_NSECT * SI_NTRAC); tn = sn / SI_NSECT; *************** *** 340,346 **** */ dp = sitab.b_actf; bp = dp->b_actf; ! unit = dkunit(bp); /* * Check for and process errors. */ --- 342,348 ---- */ dp = sitab.b_actf; bp = dp->b_actf; ! unit = dkunit(bp->b_dev); /* * Check for and process errors. */ *** /usr/src/sys/pdpuba/ra.c.old Wed Jan 11 20:58:31 1995 --- /usr/src/sys/pdpuba/ra.c Mon Jul 3 21:12:59 1995 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ra.c 2.5 (2.11BSD GTE) 1/11/95 */ /*********************************************************************** --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ra.c 2.9 (2.11BSD GTE) 1995/07/03 */ /*********************************************************************** *************** *** 14,19 **** --- 14,42 ---- /* * ra.c - MSCP Driver + * Date: July 3, 1995 + * Fix a couple bugs and simplify the close protocol. + * + * Date: June 16, 1995 + * Use the common label ioctl routine created today. + * + * Date: June 15, 1995 + * Disklabels work! A few minor changes made - raopen() needed to always + * validate the partition number not just when the drive was first brought + * online. + * + * Date: May 20, 1995 + * Minor changes before beginning testing. + * + * Date: May 03, 1995 + * Resume adding disklabel support. The past several weeks were spent + * porting/rewriting 'newfs', 'disklabel', 'getdiskbyname' and so on. + * + * Date: Apr 13, 1995 + * Begin implementing disklabels. First job was to remove/change references + * to dkunit() since that macro has moved from buf.h to disk.h and takes a + * 'dev_t' now instead of 'buf *'. + * * Date: Jan 11, 1995 * Remove extra parameter to ra_error() call in radump(). * *************** *** 65,71 **** * The error message output was rearranged saving another 82 bytes of * kernel D space. Also, there was an extraneous buffer header allocated, * it was removed, saving a further 24 bytes of D space. ! * sms@wlv.imsd.contel.com * * Date: Jan 30 1984 * This thing has been beaten beyound belief. --- 88,94 ---- * The error message output was rearranged saving another 82 bytes of * kernel D space. Also, there was an extraneous buffer header allocated, * it was removed, saving a further 24 bytes of D space. ! * sms@wlv.iipo.gtegsc.com (was wlv.imsd.contel.com at the time). * * Date: Jan 30 1984 * This thing has been beaten beyound belief. *************** *** 89,213 **** #include "conf.h" #include "map.h" #include "syslog.h" #include "uba.h" #include "rareg.h" #include "dk.h" #include "errno.h" #define RACON(x) ((minor(x) >> 6) & 03) #define RAUNIT(x) ((minor(x) >> 3) & 07) - struct rasizes { - daddr_t nblocks; - daddr_t blkoff; - } rd52_sizes[8] = { /* Setup for RD52 and RD53 disks */ - 9700, 0, /* A=blk 0 thru 9699 (root for 52 & 53) */ - 17300, 9700, /* B=blk 9700 thru 26999 (52 & 53 only) */ - 3100, 27000, /* C=blk 27000 thru 30099 (swap 52 & 53) */ - -1, 30100, /* D=blk 30100 thru end (52 & 53 only) */ - 0, 0, /* E=unused */ - 0, 0, /* F=unused */ - -1, 9700, /* G=blk 9700 thru end (52 & 53) */ - -1, 0, /* H=blk 0 thru end (52, 53) */ - }, ra60_sizes[8] = { - 15884, 0, /* A=blk 0 thru 15883 */ - 33440, 15884, /* B=blk 15884 thru 49323 */ - 193282, 49324, /* C=blk 49324 thru 242605 */ - 15884, 242606, /* D=blk 242606 thru 258489 */ - -1, 258490, /* E=blk 258490 thru end */ - 0, 0, /* F=unused */ - -1, 242606, /* G=blk 242606 thru end */ - -1, 0, /* H=blk 0 thru end */ - }, ra80_sizes[8] = { - 15884, 0, /* A=blk 0 thru 15883 */ - 33440, 15884, /* B=blk 15884 thru 49323 */ - -1, 49324, /* C=blk 49324 thru end */ - 0, 0, /* D=unused */ - 0, 0, /* E=unused */ - 0, 0, /* F=unused */ - 0, 0, /* G=unused */ - -1, 0, /* H=blk 0 thru end */ - }, ra81_sizes[8] ={ - 15884, 0, /* A=blk 0 thru 15883 */ - 33440, 15884, /* B=blk 15884 thru 49323 */ - 193282, 49324, /* C=blk 49324 thru 242605 */ - 15884, 242606, /* D=blk 242606 thru 258489 */ - 307200, 258490, /* E=blk 258490 thru 565689 */ - -1, 565690, /* F=blk 565690 thru end */ - -1, 242606, /* G=blk 242606 thru end */ - -1, 0, /* H=blk 0 thru end */ - }, ra_gen1[8] ={ - 15884, 0, /* A=blk 0 thru 15883 */ - 8360, 15884, /* B=blk 15884 thru 24243 */ - -1, 0, /* C=blk 0 thru end */ - 0, 0, /* D=unused */ - 0, 0, /* E=unused */ - 0, 0, /* F=unused */ - -1, 24244, /* G=blk 24244 thru end */ - 0, 0, /* H=unused */ - }, ra_gen2[8] ={ - 15884, 0, /* A=blk 0 thru 15883 */ - 16720, 15884, /* B=blk 15884 thru 32603 */ - -1, 0, /* C=blk 0 thru end */ - 227136, 32604, /* D=blk 32604 thru 259739 */ - -1, 259740, /* E=blk 259740 thru end */ - 0, 0, /* F=unused */ - -1, 32604, /* G=32604 thru end */ - 0, 0, /* H=unused */ - }, ra_gen3[8] ={ - -1, 0, /* A=blk 0 thru end */ - 0, 0, /* B=unused */ - -1, 0, /* C=blk 0 thru end */ - 0, 0, /* D=unused */ - 0, 0, /* E=unused */ - 0, 0, /* F=unused */ - 0, 0, /* G=unused */ - 0, 0, /* H=unused */ - }, ra_gen4[8] ={ - 15884, 0, /* A=blk 0 thru 15883 */ - 16720, 15884, /* B=blk 15884 thru 32603 */ - -1, 0, /* C=blk 0 thru end */ - 227136, 32604, /* D=blk 32604 thru 259739 */ - 409600, 259740, /* E=blk 259740 thru 669339 */ - -1, 669340, /* F=blk 669340 thru end */ - -1, 32604, /* G=blk 32604 thru end */ - 0, 0, /* H=unused */ - }, ra_gen5[8] ={ - 15884, 0, /* A=blk 0 thru 15883 */ - 16720, 15884, /* B=blk 15884 thru 32603 */ - -1, 0, /* C=blk 0 thru end */ - 227136, 32604, /* D=blk 32604 thru 259739 */ - 409600, 259740, /* E=blk 259740 thru 669339 */ - 182464, 669340, /* F=blk 669340 thru 851803 */ - 819200, 32604, /* G=blk 32604 thru 851803 */ - -1, 851804, /* H=blk 851804 thru end */ - }; - - #define M15(a,b,c) ((((((a - '@') & 0x1f) << 10) | \ - ((b - '@') & 0x1f) << 5) | \ - ((c - '@') & 0x1f) << 0)) - - /* - * Entries are only placed in this table to over-ride the drive size - * based selection of partition tables in radisksetup(). For example: - * the RA81 is listed here to keep the "old" partition table rather than - * assigning 'ra_gen5' (because the RA81 is > 851804 sectors. - */ - - struct MEDIA - { - short id7; - short name15; - struct rasizes *parts; - } Mscptbl[] = { - { 81, M15('R','A','@'), ra81_sizes }, - { 60, M15('R','A','@'), ra60_sizes }, - { 80, M15('R','A','@'), ra80_sizes }, - { 53, M15('R','D','@'), rd52_sizes }, - { 52, M15('R','D','@'), rd52_sizes }, - { 0, 0, 0 } - }; - #define NRSPL2 3 /* log2 number of response packets */ #define NCMDL2 3 /* log2 number of command packets */ #define NRSP (1<> 6) & 03) #define RAUNIT(x) ((minor(x) >> 3) & 07) #define NRSPL2 3 /* log2 number of response packets */ #define NCMDL2 3 /* log2 number of command packets */ #define NRSP (1<ra_dsize == 0L) return(p); return(NULL); } --- 311,322 ---- register int i; register ra_infoT *p; ! for (i = NRAD, p = ra_disks; i--; p++) ! if ((p->ra_flags & DKF_ALIVE) == 0) ! { ! p->ra_flags = DKF_ALIVE; return(p); + } return(NULL); } *************** *** 391,410 **** /* * Open a RA. Initialize the device and set the unit online. */ ! raopen(dev, flag) dev_t dev; int flag; { register ra_infoT *disk; register struct mscp *mp; register ra_softcT *sc = &ra_sc[RACON(dev)]; ! int unit = RAUNIT(dev); ! int s, i; PRINTD(("raopen: dev=%x, flags=%d\n", dev, flag)); /* Check that controller exists */ ! if (RACON(dev) >= NRAC || sc->RAADDR == NULL) return(ENXIO); /* Open device */ --- 323,345 ---- /* * Open a RA. Initialize the device and set the unit online. */ ! raopen(dev, flag, mode) dev_t dev; int flag; + int mode; { register ra_infoT *disk; register struct mscp *mp; register ra_softcT *sc = &ra_sc[RACON(dev)]; ! int unit = RAUNIT(dev); ! int ctlr = RACON(dev); ! int mask; ! int s, i; PRINTD(("raopen: dev=%x, flags=%d\n", dev, flag)); /* Check that controller exists */ ! if (ctlr >= NRAC || sc->RAADDR == NULL) return(ENXIO); /* Open device */ *************** *** 433,454 **** * Check to see if the device is really there. This code was * taken from Fred Canters 11 driver. */ ! if ((disk = sc->sc_drives[unit]) == NULL) { PRINTD(("raopen: opening new disk %d\n", unit)); s = splbio(); /* Allocate disk table entry for disk */ if ((disk = ragetdd()) != NULL) { sc->sc_drives[unit] = disk; ! disk->ra_unit = unit; ! disk->ra_dsize = -1L; } else { ! printf("ra%d: no disk structures\n", unit); splx(s); return(ENXIO); } } /* Try to online disk unit, it might have gone offline */ ! if (disk->ra_dsize == -1L) { /* In high kernel, don't saveseg5, just use normalseg5 later on. */ while ((mp = ragetcp(sc)) == 0) { ++sc->sc_cp_wait; --- 368,389 ---- * Check to see if the device is really there. This code was * taken from Fred Canters 11 driver. */ ! disk = sc->sc_drives[unit]; ! if (disk == NULL) { PRINTD(("raopen: opening new disk %d\n", unit)); s = splbio(); /* Allocate disk table entry for disk */ if ((disk = ragetdd()) != NULL) { sc->sc_drives[unit] = disk; ! disk->ra_unit = ctlr; /* controller number */ } else { ! printf("ra: !disk structs\n"); splx(s); return(ENXIO); } } /* Try to online disk unit, it might have gone offline */ ! if ((disk->ra_flags & DKF_ONLINE) == 0) { /* In high kernel, don't saveseg5, just use normalseg5 later on. */ while ((mp = ragetcp(sc)) == 0) { ++sc->sc_cp_wait; *************** *** 458,486 **** mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); mp->m_opcode = M_O_ONLIN; mp->m_unit = unit; ! mp->m_cmdref = (unsigned)&disk->ra_dsize; ((Trl *)mp->m_dscptr)->hsh |= RA_OWN|RA_INT; normalseg5(); i = sc->RAADDR->raip; ! timeout(wakeup, (caddr_t)&disk->ra_dsize, 10 * LINEHZ); ! sleep((caddr_t)&disk->ra_dsize, PSWP+1); splx(s); } /* Did it go online? */ ! if (disk->ra_dsize == -1L) { PRINTD(("raopen: disk didn't go online\n")); s = splbio(); ! disk->ra_dsize = 0L; sc->sc_drives[unit] = NULL; splx(s); return(ENXIO); } PRINTD(("raopen: disk online\n")); return(0); } /* * Initialize controller, data structures, and start hardware * initialization sequence. */ --- 393,565 ---- mapseg5(ra_com[sc->sc_unit], MAPSEGDESC); mp->m_opcode = M_O_ONLIN; mp->m_unit = unit; ! mp->m_cmdref = (unsigned)&disk->ra_flags; ((Trl *)mp->m_dscptr)->hsh |= RA_OWN|RA_INT; normalseg5(); i = sc->RAADDR->raip; ! timeout(wakeup, (caddr_t)&disk->ra_flags, 10 * LINEHZ); ! sleep((caddr_t)&disk->ra_flags, PSWP+1); splx(s); } /* Did it go online? */ ! if ((disk->ra_flags & DKF_ONLINE) == 0) { PRINTD(("raopen: disk didn't go online\n")); s = splbio(); ! disk->ra_flags = 0; sc->sc_drives[unit] = NULL; splx(s); return(ENXIO); } + /* + * Now we read the label. Allocate an external label structure if one has + * not already been assigned to this drive. First wait for any pending + * opens/closes to complete. + */ + + while (disk->ra_flags & (DKF_OPENING | DKF_CLOSING)) + sleep(disk, PRIBIO); + + /* + * Next if an external label buffer has not already been allocated do so + * now. This "can not fail" because if the initial pool of label buffers + * has been exhausted the allocation takes place from main memory. The + * return value is the 'click' address to be used when mapping in the label. + */ + + if (disk->ra_label == 0) + disk->ra_label = disklabelalloc(); + + /* + * On first open get label and partition info. We may block reading the + * label so be careful to stop any other opens. + */ + if (disk->ra_open == 0) + { + disk->ra_flags |= DKF_OPENING; + ragetinfo(disk, dev); + disk->ra_flags &= ~DKF_OPENING; + wakeup(disk); + } + /* + * Need to make sure the partition is not out of bounds. This requires + * mapping in the external label. This only happens when a partition + * is opened (at mount time) and isn't an efficiency problem. + */ + mapseg5(disk->ra_label, LABELDESC); + i = ((struct disklabel *)SEG5)->d_npartitions; + normalseg5(); + if (dkpart(dev) >= i) + return(ENXIO); + + mask = 1 << dkpart(dev); + dkoverlapchk(disk->ra_open, dev, disk->ra_label, "ra"); + if (mode == S_IFCHR) + disk->ra_copen |= mask; + else if (mode == S_IFBLK) + disk->ra_bopen |= mask; + else + return(EINVAL); + disk->ra_open |= mask; PRINTD(("raopen: disk online\n")); return(0); } /* + * Disk drivers now have to have close entry points in order to keep + * track of what partitions are still active on a drive. + */ + raclose(dev, flag, mode) + register dev_t dev; + int flag, mode; + { + int s, unit = RAUNIT(dev); + register int mask; + register ra_infoT *disk; + ra_softcT *sc = &ra_sc[RACON(dev)]; + + disk = sc->sc_drives[unit]; + mask = 1 << dkpart(dev); + if (mode == S_IFCHR) + disk->ra_copen &= ~mask; + else if (mode == S_IFBLK) + disk->ra_bopen &= ~mask; + else + return(EINVAL); + disk->ra_open = disk->ra_bopen | disk->ra_copen; + if (disk->ra_open == 0) + { + disk->ra_flags |= DKF_CLOSING; + s = splbio(); + while (rautab[unit].b_actf) + sleep(&rautab[unit], PRIBIO); + splx(s); + disk->ra_flags &= ~DKF_CLOSING; + wakeup(disk); + } + return(0); + } + + /* + * Read disklabel. It is tempting to generalize this routine so that + * all disk drivers could share it. However by the time all of the + * necessary parameters are setup and passed the savings vanish. Also, + * each driver has a different method of calculating the number of blocks + * to use if one large partition must cover the disk. + * + * This routine used to always return success and callers carefully checked + * the return status. Silly. This routine will fake a label (a single + * partition spanning the drive) if necessary but will never return an error. + * + * It is the caller's responsibility to check the validity of partition + * numbers, etc. + */ + + void + ragetinfo(disk, dev) + register ra_infoT *disk; + dev_t dev; + { + struct disklabel locallabel; + char *msg; + register struct disklabel *lp = &locallabel; + int part = dkpart(dev); + /* + * NOTE: partition 0 ('a') is used to read the label. Therefore 'a' must + * start at the beginning of the disk! If there is no label or the label + * is corrupted then 'a' will span the entire disk + */ + register struct partition *pi = lp->d_partitions; + struct partition *kpi = disk->ra_parts; + + bzero(lp, sizeof (*lp)); + lp->d_type = DTYPE_MSCP; + lp->d_secsize = 512; /* XXX */ + lp->d_nsectors = 32; + lp->d_ntracks = 1; + lp->d_secpercyl = 20 * 32; + lp->d_npartitions = 1; /* 'a' */ + pi[0].p_offset = 0; + pi[0].p_size = LABELSECTOR + 1; + pi[0].p_fstype = FS_V71K; + kpi[0].p_offset = 0; /* put where rastrategy will look */ + kpi[0].p_size = LABELSECTOR + 1; + kpi[0].p_fstype = FS_V71K; + msg = readdisklabel((dev & ~7) | 0, rastrategy, lp); /* 'a' */ + if (msg == 0) + { + mapseg5(disk->ra_label, LABELDESC); + bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel)); + normalseg5(); + bcopy(pi, kpi, sizeof (lp->d_partitions)); + return; + } + log(LOG_NOTICE, "ra%da is entire disk: '%s'\n", dkunit(dev), msg); + kpi[0].p_size = disk->ra_nblks; + return; + } + + /* * Initialize controller, data structures, and start hardware * initialization sequence. */ *************** *** 506,513 **** */ sc->sc_ctab.b_un.b_addr = (caddr_t)loint(adr); sc->sc_ctab.b_xmem = hiint(adr); - PRINTD(("rainit: com area addr low=0%o, high=0%o\n", - sc->sc_ctab.b_un.b_addr, sc->sc_ctab.b_xmem)); /* * Start the hardware initialization sequence. --- 585,590 ---- *************** *** 533,562 **** register ra_infoT *disk; register struct buf *dp; ra_softcT *sc = &ra_sc[RACON(bp->b_dev)]; ! int part = minor(bp->b_dev) & 07; daddr_t sz, maxsz; int s; /* Is disk online */ ! if ((disk = sc->sc_drives[dkunit(bp) & 7]) == NULL || disk->ra_dsize <= 0L) goto bad; /* Valid block in device partition */ sz = (bp->b_bcount + 511) >> 9; ! if ((maxsz = disk->ra_size[part].nblocks) < 0) ! maxsz = disk->ra_dsize - disk->ra_size[part].blkoff; ! if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz ! || disk->ra_size[part].blkoff >= disk->ra_dsize) goto bad; ! /* Unibus Map buffer if required */ ! mapalloc(bp); /* * Link the buffer onto the drive queue */ s = splbio(); ! dp = &disk->ra_dtab; if (dp->b_actf == 0) dp->b_actf = bp; else --- 610,665 ---- register ra_infoT *disk; register struct buf *dp; ra_softcT *sc = &ra_sc[RACON(bp->b_dev)]; ! int unit = RAUNIT(bp->b_dev); ! int part = dkpart(bp->b_dev); ! struct partition *pi; daddr_t sz, maxsz; int s; /* Is disk online */ ! if ((disk = sc->sc_drives[unit]) == NULL || ! !(disk->ra_flags & (DKF_ONLINE | DKF_ALIVE))) goto bad; + pi = &disk->ra_parts[part]; /* Valid block in device partition */ sz = (bp->b_bcount + 511) >> 9; ! if (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size) ! { ! sz = pi->p_size - bp->b_blkno; ! /* if exactly at end of disk, return an EOF */ ! if (sz == 0) ! { ! bp->b_resid = bp->b_bcount; ! goto done; ! } ! /* or truncate if part of it fits */ ! if (sz < 0) ! { ! bp->b_error = EINVAL; ! goto bad; ! } ! bp->b_bcount = dbtob(sz); /* compute byte count */ ! } ! /* ! * Check for write to write-protected label area. This does not include ! * sector 0 which is the boot block. ! */ ! if (bp->b_blkno + pi->p_offset <= LABELSECTOR && ! bp->b_blkno + pi->p_offset + sz > LABELSECTOR && ! !(bp->b_flags & B_READ) && !(disk->ra_flags & DKF_WLABEL)) ! { ! bp->b_error = EROFS; goto bad; + } ! mapalloc(bp); /* Unibus Map buffer if required */ /* * Link the buffer onto the drive queue */ s = splbio(); ! dp = &rautab[unit]; if (dp->b_actf == 0) dp->b_actf = bp; else *************** *** 587,592 **** --- 690,696 ---- return; bad: bp->b_flags |= B_ERROR; + done: iodone(bp); return; } *************** *** 598,603 **** --- 702,708 ---- register struct mscp *mp; register struct buf *bp; struct buf *dp; + struct partition *pi; ra_infoT *disk; int i; long temp; *************** *** 627,635 **** --- 732,745 ---- * No more requests for this drive, remove * from controller queue and look at next drive. * We know we're at the head of the controller queue. + * The drive may not need anything, in which case it might + * be shutting down in raclose() and a wakeup is needed. */ dp->b_active = 0; sc->sc_ctab.b_actf = dp->b_forw; + disk = sc->sc_drives[dp - rautab]; + if (disk->ra_open == 0) + wakeup(dp); /* finish close protocol */ goto loop; } *************** *** 651,659 **** goto out; mp->m_cmdref = (unsigned)bp; /* pointer to get back */ mp->m_opcode = bp->b_flags & B_READ ? M_O_READ : M_O_WRITE; ! mp->m_unit = dkunit(bp) & 7; disk = sc->sc_drives[mp->m_unit]; ! temp = bp->b_blkno + disk->ra_size[minor(bp->b_dev) & 7].blkoff; mp->m_lbn_l = loint(temp); mp->m_lbn_h = hiint(temp); mp->m_bytecnt = bp->b_bcount; --- 761,770 ---- goto out; mp->m_cmdref = (unsigned)bp; /* pointer to get back */ mp->m_opcode = bp->b_flags & B_READ ? M_O_READ : M_O_WRITE; ! mp->m_unit = RAUNIT(bp->b_dev); disk = sc->sc_drives[mp->m_unit]; ! pi = &disk->ra_parts[dkpart(bp->b_dev)]; ! temp = bp->b_blkno + pi->p_offset; mp->m_lbn_l = loint(temp); mp->m_lbn_h = hiint(temp); mp->m_bytecnt = bp->b_bcount; *************** *** 786,792 **** break; default: ! printf("ra: state %d ignored\n", sc->sc_state); return; } --- 897,903 ---- break; default: ! printf("ra: state %d ign\n", sc->sc_state); return; } *************** *** 806,812 **** * Check for buffer purge request */ if (sc->sc_com->ra_ca.ca_bdp) { - PRINTD(("ra%d: buffer purge request\n", sc->sc_unit)); sc->sc_com->ra_ca.ca_bdp = 0; sc->RAADDR->rasa = 0; } --- 917,922 ---- *************** *** 821,830 **** /* * Check for command ring transition (Should never happen!) */ ! if (sc->sc_com->ra_ca.ca_cmdint) { ! PRINTD(("ra: command ring transition\n")); sc->sc_com->ra_ca.ca_cmdint = 0; - } restorseg5(seg5); --- 931,938 ---- /* * Check for command ring transition (Should never happen!) */ ! if (sc->sc_com->ra_ca.ca_cmdint) sc->sc_com->ra_ca.ca_cmdint = 0; restorseg5(seg5); *************** *** 969,978 **** switch (mp->m_opcode) { case M_O_ONLIN|M_O_END: if ((disk = sc->sc_drives[mp->m_unit]) == NULL) { ! printf("ra: couldn't ONLINE disk\n"); break; } ! dp = &disk->ra_dtab; if (st == M_S_SUCC) { /* Link the drive onto the controller queue */ --- 1077,1087 ---- switch (mp->m_opcode) { case M_O_ONLIN|M_O_END: if ((disk = sc->sc_drives[mp->m_unit]) == NULL) { ! log(LOG_NOTICE,"ra%d !ONLINE\n", sc->sc_unit * 8 + ! mp->m_unit); break; } ! dp = &rautab[mp->m_unit]; if (st == M_S_SUCC) { /* Link the drive onto the controller queue */ *************** *** 987,993 **** radisksetup(disk, mp); dp->b_active = 1; } else { ! printf("ra%d,%d: OFFLINE\n", sc->sc_unit, mp->m_unit); while (bp = dp->b_actf) { dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; --- 1096,1102 ---- radisksetup(disk, mp); dp->b_active = 1; } else { ! printf("ra%d: OFFLINE\n", sc->sc_unit * 8 + mp->m_unit); while (bp = dp->b_actf) { dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; *************** *** 1002,1010 **** case M_O_AVATN: /* it went offline and we didn't notice */ ! PRINTD(("ra%d: unit %d attention\n", sc->sc_unit, mp->m_unit)); if ((disk = sc->sc_drives[mp->m_unit]) != NULL) ! disk->ra_dsize = -1L; break; case M_O_END: --- 1111,1119 ---- case M_O_AVATN: /* it went offline and we didn't notice */ ! PRINTD(("ra%d: attention\n", sc->sc_unit * 8 + mp->m_unit)); if ((disk = sc->sc_drives[mp->m_unit]) != NULL) ! disk->ra_flags &= ~DKF_ONLINE; break; case M_O_END: *************** *** 1025,1031 **** */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; ! dp = &disk->ra_dtab; #ifdef UCB_METER if (ra_dkn >= 0) { --- 1134,1140 ---- */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; ! dp = &rautab[mp->m_unit]; #ifdef UCB_METER if (ra_dkn >= 0) { *************** *** 1036,1042 **** #endif if (st == M_S_OFFLN || st == M_S_AVLBL) { /* mark unit offline */ ! disk->ra_dsize = -1L; /* Link the buffer onto the front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) --- 1145,1151 ---- #endif if (st == M_S_OFFLN || st == M_S_AVLBL) { /* mark unit offline */ ! disk->ra_flags &= ~DKF_ONLINE; /* Link the buffer onto the front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) *************** *** 1068,1074 **** break; default: ! log(LOG_INFO,"ra: opcode %o\n", mp->m_opcode); ra_error((caddr_t)mp); } } --- 1177,1183 ---- break; default: ! log(LOG_INFO,"ra: op %o\n", mp->m_opcode); ra_error((caddr_t)mp); } } *************** *** 1079,1088 **** radisksetup(disk, mp) register ra_infoT *disk; register struct mscp *mp; ! { ! register struct MEDIA *tp; ! int nameid, numid, i; ! daddr_t blks; nameid = (((loint(mp->m_mediaid) & 0x3f) << 9) | ((hiint(mp->m_mediaid) >> 7) & 0x1ff)); --- 1188,1195 ---- radisksetup(disk, mp) register ra_infoT *disk; register struct mscp *mp; ! { ! int nameid, numid; nameid = (((loint(mp->m_mediaid) & 0x3f) << 9) | ((hiint(mp->m_mediaid) >> 7) & 0x1ff)); *************** *** 1089,1144 **** numid = hiint(mp->m_mediaid) & 0x7f; /* Get unit total block count */ ! disk->ra_dsize = mp->m_uslow + ((long)mp->m_ushigh << 16); /* spill the beans about what we have brought online */ ! log(LOG_NOTICE, "ra%d: %c%c%d%c size=%D id: %X\n", mp->m_unit, mx(nameid,2), mx(nameid,1), numid, mx(nameid,0), ! disk->ra_dsize, mp->m_mediaid); - /* - * Look for override in the table, if found use the partition - * table specified. Else use a size based rule for assigning on - * of the 5 general purpose tables. - */ - - for (blks = disk->ra_dsize, tp = Mscptbl; tp->id7; tp++) - { - if (tp->id7 == numid && tp->name15 == nameid) - { - disk->ra_size = tp->parts; - log(LOG_NOTICE, "ra%d: old table\n", mp->m_unit); - return; - } - } - if (blks < 24244L) - { - i = 3; /* < ~12mb = type 3 */ - disk->ra_size = ra_gen3; - } - else if (blks < 259740L) - { - i = 1; /* < ~112mb = type 1 */ - disk->ra_size = ra_gen1; - } - else if (blks < 669340L) /* < ~330mb = type 2 */ - { - i = 2; - disk->ra_size = ra_gen2; - } - else if (blks < 851804L) /* < ~420mb = type 4 */ - { - i = 4; - disk->ra_size = ra_gen4; - } - else - { - i = 5; /* > ~420mb = type 5 */ - disk->ra_size = ra_gen5; - } - log(LOG_NOTICE, "ra%d: type %d partitions\n", mp->m_unit, i); - } - /* * this is a routine rather than a macro to save space - shifting, etc * generates a lot of code. --- 1196,1211 ---- numid = hiint(mp->m_mediaid) & 0x7f; /* Get unit total block count */ ! disk->ra_nblks = mp->m_uslow + ((long)mp->m_ushigh << 16); /* spill the beans about what we have brought online */ ! log(LOG_NOTICE, "ra%d: %c%c%d%c size=%D\n", ! disk->ra_unit * 8 + mp->m_unit, mx(nameid,2), mx(nameid,1), numid, mx(nameid,0), ! disk->ra_nblks); ! disk->ra_flags |= DKF_ONLINE; ! } /* * this is a routine rather than a macro to save space - shifting, etc * generates a lot of code. *************** *** 1155,1160 **** --- 1222,1241 ---- return(c + '@'); } + raioctl(dev, cmd, data, flag) + dev_t dev; + int cmd; + caddr_t data; + int flag; + { + ra_softcT *sc = &ra_sc[RACON(dev)]; + ra_infoT *disk = sc->sc_drives[RAUNIT(dev)]; + int error; + + error = ioctldisklabel(dev, cmd, data, flag, disk, rastrategy); + return(error); + } + /* * Process an error log message * *************** *** 1166,1172 **** ra_error(mp) register struct mslg *mp; { ! printf("ra: %s error, ", mp->me_flags & (M_LF_SUCC|M_LF_CONT) ? "soft" : "hard"); switch (mp->me_format) { --- 1247,1253 ---- ra_error(mp) register struct mslg *mp; { ! printf("ra: %s err, ", mp->me_flags & (M_LF_SUCC|M_LF_CONT) ? "soft" : "hard"); switch (mp->me_format) { *************** *** 1177,1183 **** printf("M_F_BUSADDR %o", mp->me_busaddr); break; case M_F_DISKTRN: ! printf("disk xfer, unit %d grp x%x hdr x%x", mp->me_unit, mp->me_group, mp->me_hdr); break; case M_F_SDI: --- 1258,1264 ---- printf("M_F_BUSADDR %o", mp->me_busaddr); break; case M_F_DISKTRN: ! printf("disk xfr, unit %d grp x%x hdr x%x", mp->me_unit, mp->me_group, mp->me_hdr); break; case M_F_SDI: *************** *** 1218,1239 **** register ra_infoT *disk; register struct mscp *mp; struct mscp *racmd(); daddr_t bn, dumpsize; long paddr, maddr; ! int count; struct ubmap *ubp; int unit, partition; segm seg5; /* paranoia, space hack */ - disk = ra_disks; unit = RAUNIT(dev); sc = &ra_sc[RACON(dev)]; ! partition = minor(dev) & 7; ! if (bdevsw[major(dev)].d_strategy != rastrategy || sc->RAADDR == NULL) return(EINVAL); ! /* Init RA controller */ paddr = _iomap(ra_com[sc->sc_unit]); if (ubmap) { ubp = UBMAP; --- 1299,1333 ---- register ra_infoT *disk; register struct mscp *mp; struct mscp *racmd(); + struct partition *pi; daddr_t bn, dumpsize; long paddr, maddr; ! int count, memblks; struct ubmap *ubp; int unit, partition; segm seg5; /* paranoia, space hack */ unit = RAUNIT(dev); sc = &ra_sc[RACON(dev)]; ! partition = dkpart(dev); ! if (sc->RAADDR == NULL) return(EINVAL); + disk = sc->sc_drives[unit]; + /* + * The drive to which we dump must be present and alive. + */ + if (!disk || !(disk->ra_flags & DKF_ALIVE)) + return(ENXIO); + pi = &disk->ra_parts[partition]; + /* + * Paranoia - we do not dump to a partition if it has not been declared as + * a 'swap' type of filesystem. + */ + if (pi->p_fstype != FS_SWAP) + return(EFTYPE); ! /* Init RA controller */ paddr = _iomap(ra_com[sc->sc_unit]); if (ubmap) { ubp = UBMAP; *************** *** 1265,1297 **** sc->RAADDR->rasa = RA_GO; ramsginit(sc, sc->sc_com->ra_ca.ca_rsp, mp, 0, 2, 0); if (!racmd(M_O_STCON, unit, sc)) { ! PRINTB(("radump: failed to start controller\n")); return(EFAULT); } ! PRINTB(("radump: controller up ok\n")); /* Bring disk for dump online */ if (!(mp = racmd(M_O_ONLIN, unit, sc))) { ! PRINTB(("radump: failed to bring disk online\n")); return(EFAULT); } ! radisksetup(disk, mp); ! dumpsize = MIN(disk->ra_dsize - disk->ra_size[partition].blkoff, ! disk->ra_size[partition].nblocks); ! PRINTB(("radump: disk up ok, size=%D, type=%d\n", dumpsize, hiint(mp->m_mediaid) & 0xff)); /* Check if dump ok on this disk */ ! if (dumplo < 0 || dumplo >= dumpsize || dumpsize <= 0) return(EINVAL); ! dumpsize -= dumplo; /* Save core to dump partition */ ubp = &UBMAP[1]; ! for (paddr = 0L; dumpsize > 0; dumpsize -= count) { ! count = MIN(dumpsize, DBSIZE); ! bn = dumplo + (paddr >> PGSHIFT) ! + disk->ra_size[partition].blkoff; maddr = paddr; if (ubmap) { --- 1359,1391 ---- sc->RAADDR->rasa = RA_GO; ramsginit(sc, sc->sc_com->ra_ca.ca_rsp, mp, 0, 2, 0); if (!racmd(M_O_STCON, unit, sc)) { ! PRINTB(("radump: failed start controller\n")); return(EFAULT); } ! PRINTB(("radump: controller up\n")); /* Bring disk for dump online */ if (!(mp = racmd(M_O_ONLIN, unit, sc))) { ! PRINTB(("radump: failed online\n")); return(EFAULT); } ! ! dumpsize = rasize(dev) - dumplo; ! memblks = ctod(physmem); ! PRINTB(("radump: disk up, size=%D, type=%d\n", dumpsize, hiint(mp->m_mediaid) & 0xff)); /* Check if dump ok on this disk */ ! if (dumplo < 0 || dumpsize <= 0) return(EINVAL); ! if (memblks > dumpsize) ! memblks = dumpsize; ! bn = dumplo + pi->p_offset; /* Save core to dump partition */ ubp = &UBMAP[1]; ! for (paddr = 0L; memblks > 0; ) { ! count = MIN(memblks, DBSIZE); maddr = paddr; if (ubmap) { *************** *** 1310,1316 **** if (racmd(M_O_WRITE, unit, sc) == 0) return(EIO); ! paddr += (DBSIZE << PGSHIFT); } restorseg5(seg5); return(0); --- 1404,1412 ---- if (racmd(M_O_WRITE, unit, sc) == 0) return(EIO); ! paddr += (count << PGSHIFT); ! bn += count; ! memblks -= count; } restorseg5(seg5); return(0); *************** *** 1354,1361 **** #endif RA_DUMP /* ! * Assumes the 'open' routine has already been called to bring the ! * drive online and initialize the drive size structures. */ daddr_t rasize(dev) --- 1450,1458 ---- #endif RA_DUMP /* ! * Return the number of blocks in a partition. Call raopen() to online ! * the drive if necessary. If an open is necessary then a matching close ! * will be done. */ daddr_t rasize(dev) *************** *** 1363,1370 **** { ra_softcT *sc = &ra_sc[RACON(dev)]; register ra_infoT *disk; disk = sc->sc_drives[RAUNIT(dev)]; ! return(disk->ra_size[dev & 7].nblocks); } #endif NRAC > 0 && NRAD > 0 --- 1460,1483 ---- { ra_softcT *sc = &ra_sc[RACON(dev)]; register ra_infoT *disk; + daddr_t psize; + int didopen = 0; disk = sc->sc_drives[RAUNIT(dev)]; ! /* ! * This should never happen but if we get called early in the kernel's ! * life (before opening the swap or root devices) then we have to do ! * the open here. ! */ ! if (disk->ra_open == 0) ! { ! if (raopen(dev, FREAD|FWRITE, S_IFBLK)) ! return(-1); ! didopen = 1; ! } ! psize = disk->ra_parts[dkpart(dev)].p_size; ! if (didopen) ! raclose(dev, FREAD|FWRITE, S_IFBLK); ! return(psize); } #endif NRAC > 0 && NRAD > 0 *** /usr/src/sys/pdpuba/hk.c.old Tue Dec 29 22:29:57 1992 --- /usr/src/sys/pdpuba/hk.c Thu Apr 13 22:33:02 1995 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)hk.c 2.0 (2.11BSD GTE) 12/29/92 */ /* --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)hk.c 2.1 (2.11BSD GTE) 1995/04/13 */ /* *************** *** 13,18 **** --- 13,20 ---- * It does overlapped seeks, ECC, and bad block handling. * salkind@nyu * + * dkunit() takes a 'dev_t' now instead of 'buf *'. 1995/04/13 - sms + * * Modified to correctly handle 22 bit addressing available on DILOG * DQ615 controller. 05/31/90 -- tymann@oswego.edu * *************** *** 36,41 **** --- 38,45 ---- #include "hkreg.h" #include "dkbad.h" #include "dk.h" + #include "disklabel.h" + #include "disk.h" #include "syslog.h" #define NHK7CYL 815 *************** *** 169,175 **** long sz; struct size *szp; ! unit = dkunit(bp); part = bp->b_dev & 7; if (unit >= NHK || !HKADDR || !(szp = hk_sizes[unit])) { bp->b_error = ENXIO; --- 173,179 ---- long sz; struct size *szp; ! unit = dkunit(bp->b_dev); part = bp->b_dev & 7; if (unit >= NHK || !HKADDR || !(szp = hk_sizes[unit])) { bp->b_error = ENXIO; *************** *** 176,182 **** goto bad; } sz = (bp->b_bcount + (NBPG-1)) >> PGSHIFT; ! if (bp->b_blkno < 0 || (bn = dkblock(bp))+sz > szp[part].nblocks) { bp->b_error = EINVAL; goto bad; } --- 180,186 ---- goto bad; } sz = (bp->b_bcount + (NBPG-1)) >> PGSHIFT; ! if (bp->b_blkno < 0 || (bn = bp->b_blkno)+sz > szp[part].nblocks) { bp->b_error = EINVAL; goto bad; } *************** *** 294,301 **** goto loop; } hktab.b_active++; ! unit = dkunit(bp); ! bn = dkblock(bp); sn = bn % HK_NSPC; tn = sn / HK_NSECT; --- 298,305 ---- goto loop; } hktab.b_active++; ! unit = dkunit(bp->b_dev); ! bn = bp->b_blkno; sn = bn % HK_NSPC; tn = sn / HK_NSECT; *************** *** 366,372 **** if (hktab.b_active) { dp = hktab.b_actf; bp = dp->b_actf; ! unit = dkunit(bp); #ifdef UCB_METER if (hk_dkn >= 0) dk_busy &= ~(1 << (hk_dkn + NHK)); --- 370,376 ---- if (hktab.b_active) { dp = hktab.b_actf; bp = dp->b_actf; ! unit = dkunit(bp->b_dev); #ifdef UCB_METER if (hk_dkn >= 0) dk_busy &= ~(1 << (hk_dkn + NHK)); *************** *** 591,598 **** ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / NBPG; } ! unit = dkunit(bp); ! bn = dkblock(bp); cn = bp->b_cylin - bn / HK_NSPC; bn += npx; cn += bn / HK_NSPC; --- 595,602 ---- ndone = (wc * NBPW) + bp->b_bcount; npx = ndone / NBPG; } ! unit = dkunit(bp->b_dev); ! bn = bp->b_blkno; cn = bp->b_cylin - bn / HK_NSPC; bn += npx; cn += bn / HK_NSPC; *** /usr/src/sys/pdpuba/br.c.old Sun Jan 3 18:29:18 1993 --- /usr/src/sys/pdpuba/br.c Thu Apr 13 23:12:33 1995 *************** *** 30,35 **** --- 30,36 ---- * 12/23/92 - add the partition size routine. * 1/2/93 - remove unibus map ifdefs, the run time check using 'ubmap' is * sufficient and does the right thing. + * 1995/04/13 - change reference to dkunit. */ #include "br.h" *************** *** 44,49 **** --- 45,52 ---- #include "user.h" #include "brreg.h" #include "dk.h" + #include "disklabel.h" + #include "disk.h" #include "syslog.h" #include "map.h" #include "uba.h" *************** *** 332,338 **** while (((Br_addr->brcs.w&BR_RDY) == 0) && --ctr) ; if (brtab.b_errcnt == 0) { log(LOG_WARNING,"br%d%c ds:%b er:%b cs:%b wc:%o ba:%o ca:%o da:%o bae:%o\n", ! dkunit(bp), 'a'+ (bp->b_dev & 07), brsave.brds, BRDS_BITS, brsave.brer, BRER_BITS, brsave.brcs.w, BR_BITS, brsave.brwc,brsave.brba, brsave.brca, brsave.brda, brsave.brae); --- 335,341 ---- while (((Br_addr->brcs.w&BR_RDY) == 0) && --ctr) ; if (brtab.b_errcnt == 0) { log(LOG_WARNING,"br%d%c ds:%b er:%b cs:%b wc:%o ba:%o ca:%o da:%o bae:%o\n", ! dkunit(bp->b_dev), 'a'+ dkpart(bp->b_dev), brsave.brds, BRDS_BITS, brsave.brer, BRER_BITS, brsave.brcs.w, BR_BITS, brsave.brwc,brsave.brba, brsave.brca, brsave.brda, brsave.brae); *** /usr/src/sys/pdpuba/rl.c.old Sat Jan 2 23:24:01 1993 --- /usr/src/sys/pdpuba/rl.c Wed Jun 28 19:59:31 1995 *************** *** 3,18 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)rl.c 1.4 (2.11BSD GTE) 1/2/93 */ /* * RL01/RL02 disk driver */ #include "rl.h" #if NRL > 0 #include "param.h" #include "buf.h" #include "user.h" --- 3,27 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)rl.c 1.5 (2.11BSD GTE) 1995/06/28 */ /* * RL01/RL02 disk driver + * + * Date: June 15, 1995. + * Modified to handle disklabels. This provides the ability to partition + * a drive. An RL02 can hold a root and swap partition quite easily and is + * useful for maintenance. */ #include "rl.h" #if NRL > 0 + #if NRL > 4 + error to have more than 4 drives - only 1 controller is supported. + #endif + #include "param.h" #include "buf.h" #include "user.h" *************** *** 19,26 **** --- 28,41 ---- #include "systm.h" #include "conf.h" #include "dk.h" + #include "file.h" + #include "ioctl.h" + #include "stat.h" #include "map.h" #include "uba.h" + #include "disklabel.h" + #include "disk.h" + #include "syslog.h" #include "rlreg.h" #define RL01_NBLKS 10240 /* Number of UNIX blocks for an RL01 drive */ *************** *** 29,45 **** #define RL_SECSZ 256 /* bytes per sector */ #define rlwait(r) while (((r)->rlcs & RL_CRDY) == 0) struct rldevice *RLADDR; static int q22bae = 1; struct buf rlutab[NRL]; /* Seek structure for each device */ struct buf rltab; struct rl_softc { short cn[4]; /* location of heads for each drive */ ! short type[4]; /* parameter dependent on drive type (RL01/2) */ short dn; /* drive number */ short com; /* read or write command word */ short chn; /* cylinder and head number */ --- 44,63 ---- #define RL_SECSZ 256 /* bytes per sector */ #define rlwait(r) while (((r)->rlcs & RL_CRDY) == 0) + #define RLUNIT(x) ((minor(x) >> 3) & 7) struct rldevice *RLADDR; static int q22bae = 1; + daddr_t rlsize(); + int rlstrategy(); struct buf rlutab[NRL]; /* Seek structure for each device */ struct buf rltab; struct rl_softc { short cn[4]; /* location of heads for each drive */ ! short nblks[4]; /* number of blocks on drive */ short dn; /* drive number */ short com; /* read or write command word */ short chn; /* cylinder and head number */ *************** *** 51,58 **** long l; } rl_un; /* address of memory for transfer */ ! } rl = {-1,-1,-1,-1, -1,-1,-1,-1}; /* initialize cn[] and type[] */ #ifdef UCB_METER static int rl_dkn = -1; /* number for iostat */ #endif --- 69,78 ---- long l; } rl_un; /* address of memory for transfer */ ! } rl = {-1,-1,-1,-1}; /* initialize cn[] */ + struct dkdevice rl_dk[NRL]; + #ifdef UCB_METER static int rl_dkn = -1; /* number for iostat */ #endif *************** *** 67,73 **** { #ifdef UCB_METER if (rl_dkn < 0) { ! dk_alloc(&rl_dkn, NRL+1, "rl", 40L * 40L * 128L); if (rl_dkn >= 0) dk_wps[rl_dkn+NRL] = 0L; } --- 87,93 ---- { #ifdef UCB_METER if (rl_dkn < 0) { ! dk_alloc(&rl_dkn, NRL+1, "rl", 20L * 10L * 512L); if (rl_dkn >= 0) dk_wps[rl_dkn+NRL] = 0L; } *************** *** 83,143 **** return (0); } ! rlopen(dev, flag) dev_t dev; int flag; ! { ! register int drive = minor(dev); ! ! if (drive >= NRL || !RLADDR) return (ENXIO); ! if (rl.type[drive] == -1) ! rlgsts(drive); ! return (0); ! } rlstrategy(bp) register struct buf *bp; { ! register int drive; ! int nblocks, s, ctr; ! drive = minor(bp->b_dev); ! if (drive >= NRL || !RLADDR) { bp->b_error = ENXIO; goto bad; ! } ! /* ! * We must determine what type of drive we are talking to in order ! * to determine how many blocks are on the device. The rl.type[] ! * array has been initialized with -1's so that we may test first ! * contact with a particular drive and do this determination only once. ! */ ! if (rl.type[drive] < 0) ! rlgsts(drive); ! /* determine nblocks based upon which drive this is */ ! nblocks = rl.type[drive]; ! if(bp->b_blkno >= nblocks) { ! if((bp->b_blkno == nblocks) && (bp->b_flags & B_READ)) bp->b_resid = bp->b_bcount; ! else { ! bp->b_error = ENXIO; ! bad: ! bp->b_flags |= B_ERROR; } ! iodone(bp); ! return; ! } mapalloc(bp); bp->av_forw = NULL; ! bp->b_cylin = (int)(bp->b_blkno/20l); s = splbio(); disksort(&rlutab[drive], bp); /* Put the request on drive Q */ ! if(rltab.b_active == NULL) rlstart(); splx(s); } rlstart() --- 103,341 ---- return (0); } ! rlopen(dev, flag, mode) dev_t dev; int flag; ! int mode; ! { ! int i, mask; ! int drive = RLUNIT(dev); ! register struct dkdevice *disk; ! ! if (drive >= NRL || !RLADDR) return (ENXIO); ! disk = &rl_dk[drive]; ! if ((disk->dk_flags & DKF_ALIVE) == 0) ! { ! if (rlgsts(drive) < 0) ! return(ENXIO); ! } ! /* ! * The drive has responded to a GETSTATUS (is alive). Now we read the ! * label. Allocate an external label structure if one has not already ! * been assigned to this drive. First wait for any pending opens/closes ! * to complete. ! */ ! while (disk->dk_flags & (DKF_OPENING | DKF_CLOSING)) ! sleep(disk, PRIBIO); + /* + * Next if an external label buffer has not already been allocated do so now. + * This "can not fail" because if the initial pool of label buffers has + * been exhausted the allocation takes place from main memory. The return + * value is the 'click' address to be used when mapping in the label. + */ + + if (disk->dk_label == 0) + disk->dk_label = disklabelalloc(); + + /* + * On first open get label and partition info. We may block reading the + * label so be careful to stop any other opens. + */ + + if (disk->dk_openmask == 0) + { + disk->dk_flags |= DKF_OPENING; + rlgetinfo(disk, dev); + disk->dk_flags &= ~DKF_OPENING; + wakeup(disk); + } + /* + * Need to make sure the partition is not out of bounds. This requires + * mapping in the external label. This only happens when a partition + * is opened (at mount time) and isn't an efficiency problem. + */ + mapseg5(disk->dk_label, LABELDESC); + i = ((struct disklabel *)SEG5)->d_npartitions; + normalseg5(); + if (dkpart(dev) >= i) + return(ENXIO); + + mask = 1 << dkpart(dev); + dkoverlapchk(disk->dk_openmask, dev, disk->dk_label, "rl"); + if (mode == S_IFCHR) + disk->dk_copenmask |= mask; + else if (mode == S_IFBLK) + disk->dk_bopenmask |= mask; + else + return(EINVAL); + disk->dk_openmask |= mask; + return(0); + } + + /* + * Disk drivers now have to have close entry points in order to keep + * track of what partitions are still active on a drive. + */ + rlclose(dev, flag, mode) + register dev_t dev; + int flag, mode; + { + int s, drive = RLUNIT(dev); + register int mask; + register struct dkdevice *disk; + + disk = &rl_dk[drive]; + mask = 1 << dkpart(dev); + if (mode == S_IFCHR) + disk->dk_copenmask &= ~mask; + else if (mode == S_IFBLK) + disk->dk_bopenmask &= ~mask; + else + return(EINVAL); + disk->dk_openmask = disk->dk_bopenmask | disk->dk_copenmask; + if (disk->dk_openmask == 0) + { + disk->dk_flags |= DKF_CLOSING; + s = splbio(); + while (rlutab[drive].b_actf) + { + disk->dk_flags |= DKF_WANTED; + sleep(&rlutab[drive], PRIBIO); + } + splx(s); + disk->dk_flags &= ~(DKF_CLOSING | DKF_WANTED); + wakeup(disk); + } + return(0); + } + + /* + * Read disklabel. It is tempting to generalize this routine so that + * all disk drivers could share it. However by the time all of the + * necessary parameters are setup and passed the savings vanish. Also, + * each driver has a different method of calculating the number of blocks + * to use if one large partition must cover the disk. + * + * This routine used to always return success and callers carefully checked + * the return status. Silly. This routine will fake a label (a single + * partition spanning the drive) if necessary but will never return an error. + * + * It is the caller's responsibility to check the validity of partition + * numbers, etc. + */ + + void + rlgetinfo(disk, dev) + register struct dkdevice *disk; + dev_t dev; + { + struct disklabel locallabel; + char *msg; + register struct disklabel *lp = &locallabel; + int part = dkpart(dev); + /* + * NOTE: partition 0 ('a') is used to read the label. Therefore 'a' must + * start at the beginning of the disk! If there is no label or the label + * is corrupted then 'a' will span the entire disk + */ + register struct partition *pi = lp->d_partitions; + struct partition *kpi = disk->dk_parts; + + bzero(lp, sizeof (*lp)); + lp->d_type = DTYPE_DEC; + lp->d_secsize = 512; /* XXX */ + lp->d_nsectors = 20; + lp->d_ntracks = 2; + lp->d_secpercyl = 2 * 20; + lp->d_npartitions = 1; /* 'a' */ + pi[0].p_offset = 0; + pi[0].p_size = LABELSECTOR + 1; + pi[0].p_fstype = FS_V71K; + kpi[0].p_offset = 0; /* put where rlstrategy will look */ + kpi[0].p_size = LABELSECTOR + 1; + kpi[0].p_fstype = FS_V71K; + msg = readdisklabel((dev & ~7) | 0, rlstrategy, lp); /* 'a' */ + if (msg == 0) + { + mapseg5(disk->dk_label, LABELDESC) + bcopy(lp, (struct disklabel *)SEG5, sizeof (struct disklabel)); + normalseg5(); + bcopy(pi, kpi, sizeof (lp->d_partitions)); + return; + } + log(LOG_NOTICE, "rl%da is entire disk: '%s'\n", dkunit(dev), msg); + kpi[0].p_size = rl.nblks[dkunit(dev)]; + return; + } + rlstrategy(bp) register struct buf *bp; { ! int drive, part; ! int s, ctr; ! daddr_t sz; ! register struct dkdevice *disk; ! register struct partition *pi; ! drive = RLUNIT(bp->b_dev); ! part = dkpart(bp->b_dev); ! disk = &rl_dk[drive]; ! ! if (drive >= NRL || !RLADDR || !(disk->dk_flags & DKF_ALIVE)) ! { bp->b_error = ENXIO; goto bad; ! } ! pi = &disk->dk_parts[part]; ! ! /* Valid block in device partition */ ! sz = (bp->b_bcount + 511) >> 9; ! if (bp->b_blkno < 0 || bp->b_blkno + sz > pi->p_size) ! { ! sz = pi->p_size - bp->b_blkno; ! /* if exactly at end of disk, return an EOF */ ! if (sz == 0) ! { bp->b_resid = bp->b_bcount; ! goto done; ! } ! /* or truncate if part of it fits */ ! if (sz < 0) ! { ! bp->b_error = EINVAL; ! goto bad; ! } ! bp->b_bcount = dbtob(sz); /* compute byte count */ } ! /* ! * Check for write to write-protected label area. This does not include ! * sector 0 which is the boot block. ! */ ! if (bp->b_blkno + pi->p_offset <= LABELSECTOR && ! bp->b_blkno + pi->p_offset + sz > LABELSECTOR && ! !(bp->b_flags & B_READ) && !(disk->dk_flags & DKF_WLABEL)) ! { ! bp->b_error = EROFS; ! goto bad; ! } mapalloc(bp); bp->av_forw = NULL; ! bp->b_cylin = (int)(bp->b_blkno/20L); s = splbio(); disksort(&rlutab[drive], bp); /* Put the request on drive Q */ ! if (rltab.b_active == 0) rlstart(); splx(s); + return; + bad: + bp->b_flags |= B_ERROR; + done: + iodone(bp); + return; } rlstart() *************** *** 144,156 **** { register struct rl_softc *rlp = &rl; register struct buf *bp, *dp; int unit; if((bp = rltab.b_actf) == NULL) { for(unit = 0;unit < NRL;unit++) { /* Start seeks */ dp = &rlutab[unit]; ! if(dp->b_actf == NULL) continue; rlseek((int)(dp->b_actf->b_blkno/20l),unit); } --- 342,368 ---- { register struct rl_softc *rlp = &rl; register struct buf *bp, *dp; + struct dkdevice *disk; int unit; if((bp = rltab.b_actf) == NULL) { for(unit = 0;unit < NRL;unit++) { /* Start seeks */ dp = &rlutab[unit]; ! if (dp->b_actf == NULL) ! { ! /* ! * No more requests in the drive queue. If a close is pending waiting ! * for activity to be done on the drive then issue a wakeup and clear the ! * flag. ! */ ! disk = &rl_dk[unit]; ! if (disk->dk_flags & DKF_WANTED) ! { ! disk->dk_flags &= ~DKF_WANTED; ! wakeup(dp); ! } continue; + } rlseek((int)(dp->b_actf->b_blkno/20l),unit); } *************** *** 159,165 **** return; } rltab.b_active++; ! rlp->dn = minor(bp->b_dev); rlp->chn = bp->b_blkno / 20; rlp->sn = (bp->b_blkno % 20) << 1; rlp->bleft = bp->b_bcount; --- 371,377 ---- return; } rltab.b_active++; ! rlp->dn = RLUNIT(bp->b_dev); rlp->chn = bp->b_blkno / 20; rlp->sn = (bp->b_blkno % 20) << 1; rlp->bleft = bp->b_bcount; *************** *** 343,377 **** } } #ifdef RL_DUMP /* * Dump routine for RL01/02 - * Dumps from dumplo to end of memory/end of disk section for minor(dev). * This routine is stupid (because the rl is stupid) and assumes that * dumplo begins on a track boundary! */ ! #define DBSIZE 10 /* Same number */ rldump(dev) dev_t dev; { register struct rldevice *rladdr = RLADDR; daddr_t bn, dumpsize; long paddr; ! register int count; u_int com; ! int ccn, cn, tn, sn, unit, dif, ctr; register struct ubmap *ubp; ! unit = minor(dev); ! ctr = 0; ! if (rlgsts(unit) < 0) ! return(EIO); ! dumpsize = rl.type[unit]; ! if((dumplo < 0) || (dumplo >= dumpsize)) return(EINVAL); ! dumpsize -= dumplo; rladdr->rlcs = (dev << 8) | RL_RHDR; /* Find the heads */ rlwait(rladdr); --- 555,615 ---- } } + rlioctl(dev, cmd, data, flag) + dev_t dev; + int cmd; + caddr_t data; + int flag; + { + register int error; + struct dkdevice *disk = &rl_dk[RLUNIT(dev)]; + + error = ioctldisklabel(dev, cmd, data, flag, disk, rlstrategy); + return(error); + } + #ifdef RL_DUMP /* * Dump routine for RL01/02 * This routine is stupid (because the rl is stupid) and assumes that * dumplo begins on a track boundary! */ ! #define DBSIZE 10 /* Half a track of sectors. Can't go higher ! * because only a single UMR is set for the transfer. ! */ rldump(dev) dev_t dev; { register struct rldevice *rladdr = RLADDR; + struct dkdevice *disk; + struct partition *pi; daddr_t bn, dumpsize; long paddr; ! int count, memblks; u_int com; ! int ccn, cn, tn, sn, unit, dif, partition; register struct ubmap *ubp; ! unit = RLUNIT(dev); ! partition = dkpart(dev); ! disk = &rl_dk[unit]; ! pi = &disk->dk_parts[partition]; ! ! if (!(disk->dk_flags & DKF_ALIVE)) ! return(ENXIO); ! if (pi->p_fstype != FS_SWAP) ! return(EFTYPE); ! ! dumpsize = rlsize(dev) - dumplo; ! memblks = ctod(physmem); ! ! if (dumplo < 0 || dumpsize <= 0) return(EINVAL); ! if (memblks > dumpsize) ! memblks = dumpsize; ! bn = dumplo + pi->p_offset; rladdr->rlcs = (dev << 8) | RL_RHDR; /* Find the heads */ rlwait(rladdr); *************** *** 378,386 **** ccn = ((unsigned)rladdr->rlmp&0177700) >> 6; ubp = &UBMAP[0]; ! for(paddr = 0L;dumpsize > 0;dumpsize -= count) { ! count = dumpsize > DBSIZE ? DBSIZE : dumpsize; ! bn = dumplo + (paddr >> PGSHIFT); cn = bn / 20; sn = (unsigned)(bn % 20) << 1; dif = (ccn >> 1) - (cn >> 1); --- 616,623 ---- ccn = ((unsigned)rladdr->rlmp&0177700) >> 6; ubp = &UBMAP[0]; ! for (paddr = 0L; memblks > 0; ) { ! count = MIN(memblks, DBSIZE); cn = bn / 20; sn = (unsigned)(bn % 20) << 1; dif = (ccn >> 1) - (cn >> 1); *************** *** 421,427 **** RLDA_BITS, rladdr->rlmp, RLMP_BITS); return(EIO); } ! paddr += (DBSIZE << PGSHIFT); } return(0); /* Filled the disk */ } --- 658,666 ---- RLDA_BITS, rladdr->rlmp, RLMP_BITS); return(EIO); } ! paddr += (count << PGSHIFT); ! bn += count; ! memblks -= count; } return(0); /* Filled the disk */ } *************** *** 428,445 **** #endif RL_DUMP /* ! * Assumes the 'open' routine has already been called to get the drive ! * status and determine what type of drive this is. */ daddr_t rlsize(dev) ! dev_t dev; { ! return(rl.type[minor(dev)]); } ! /* For some unknown reason the RL02 (seems to be * only drive 1) does not return a valid drive status * the first time that a GET STATUS request is issued * for the drive, in fact it can take up to three or more --- 667,708 ---- #endif RL_DUMP /* ! * Return the number of blocks in a partition. Call rlopen() to online ! * the drive if necessary. If an open is necessary then a matching close ! * will be done. */ daddr_t rlsize(dev) ! register dev_t dev; { + register struct dkdevice *disk; + daddr_t psize; + int didopen = 0; ! disk = &rl_dk[RLUNIT(dev)]; ! /* ! * This should never happen but if we get called early in the kernel's ! * life (before opening the swap or root devices) then we have to do ! * the open here. ! */ ! if (disk->dk_openmask == 0) ! { ! if (rlopen(dev, FREAD|FWRITE, S_IFBLK)) ! return(-1); ! didopen = 1; ! } ! psize = disk->dk_parts[dkpart(dev)].p_size; ! if (didopen) ! raclose(dev, FREAD|FWRITE, S_IFBLK); ! return(psize); } ! /* ! * This routine is only called by rlopen() the first time a drive is ! * touched. Once the number of blocks has been determined the drive is ! * marked 'alive'. ! * ! * For some unknown reason the RL02 (seems to be * only drive 1) does not return a valid drive status * the first time that a GET STATUS request is issued * for the drive, in fact it can take up to three or more *************** *** 465,477 **** { printf("rl%d: !status cs=%b da=%b\n", drive, rp->rlcs, RL_BITS, rp->rlda, RLDA_BITS); ! rl.type[drive] = RL02_NBLKS; /* assume RL02 */ return(-1); } ! else if (rp->rlmp & RLMP_DTYP) ! rl.type[drive] = RL02_NBLKS; /* drive is RL02 */ else ! rl.type[drive] = RL01_NBLKS; /* drive RL01 */ return(0); } ! #endif --- 728,741 ---- { printf("rl%d: !status cs=%b da=%b\n", drive, rp->rlcs, RL_BITS, rp->rlda, RLDA_BITS); ! rl_dk[drive].dk_flags &= ~DKF_ALIVE; return(-1); } ! if (rp->rlmp & RLMP_DTYP) ! rl.nblks[drive] = RL02_NBLKS; /* drive is RL02 */ else ! rl.nblks[drive] = RL01_NBLKS; /* drive RL01 */ ! rl_dk[drive].dk_flags |= DKF_ALIVE; return(0); } ! #endif /* NRL */