xy.c

Upload User: acmefrp
Upload Date: 2010-03-06
Package Size: 23768k
Code Size: 74k
Category: OS Develop
Development Platform: C/C++
  1. #ifndef lint
  2. static char sccsid[] = "@(#)xy.c 1.1 92/07/30 SMI";
  3. #endif
  4. /*
  5.  * Copyright (c) 1987 by Sun Microsystems, Inc.
  6.  */
  7. /*
  8.  * Driver for Xylogics 450/451 SMD disk controllers
  9.  */
  10. #include <sys/param.h>
  11. #include <sys/systm.h>
  12. #include <sys/dk.h>
  13. #include <sys/buf.h>
  14. #include <sys/conf.h>
  15. #include <sys/user.h>
  16. #include <sys/map.h>
  17. #include <sys/vmmac.h>
  18. #include <sys/uio.h>
  19. #include <sys/kernel.h>
  20. #include <sys/dkbad.h>
  21. #include <sys/file.h>
  22. #include <sys/kmem_alloc.h>
  23. #include <vm/hat.h>
  24. #include <vm/seg.h>
  25. #include <vm/as.h>
  26. #include <machine/psl.h>
  27. #include <sun/dkio.h>
  28. #include <sundev/mbvar.h>
  29. #include <sundev/xyvar.h>
  30. #include <sundev/xyerr.h>
  31. extern char *strncpy();
  32. extern int dkn;
  33. #ifdef DKIOCWCHK
  34. extern int dvmasize, maxphys;
  35. #endif
  36. static initlabel(), uselabel(), usegeom(), islabel(), ck_cksum();
  37. static initiopb(), cleariopb(), doattach(), findslave();
  38. static struct xyerror *finderr();
  39. static printerr();
  40. #ifdef DKIOCWCHK
  41. static void xywchk_start();
  42. static int xywchk_done();
  43. #endif DKIOCWCHK
  44. int xyprobe(), xyslave(), xyattach(), xygo(), xydone(), xypoll();
  45. /*
  46.  * Config dependent structures -- declared in xy_conf.c
  47.  */
  48. extern int nxy, nxyc;
  49. extern struct mb_ctlr *xycinfo[];
  50. extern struct mb_device *xydinfo[];
  51. extern struct xyunit xyunits[];
  52. extern struct xyctlr xyctlrs[];
  53. struct mb_driver xycdriver = {
  54. xyprobe, xyslave, xyattach, xygo, xydone, xypoll,
  55. sizeof (struct xydevice), "xy", xydinfo, "xyc", xycinfo, MDR_BIODMA,
  56. };
  57. /*
  58.  * Settable error level.
  59.  */
  60. short xyerrlvl = EL_FIXED | EL_RETRY | EL_RESTR | EL_RESET | EL_FAIL;
  61. /*
  62.  * Flags value that turns off command chaining
  63.  */
  64. #define XY_NOCHAINING 0x1
  65. /*
  66.  * Macro to provide a quick test for wait avoidance.
  67.  */
  68. #define XYCSRVALID(xyio) { 
  69. if ((xyio)->xy_csr & (XY_BUSY|XY_DBLERR)) 
  70. (void) xycsrvalid(xyio); 
  71. }
  72. /*
  73.  * List of commands for the 450.  Used to print nice error messages.
  74.  */
  75. char *xycmdnames[] = {
  76. "nop",
  77. "write",
  78. "read",
  79. "write headers",
  80. "read headers",
  81. "seek",
  82. "drive reset",
  83. "format",
  84. "read all",
  85. "read status",
  86. "write all",
  87. "set drive size",
  88. "self test",
  89. "reserved",
  90. "buffer load",
  91. "buffer dump",
  92. };
  93. int xywstart, xywatch(); /* have started guardian */
  94. int xyticks = 1; /* timer for guardian */
  95. int xythrottle = XY_THROTTLE; /* transfer burst count */
  96. /*
  97.  * Determine existence of a controller.  Called at boot time only.
  98.  * NOTE: we delay 15-20 microseconds after every register write
  99.  * to the controller.  This is because we are paranoid about the 450
  100.  * extending the bus cycle correctly and instead wait till it should
  101.  * be ready for the next cycle.
  102.  */
  103. xyprobe(reg, ctlr)
  104. caddr_t reg;
  105. int ctlr;
  106. {
  107. register struct xyctlr *c = &xyctlrs[ctlr];
  108. register struct xydevice *xyio;
  109. u_char err;
  110. /*
  111.  * See if there's hardware present by trying to reset it
  112.  */
  113. xyio = c->c_io = (struct xydevice *)reg;
  114. if (peekc((char *)&xyio->xy_resupd))
  115. return (0);
  116. if (!xywait(xyio)) {
  117. printf("xyc%d: controller reset failedn", ctlr);
  118. return (0);
  119. }
  120. /*
  121.  * Make sure its not a 2180 controller by using unique regs
  122.  */
  123. xyio->xy_iopbrel[0] = 0x67;
  124. xyio->xy_iopbrel[1] = 0x89;
  125. DELAY(15);
  126. if (xyio->xy_iopbrel[0] != 0x67 || xyio->xy_iopbrel[1] != 0x89)
  127. return (0);
  128. /*
  129.  * Set the iopb relocation regs to 0.  This assumes that the
  130.  * entire IOPBMAP resides in the bottom 64K of DVMA space.
  131.  */
  132. xyio->xy_iopbrel[0] = 0;
  133. DELAY(15);
  134. xyio->xy_iopbrel[1] = 0;
  135. DELAY(15);
  136. if ((xyio->xy_iopbrel[0] != 0) || (xyio->xy_iopbrel[1] != 0))
  137. return (0);
  138. /*
  139.  * Allocate an iopb for controller use.
  140.  */
  141. c->c_cmd.iopb = (struct xyiopb *)rmalloc(iopbmap,
  142. (long)sizeof (struct xyiopb));
  143. if (c->c_cmd.iopb == NULL) {
  144. printf("xyc%d: no iopb spacen", ctlr);
  145. return (0);
  146. }
  147. initiopb(c->c_cmd.iopb);
  148. c->c_cmd.c = c;
  149. /*
  150.  * Use a nop command to get back the controller's type field.
  151.  * It must be a 450 or we bail out.
  152.  */
  153. err = xycmd(&c->c_cmd, XY_NOP, NOLPART, (caddr_t)0, 0, (daddr_t)0, 0,
  154.     XY_SYNCH, 0);
  155. if (err || (c->c_cmd.iopb->xy_ctype != XYC_450)) {
  156. printf("xyc%d: unsupported controller typen", ctlr);
  157. return (0);
  158. }
  159. /*
  160.  * Run the controller self test
  161.  */
  162. if (err = xycmd(&c->c_cmd, XY_TEST, NOLPART, (caddr_t)0, 0, (daddr_t)0,
  163.     0, XY_SYNCH, 0)) {
  164. printf("xyc%d: self test errorn", ctlr);
  165. return (0);
  166. }
  167. if (xyio->xy_csr & XY_ADDR24)
  168. c->c_flags |= XY_C_24BIT;
  169. c->c_flags |= XY_C_PRESENT;
  170. return (sizeof (struct xydevice));
  171. }
  172. /*
  173.  * See if a slave unit exists.  This routine is called only at boot time.
  174.  * It is a wrapper for findslave() to match parameter types.
  175.  */
  176. xyslave(md, reg)
  177. register struct mb_device *md;
  178. caddr_t reg;
  179. {
  180. register struct xyctlr *c;
  181. int i;
  182. /*
  183.  * Find the controller at the given io address
  184.  */
  185. for (i = 0; i < nxyc; i++)
  186. if (xyctlrs[i].c_io == (struct xydevice *)reg)
  187. break;
  188. if (i >= nxyc) {
  189. printf("xy%d: ", md->md_unit);
  190. panic("io address mismatch");
  191. }
  192. c = &xyctlrs[i];
  193. /*
  194.  * Use findslave() to look for the drive synchronously
  195.  */
  196. return (findslave(md, c, XY_SYNCH));
  197. }
  198. /*
  199.  * Actual search for a slave unit.  Used by xyslave() and xyopen().  This
  200.  * routine is always called at disk interrupt priority.
  201.  */
  202. static
  203. findslave(md, c, mode)
  204. register struct mb_device *md;
  205. register struct xyctlr *c;
  206. int mode;
  207. {
  208. register struct mb_ctlr *mc;
  209. int i, low, high;
  210. /*
  211.  * Set up the vectored interrupt to pass the ctlr pointer.
  212.  * Also check to make sure the address size jumper is correct.
  213.  * NOTE: we assume here that vectored interrupts imply
  214.  * a VMEbus and autovectors imply a Multibus.  This is
  215.  * currently guaranteed by config.  This needs to be done here so
  216.  * the drive reset can interrupt correctly when it completes in
  217.  * the asynchwait case.
  218.  */
  219. mc = xycinfo[c - xyctlrs];
  220. if (mc->mc_intr) {
  221. if (!(c->c_flags & XY_C_24BIT))
  222. printf("xyc%d: WARNING: 20 bit addressesn",
  223.     mc->mc_ctlr);
  224. *(mc->mc_intr->v_vptr) = (int)c;
  225. } else if (c->c_flags & XY_C_24BIT)
  226. printf("xyc%d: WARNING: 24 bit addressesn", mc->mc_ctlr);
  227. /*
  228.  * Set up loop to search for a wildcarded drive number
  229.  */
  230. if (md->md_slave == '?') {
  231. low = 0;
  232. high = XYUNPERC-1;
  233. } else
  234. low = high = md->md_slave;
  235. /*
  236.  * Look for a drive that's online but not already taken
  237.  */
  238. for (i = low; i <= high; i++) {
  239. if (i >= XYUNPERC)
  240. break;
  241. if (c->c_units[i] != NULL &&
  242.     (c->c_units[i]->un_flags & XY_UN_PRESENT))
  243. continue;
  244. /*
  245.  * If a drive reset succeeds, we assume that the drive
  246.  * is there.
  247.  */
  248. if (!xycmd(&c->c_cmd, XY_RESTORE, NOLPART, (caddr_t)0, i,
  249.     (daddr_t)0, 0, mode, XY_NOMSG)) {
  250. md->md_slave = i;
  251. return (1);
  252. }
  253. }
  254. return (0);
  255. }
  256. /*
  257.  * This routine is used to attach a drive to the system.  It is called only
  258.  * at boot time.  It is a wrapper for doattach() to get the parameter
  259.  * types matched.
  260.  */
  261. xyattach(md)
  262. register struct mb_device *md;
  263. {
  264. doattach(md, XY_SYNCH);
  265. }
  266. /*
  267.  * This routine does the actual work involved in attaching a drive to the
  268.  * system.  It is called from xyattach() and xyopen().  It is always called
  269.  * at disk interrupt priority.
  270.  */
  271. static
  272. doattach(md, mode)
  273. register struct mb_device *md;
  274. int mode;
  275. {
  276. register struct xyctlr *c = &xyctlrs[md->md_ctlr];
  277. register struct xyunit *un = &xyunits[md->md_unit];
  278. register struct dk_label *l;
  279. int s, i, found = 0;
  280. /*
  281.  * If this disk has never been seen before, we need to set
  282.  * up all the structures for the device.
  283.  */
  284. if (!(un->un_flags & XY_UN_ATTACHED)) {
  285. /*
  286.  * Allocate an iopb for the unit.  NOTE: because other
  287.  * devices may be doing similar things in the asynchronous
  288.  * case, we lock out all mainbus activity while we are
  289.  * looking at the resource map.
  290.  */
  291. s = splr(pritospl(SPLMB));
  292. un->un_cmd.iopb = (struct xyiopb *)rmalloc(iopbmap,
  293.     (long)sizeof (struct xyiopb));
  294. (void) splx(s);
  295. if (un->un_cmd.iopb == NULL) {
  296. printf("xy%d: no space for unit iopbn", md->md_unit);
  297. return;
  298. }
  299. un->un_flags |= XY_UN_ATTACHED;
  300. /*
  301.  * If no one has started the watchdog routine, do so.
  302.  */
  303. if (xywstart++ == 0)
  304. timeout(xywatch, (caddr_t)0, hz);
  305. /*
  306.  * Set up all the pointers and allocate space for the
  307.  * dynamic parts of the unit structure.  NOTE: if the
  308.  * alloc fails the system panics, so we don't need to
  309.  * test the return value.
  310.  */
  311. c->c_units[md->md_slave] = un;
  312. un->un_md = md;
  313. un->un_mc = md->md_mc;
  314. un->un_map = (struct dk_map *)new_kmem_alloc(
  315. sizeof (struct dk_map) * XYNLPART, KMEM_SLEEP);
  316. un->un_g = (struct dk_geom *)new_kmem_alloc(
  317. sizeof (struct dk_geom), KMEM_SLEEP);
  318. un->un_rtab = (struct buf *)new_kmem_alloc(
  319. sizeof (struct buf), KMEM_SLEEP);
  320. /*
  321.  * Zero the buffer. The other structures are initialized
  322.  * later by initlabel().
  323.  */
  324. bzero((caddr_t)un->un_rtab, sizeof (struct buf));
  325. un->un_bad = (struct dkbad *)new_kmem_alloc(
  326. sizeof (struct dkbad), KMEM_SLEEP);
  327. initiopb(un->un_cmd.iopb);
  328. un->un_cmd.c = c;
  329. if (md->md_flags & XY_NOCHAINING)
  330. c->c_flags |= XY_C_NOCHN;
  331. }
  332. /*
  333.  * Allocate a temporary buffer in DVMA space for reading the label.
  334.  * Again we must lock out all main bus activity to protect the
  335.  * resource map.
  336.  */
  337. s = splr(pritospl(SPLMB));
  338. l = (struct dk_label *)rmalloc(iopbmap, (long)SECSIZE);
  339. (void) splx(s);
  340. if (l == NULL) {
  341. printf("xy%d: no space for disk labeln", md->md_unit);
  342. return;
  343. }
  344. /*
  345.  * Unit is now officially present.  It can now be accessed by the system
  346.  * even if the rest of this routine fails.
  347.  */
  348. un->un_flags |= XY_UN_PRESENT;
  349. /*
  350.  * Initialize the label structures.  This is necessary so weird
  351.  * entries in the bad sector map don't bite us while reading the
  352.  * label.
  353.  */
  354. initlabel(un);
  355. /*
  356.  * Search for a label using each possible drive type, since we
  357.  * don't know which type the disk is yet.
  358.  */
  359. for (un->un_drtype = 0; un->un_drtype < NXYDRIVE; un->un_drtype++) {
  360. l->dkl_magic = 0; /* reset from last try */
  361. /*
  362.  * Attempt to read the label.  We use silent flag so
  363.  * no one will know if we fail.
  364.  */
  365. if (xycmd(&un->un_cmd, XY_READ, NOLPART,
  366.     (caddr_t)((char *)l - DVMA), md->md_slave, (daddr_t)0, 1,
  367.     mode, XY_NOMSG))
  368. continue;
  369. if (!islabel(md->md_unit, l))
  370. continue;
  371. uselabel(un, md->md_unit, l);
  372. if (usegeom(un, mode))
  373. continue;
  374. /*
  375.  * If we get here the label was digested correctly.  Mark
  376.  * label found and quit searching.
  377.  */
  378. found = 1;
  379. break;
  380. }
  381. /*
  382.  * If we found the label, attempt to read the bad sector map.
  383.  */
  384. if (found) {
  385. if (xycmd(&un->un_cmd, XY_READ, NOLPART,
  386.     (caddr_t)((char *)l - DVMA), md->md_slave,
  387.     (daddr_t)((((un->un_g->dkg_ncyl + un->un_g->dkg_acyl) *
  388.     un->un_g->dkg_nhead) - 1) * un->un_g->dkg_nsect), 1,
  389.     mode, 0)) {
  390. /*
  391.  * If we failed, print a message and invalidate
  392.  * the map in case it got destroyed in the read.
  393.  */
  394. printf("xy%d: unable to read bad sector infon",
  395.     un - xyunits);
  396. for (i = 0; i < 126; i++)
  397. un->un_bad->bt_bad[i].bt_cyl = 0xFFFF;
  398. /*
  399.  * Use a structure assignment to fill in the real map.
  400.  */
  401. } else
  402. *un->un_bad = *(struct dkbad *)l;
  403. /*
  404.  * If we couldn't read the label, print a message and invalidate
  405.  * the label structures in case they got destroyed in the reads.
  406.  */
  407. } else {
  408. printf("xy%d: unable to read labeln", un - xyunits);
  409. initlabel(un);
  410. }
  411. /*
  412.  * Free the buffer used for DVMA.
  413.  */
  414. s = splr(pritospl(SPLMB));
  415. rmfree(iopbmap, (long)SECSIZE, (u_long)l);
  416. (void) splx(s);
  417. return;
  418. }
  419. /*
  420.  * This routine sets the fields of the iopb that never change.  It is
  421.  * used by xyprobe() and doattach().  It is always called at disk
  422.  * interrupt priority.
  423.  */
  424. static
  425. initiopb(xy)
  426. register struct xyiopb *xy;
  427. {
  428. bzero((caddr_t)xy, sizeof (struct xyiopb));
  429. xy->xy_recal =1;
  430. xy->xy_enabext = 1;
  431. xy->xy_eccmode = 2;
  432. xy->xy_autoup = 1;
  433. xy->xy_reloc = 1;
  434. xy->xy_throttle = xythrottle;
  435. }
  436. /*
  437.  * This routine clears the fields of the iopb that must be zero before a
  438.  * command is executed.  It is used by xycmd() and xyrecover(). It is always
  439.  * called at disk interrupt priority.
  440.  */
  441. static
  442. cleariopb(xy)
  443. register struct xyiopb *xy;
  444. {
  445. xy->xy_errno = 0;
  446. xy->xy_iserr = 0;
  447. xy->xy_complete = 0;
  448. xy->xy_ctype = 0;
  449. }
  450. /*
  451.  * This routine initializes the unit label structures.  The logical partitions
  452.  * are set to zero so normal opens will fail.  The geometry is set to
  453.  * nonzero small numbers as a paranoid defense against zero divides.
  454.  * Bad sector map is filled with non-entries.
  455.  */
  456. static
  457. initlabel(un)
  458. register struct xyunit *un;
  459. {
  460. register int i;
  461. bzero((caddr_t)un->un_map, sizeof (struct dk_map) * XYNLPART);
  462. bzero((caddr_t)un->un_g, sizeof (struct dk_geom));
  463. un->un_g->dkg_ncyl = un->un_g->dkg_nhead = 2;
  464. un->un_g->dkg_nsect = 2;
  465. for (i = 0; i < 126; i++)
  466. un->un_bad->bt_bad[i].bt_cyl = 0xFFFF;
  467. }
  468. /*
  469.  * This routine verifies that the block read is indeed a disk label.  It
  470.  * is used by doattach().  It is always called at disk interrupt priority.
  471.  */
  472. static
  473. islabel(unit, l)
  474. int unit;
  475. register struct dk_label *l;
  476. {
  477. if (l->dkl_magic != DKL_MAGIC)
  478. return (0);
  479. if (!ck_cksum(l)) {
  480. printf("xy%d: corrupt labeln", unit);
  481. return (0);
  482. }
  483. return (1);
  484. }
  485. /*
  486.  * This routine checks the checksum of the disk label.  It is used by
  487.  * islabel().  It is always called at disk interrupt priority.
  488.  */
  489. static
  490. ck_cksum(l)
  491. register struct dk_label *l;
  492. {
  493. register short *sp, sum = 0;
  494. register short count = sizeof (struct dk_label)/sizeof (short);
  495. sp = (short *)l;
  496. while (count--)
  497. sum ^= *sp++;
  498. return (sum ? 0 : 1);
  499. }
  500. /*
  501.  * This routine puts the label information into the various parts of
  502.  * the unit structure.  It is used by doattach().  It is always called
  503.  * at disk interrupt priority.
  504.  */
  505. static
  506. uselabel(un, unit, l)
  507. register struct xyunit *un;
  508. int unit;
  509. register struct dk_label *l;
  510. {
  511. int i, intrlv;
  512. /*
  513.  * Print out the disk description.
  514.  */
  515. printf("xy%d: <%s>n", unit, l->dkl_asciilabel);
  516. /*
  517.  * Fill in the geometry information.
  518.  */
  519. un->un_g->dkg_ncyl = l->dkl_ncyl;
  520. un->un_g->dkg_acyl = l->dkl_acyl;
  521. un->un_g->dkg_bcyl = 0;
  522. un->un_g->dkg_nhead = l->dkl_nhead;
  523. un->un_g->dkg_nsect = l->dkl_nsect;
  524. un->un_g->dkg_intrlv = l->dkl_intrlv;
  525. un->un_g->dkg_rpm = l->dkl_rpm;
  526. un->un_g->dkg_pcyl = l->dkl_pcyl;
  527. /*
  528.  * Old labels don't have pcyl in them, so we make a guess at it.
  529.  */
  530. if (un->un_g->dkg_pcyl == 0)
  531. un->un_g->dkg_pcyl = un->un_g->dkg_ncyl + un->un_g->dkg_acyl;
  532. /*
  533.  * Fill in the logical partition map (structure assignments).
  534.  */
  535. for (i = 0; i < XYNLPART; i++)
  536. un->un_map[i] = l->dkl_map[i];
  537. /*
  538.  * Set up data for iostat.
  539.  */
  540. if (un->un_md->md_dk >= 0) {
  541. intrlv = un->un_g->dkg_intrlv;
  542. if (intrlv <= 0 || intrlv >= un->un_g->dkg_nsect)
  543. intrlv = 1;
  544. dk_bps[un->un_md->md_dk] = SECSIZE * 60 * un->un_g->dkg_nsect /
  545.     intrlv;
  546. }
  547. }
  548. /*
  549.  * This routine is used to initialize the drive type.  The 450 requires
  550.  * that each drive type be set up once by sending a set drive size
  551.  * command to the controller.  After that, any number of disks of that
  552.  * type can be used.  It is used by doattach() and xyioctl().  It is
  553.  * always called at disk interrupt priority.
  554.  */
  555. static
  556. usegeom(un, mode)
  557. register struct xyunit *un;
  558. int mode;
  559. {
  560. register struct xyctlr *c = &xyctlrs[un->un_mc->mc_ctlr];
  561. int unit;
  562. daddr_t lastb;
  563. register struct dk_geom *ng, *g = un->un_g;
  564. register struct xyunit *nun;
  565. /*
  566.  * Search for other disks of the same type on this
  567.  * controller.  If found, they must have the same
  568.  * geometry or we are stuck.
  569.  */
  570. for (unit = 0; unit < XYUNPERC; unit++) {
  571. if ((nun = c->c_units[unit]) == NULL || un == nun)
  572. continue;
  573. if (!(nun->un_flags & XY_UN_PRESENT))
  574. continue;
  575. if (nun->un_drtype != un->un_drtype)
  576. continue;
  577. ng = nun->un_g;
  578. if ((g->dkg_ncyl + g->dkg_acyl != ng->dkg_ncyl +
  579.     ng->dkg_acyl) || g->dkg_nhead != ng->dkg_nhead ||
  580.     g->dkg_nsect != ng->dkg_nsect) {
  581. printf("xy%d and xy%d are of same type (%d)",
  582.     un - xyunits, nun - xyunits, un->un_drtype);
  583. printf(" with different geometriesn");
  584. return (1);
  585. }
  586. return (0);
  587. }
  588. /*
  589.  * Just to be safe, we make sure we are initializing the drive
  590.  * to the larger of the two sizes, logical or physical.
  591.  */
  592. if (g->dkg_pcyl < g->dkg_ncyl + g->dkg_acyl)
  593. lastb = (g->dkg_ncyl + g->dkg_acyl) * g->dkg_nhead *
  594.     g->dkg_nsect - 1;
  595. else
  596. lastb = g->dkg_pcyl * g->dkg_nhead * g->dkg_nsect - 1;
  597. /*
  598.  * This type is not initialized so we must execute a set drive
  599.  * size command.  If it fails, we return the error so the label
  600.  * gets invalidated.
  601.  */
  602. if (xycmd(&un->un_cmd, XY_INIT, NOLPART, (caddr_t)0,
  603.     un->un_md->md_slave, lastb, 0, mode, 0)) {
  604. printf("xy%d: initialization failedn", un - xyunits);
  605. return (1);
  606. }
  607. return (0);
  608. }
  609. /*
  610.  * This routine sets the fields in the iopb that are needed for an
  611.  * asynchronous operation.  It does not start the operation, since the
  612.  * iopb may be chained to others.  It is used by xycmd() and xyintr().
  613.  * It is always called at disk interrupt priority.
  614.  */
  615. xyasynch(cmdblk)
  616. register struct xycmdblock *cmdblk;
  617. {
  618. register struct xyiopb *xy = cmdblk->iopb;
  619. xy->xy_ie = 1;
  620. xy->xy_intrall = 0;
  621. }
  622. /*
  623.  * This routine sets up and executes iopbs for a controller.  It always
  624.  * runs the controller's private commands first.  After that, it does
  625.  * a round-robin search of the units, looking for a ready iopb.  If chaining
  626.  * is enabled, it will also add to that any other ready iopbs that can
  627.  * be chained.  The chaining is done to both the iopbs themselves
  628.  * (so the controller sees it) and also to the link fields of the cmdblocks
  629.  * (so the interrupt routine sees it).  It is used by xycmd() and xyintr().
  630.  * It is always called at disk interrupt priority.
  631.  */
  632. xychain(c)
  633. register struct xyctlr *c;
  634. {
  635. register struct xyunit *un;
  636. register struct xyiopb *lptr = NULL;
  637. register struct xycmdblock *bptr = NULL;
  638. register int i, j;
  639. /*
  640.  * See if the controller's iopb is ready.  If so, execute it
  641.  * in isolation.  Since the only commands that use this are
  642.  * those searching for a disk, starvation of the unit iopbs
  643.  * is not an issue.
  644.  */
  645. if ((c->c_cmd.flags & XY_FBSY) &&
  646.     (c->c_cmd.flags & XY_FRDY) &&
  647.     (!(c->c_cmd.flags & XY_DONE))) {
  648. lptr = c->c_cmd.iopb;
  649. bptr = &c->c_cmd;
  650. lptr->xy_chain = 0;
  651. bptr->next = NULL;
  652. goto run;
  653. }
  654. /*
  655.  * Round-robin search of the unit iopbs for a ready one.  If
  656.  * we find one, and chaining is off for the controller or that
  657.  * command, we execute it in isolation.  Otherwise, search the
  658.  * rest of the unit iopbs for ones that are ready and chainable
  659.  * and add them in.
  660.  */
  661. for (i = 0; i < XYUNPERC; i++)
  662. if (((un = c->c_units[(c->c_nextunit + i) % XYUNPERC])
  663.     != NULL) &&
  664.     (un->un_cmd.flags & XY_FBSY) &&
  665.     (un->un_cmd.flags & XY_FRDY) &&
  666.     (!(un->un_cmd.flags & XY_DONE)))
  667. break;
  668. /*
  669.  * If we didn't find a ready one, just return.
  670.  */
  671. if (i >= XYUNPERC)
  672. return;
  673. /*
  674.  * Set the round-robin ptr to the unit after the ready one
  675.  * and set up the iopb to be run.
  676.  */
  677. c->c_nextunit = (c->c_nextunit + i + 1) % XYUNPERC;
  678. lptr = un->un_cmd.iopb;
  679. bptr = &un->un_cmd;
  680. lptr->xy_chain = 0;
  681. bptr->next = NULL;
  682. /*
  683.  * If chaining is off for any reason, just run this one.
  684.  */
  685. if ((c->c_flags & XY_C_NOCHN) || (bptr->flags & XY_NOCHN))
  686. goto run;
  687. /*
  688.  * Pick up any other ready iopbs and add them to the chain.
  689.  */
  690. for (j = 0; j < (XYUNPERC - i - 1); j++) {
  691. if (((un = c->c_units[(c->c_nextunit + j) % XYUNPERC])
  692.     != NULL) &&
  693.     (un->un_cmd.flags & XY_FBSY) &&
  694.     (un->un_cmd.flags & XY_FRDY) &&
  695.     (!(un->un_cmd.flags & XY_DONE)) &&
  696.     (!(un->un_cmd.flags & XY_NOCHN))) {
  697. un->un_cmd.iopb->xy_nxtoff = XYOFF(((char *)lptr)
  698.     - DVMA);
  699. lptr = un->un_cmd.iopb;
  700. lptr->xy_chain = 1;
  701. un->un_cmd.next = bptr;
  702. bptr = &un->un_cmd;
  703. }
  704. }
  705. run:
  706. if (lptr != NULL) {
  707. c->c_chain = bptr;
  708. c->c_wantint = xyticks;
  709. xyexec(lptr, c->c_io, c - xyctlrs);
  710. }
  711. }
  712. /*
  713.  * This routine executes a command synchronously.  This is only done at
  714.  * boot time or when a dump is being done.  It is used by xycmd().
  715.  * It is always called at disk interrupt priority.
  716.  */
  717. xysynch(cmdblk)
  718. register struct xycmdblock *cmdblk;
  719. {
  720. register struct xyiopb *xy = cmdblk->iopb;
  721. register struct xydevice *xyio = cmdblk->c->c_io;
  722. register char junk;
  723. /*
  724.  * Clean out any old state left in the controller.
  725.  */
  726. if (xyio->xy_csr & XY_BUSY) {
  727. junk = xyio->xy_resupd;
  728. if (!xywait(xyio)) {
  729. printf("xyc%d: ", cmdblk->c - xyctlrs);
  730. panic("controller reset failed");
  731. }
  732. }
  733. if (xyio->xy_csr & XY_INTR) {
  734. xyio->xy_csr = XY_INTR;
  735. (void) xycsrvalid(xyio);
  736. }
  737. if (xyio->xy_csr & (XY_ERROR | XY_DBLERR)) {
  738. xyio->xy_csr = XY_ERROR;
  739. (void) xycsrvalid(xyio);
  740. }
  741. #ifdef lint
  742. junk = junk;
  743. #endif
  744. /*
  745.  * Set necessary iopb fields then have the command executed.
  746.  */
  747. xy->xy_ie = 0;
  748. xy->xy_chain = 0;
  749. xyexec(xy, xyio, cmdblk->c - xyctlrs);
  750. /*
  751.  * Wait for the command to complete or until a timeout occurs.
  752.  */
  753. CDELAY(((xyio->xy_csr & XY_BUSY) == 0), 1000000 * XYLOSTINTTIMO);
  754. /*
  755.  * If we timed out, use the lost interrupt error to pass
  756.  * back status or just reset the controller if the command
  757.  * had already finished.
  758.  */
  759. if (xyio->xy_csr & XY_BUSY) {
  760. if (xy->xy_complete) {
  761. junk = xyio->xy_resupd;
  762. if (!xywait(xyio)) {
  763. printf("xyc%d: ", cmdblk->c - xyctlrs);
  764. panic("controller reset failed");
  765. }
  766. } else {
  767. xy->xy_iserr = 1;
  768. xy->xy_errno = XYE_LINT;
  769. }
  770. /*
  771.  * If one of the error bits is set in the controller status
  772.  * register, we need to convey this to the recovery routine
  773.  * via the iopb.  However, if the iopb has a specific error
  774.  * reported, we don't want to overwrite it.  Therefore, we
  775.  * only fold the error bits into the iopb if the iopb thinks
  776.  * things were ok.
  777.  */
  778. } else if (xyio->xy_csr & XY_DBLERR) {
  779. xyio->xy_csr = XY_ERROR; /* clears the error */
  780. (void) xycsrvalid(xyio);
  781. if (!(xy->xy_iserr && xy->xy_errno)) {
  782. xy->xy_iserr = 1;
  783. xy->xy_errno = XYE_DERR;
  784. }
  785. } else if (xyio->xy_csr & XY_ERROR) {
  786. DELAY(10);
  787. xyio->xy_csr = XY_ERROR; /* clears the error */
  788. (void) xycsrvalid(xyio);
  789. if (!(xy->xy_iserr && xy->xy_errno)) {
  790. xy->xy_iserr = 1;
  791. xy->xy_errno = XYE_ERR;
  792. }
  793. }
  794. }
  795. /*
  796.  * This routine is the focal point of all commands to the controller.
  797.  * Every command passes through here, independent of its source or
  798.  * reason.  The mode determines whether we are synchronous, asynchronous,
  799.  * or asynchronous but waiting for completion.  The flags are used
  800.  * to suppress error recovery and messages when we are doing special operations.
  801.  * It is used by xyprobe(), findslave(), doattach(), usegeom(),
  802.  * xygo(), xyioctl(), xywatch(), and xydump().
  803.  * It is always called at disk interrupt priority.
  804.  * NOTE: this routine assumes that all operations done before the disk's
  805.  * geometry is defined are done on block 0.  This impacts both this routine
  806.  * and the error recovery scheme (even the restores must use block 0).
  807.  * Failure to abide by this restriction could result in an arithmetic trap.
  808.  */
  809. xycmd(cmdblk, cmd, device, bufaddr, unit, blkno, secnt, mode, flags)
  810. register struct xycmdblock *cmdblk;
  811. u_short cmd;
  812. int device, unit, secnt, mode, flags;
  813. caddr_t bufaddr;
  814. daddr_t blkno;
  815. {
  816. register struct xyiopb *xy = cmdblk->iopb;
  817. register struct xyunit *un = cmdblk->c->c_units[unit];
  818. int stat = 0;
  819. /*
  820.  * If we are willing to wait and the cmdblock is busy, we
  821.  * sleep till it's free.  In the normal asynchronous case,
  822.  * the cmdblock was set busy up in xyustart().  In the synchronous
  823.  * case, the cmdblock can't be busy.
  824.  */
  825. if (mode == XY_ASYNCHWAIT) {
  826. while (cmdblk->flags & XY_FBSY) {
  827. cmdblk->flags |= XY_WANTED;
  828. (void) sleep((caddr_t)cmdblk, PRIBIO);
  829. }
  830. }
  831. /*
  832.  * Mark the cmdblock busy and fill in the fields.
  833.  */
  834. cmdblk->flags = XY_FBSY | XY_FRDY | flags;
  835. cmdblk->retries = cmdblk->restores = cmdblk->resets = 0;
  836. cmdblk->slave = unit;
  837. cmdblk->cmd = cmd;
  838. cmdblk->device = device;
  839. cmdblk->blkno = blkno;
  840. cmdblk->nsect = secnt;
  841. cmdblk->baddr = bufaddr;
  842. cmdblk->failed = 0;
  843. #ifdef DKIOCWCHK
  844. /*
  845.  * If this command is a write command, and we're supposed to be
  846.  * doing write checks, *AND* the transfer is to/from onboard
  847.  * memory (i.e., not across the VME bus), then set things up
  848.  * so that we do write checks later.
  849.  */
  850. if (cmd == XY_WRITE && device != NOLPART && mode == XY_ASYNCH && un &&
  851.     (un->un_wchkmap & (1<<LPART(device))) &&
  852.     MBI_MR(un->un_md->md_mbinfo) < dvmasize) {
  853. un->un_nverifies = 0;
  854. un->un_savaddr = bufaddr;
  855. un->un_savbn = blkno;
  856. un->un_savnsect = secnt;
  857. xywchk_start(un);
  858. cmdblk->flags |= XY_INWCHK;
  859. }
  860. #endif DKIOCWCHK
  861. /*
  862.  * Initialize the diagnostic info if necessary.
  863.  */
  864. if ((cmdblk->flags & XY_DIAG) && (un != NULL))
  865. un->un_errsevere = DK_NOERROR;
  866. /*
  867.  * Clear out the iopb fields that need it.
  868.  */
  869. cleariopb(xy);
  870. /*
  871.  * Set the iopb fields that are the same for all commands.
  872.  */
  873. xy->xy_cmd = cmd >> 8;
  874. xy->xy_subfunc = cmd;
  875. if (un != NULL)
  876. xy->xy_drive = un->un_drtype;
  877. else
  878. xy->xy_drive = 0;
  879. xy->xy_unit = unit;
  880. /*
  881.  * If the blockno is 0, we don't bother calculating the disk
  882.  * address.  NOTE: this is a necessary test, since some of the
  883.  * operations on block 0 are done while un is not yet defined.
  884.  * Removing the test would case bad pointer references.
  885.  */
  886. if (blkno != 0) {
  887. xy->xy_cylinder = blkno / (un->un_g->dkg_nhead *
  888.     un->un_g->dkg_nsect);
  889. xy->xy_head = (blkno / un->un_g->dkg_nsect) %
  890.     un->un_g->dkg_nhead;
  891. xy->xy_sector = blkno % un->un_g->dkg_nsect;
  892. } else
  893. xy->xy_cylinder = xy->xy_head = xy->xy_sector = 0;
  894. xy->xy_nsect = secnt;
  895. xy->xy_bufoff = XYOFF(bufaddr);
  896. xy->xy_bufrel = XYNEWREL(cmdblk->c->c_flags, bufaddr);
  897. /*
  898.  * If command is synchronous, execute it.  We continue to call
  899.  * error recovery (which will continue to execute commands) until
  900.  * it returns either success or complete failure.
  901.  */
  902. if (mode == XY_SYNCH) {
  903. xysynch(cmdblk);
  904. while ((stat = xyrecover(cmdblk, xysynch)) > 0)
  905. ;
  906. cmdblk->flags &= ~XY_FBSY;
  907. return (stat);
  908. }
  909. /*
  910.  * If command is asynchronous, set up it's execution.  We only
  911.  * start the execution if the controller isn't busy.
  912.  */
  913. xyasynch(cmdblk);
  914. if (!cmdblk->c->c_wantint)
  915. xychain(cmdblk->c);
  916. /*
  917.  * If we are waiting for the command to finish, sleep till it's
  918.  * done.  We must then wake up anyone waiting for the iopb.  If
  919.  * no one is waiting for the iopb, we simply start up the next
  920.  * unit operation.
  921.  */
  922. if (mode == XY_ASYNCHWAIT) {
  923. while (!(cmdblk->flags & XY_DONE)) {
  924. cmdblk->flags |= XY_WAIT;
  925. (void) sleep((caddr_t)cmdblk, PRIBIO);
  926. }
  927. stat = cmdblk->flags & XY_FAILED;
  928. cmdblk->flags &= ~XY_FBSY;
  929. if (cmdblk->flags & XY_WANTED) {
  930. cmdblk->flags &= ~XY_WANTED;
  931. wakeup((caddr_t)cmdblk);
  932. } else if (un != NULL && cmdblk == &un->un_cmd)
  933. xyustart(un);
  934. }
  935. /*
  936.  * Always zero for ASYNCH case, true result for ASYNCHWAIT case.
  937.  */
  938. if (stat)
  939. return (-1);
  940. else
  941. return (0);
  942. }
  943. /*
  944.  * This routine provides the error recovery for all commands to the 450.
  945.  * It examines the results of a just-executed command, and performs the
  946.  * appropriate action.  It will set up at most one followup command, so
  947.  * it needs to be called repeatedly until the error is resolved.  It
  948.  * returns three possible values to the calling routine : 0 implies that
  949.  * the command succeeded, 1 implies that recovery was initiated but not
  950.  * yet finished, and -1 implies that the command failed.  By passing the
  951.  * address of the execution function in as a parameter, the routine is
  952.  * completely isolated from the differences between synchronous and
  953.  * asynchronous commands.  It is used by xycmd() and xyintr().  It is
  954.  * always called at disk interrupt priority.
  955.  */
  956. xyrecover(cmdblk, execptr)
  957. register struct xycmdblock *cmdblk;
  958. register (*execptr)();
  959. {
  960. struct xyctlr *c = cmdblk->c;
  961. register struct xyiopb *xy = cmdblk->iopb;
  962. register struct xyunit *un = c->c_units[cmdblk->slave];
  963. struct xyerract *actptr;
  964. struct xyerror *errptr;
  965. int bn, ns, ndone;
  966. #ifdef DKIOCWCHK
  967. static char *rewrite = "rewrite after verify failure";
  968. #endif DKIOCWCHK
  969. /*
  970.  * This tests whether an error occured.  NOTE: errors reported by
  971.  * the status register of the controller must be folded into the
  972.  * iopb before this routine is called or they will not be noticed.
  973.  */
  974. if (xy->xy_iserr) {
  975. errptr = finderr(xy->xy_errno);
  976. /*
  977.  * If drive isn't even attached, we want to use error
  978.  * recovery but must be careful not to reference null
  979.  * pointers.
  980.  */
  981. if (un != NULL) {
  982. /*
  983.  * Drive has been taken offline.  Since the operation
  984.  * can't succeed, there's no use trying any more.
  985.  */
  986. if (!(un->un_flags & XY_UN_PRESENT)) {
  987. bn = cmdblk->blkno;
  988. ndone = 0;
  989. goto fail;
  990. }
  991. /*
  992.  * Extract from the iopb the sector in error and
  993.  * how many sectors succeeded.
  994.  */
  995. bn = ((xy->xy_cylinder * un->un_g->dkg_nhead) +
  996.     xy->xy_head) * un->un_g->dkg_nsect + xy->xy_sector;
  997. ndone = bn - cmdblk->blkno;
  998. /*
  999.  * Log the error for diagnostics if appropriate.
  1000.  */
  1001. if (cmdblk->flags & XY_DIAG) {
  1002. un->un_errsect = bn;
  1003. un->un_errno = errptr->errno;
  1004. un->un_errcmd =
  1005.     (xy->xy_cmd << 8) | xy->xy_subfunc;
  1006. }
  1007. } else
  1008. bn = ndone = 0;
  1009. if (errptr->errlevel != XY_ERCOR) {
  1010. /*
  1011.  * If the error wasn't corrected, see if it's a
  1012.  * bad block.  If we are already in the middle of
  1013.  * forwarding a bad block, we are not allowed to
  1014.  * encounter another one.  NOTE: the check of the
  1015.  * command is to avoid false mappings during initial
  1016.  * stuff like trying to reset a drive
  1017.  * (the bad map hasn't been initialized).
  1018.  */
  1019. if (((xy->xy_cmd == (XY_READ >> 8)) ||
  1020.     (xy->xy_cmd == (XY_WRITE >> 8))) &&
  1021.     (ns = isbad(un->un_bad, (int)xy->xy_cylinder,
  1022.     (int)xy->xy_head, (int)xy->xy_sector)) >= 0) {
  1023. if (cmdblk->flags & XY_INFRD) {
  1024. printf("xy%d: recursive mapping --",
  1025.     un->un_md->md_unit);
  1026. printf(" block #%dn", bn);
  1027. goto fail;
  1028. }
  1029. /*
  1030.  * We have a bad block.  Advance the state
  1031.  * info up to the block that failed.
  1032.  */
  1033. cmdblk->baddr += ndone * SECSIZE;
  1034. cmdblk->blkno += ndone;
  1035. cmdblk->nsect -= ndone;
  1036. /*
  1037.  * Calculate the location of the alternate
  1038.  * block.
  1039.  */
  1040. cmdblk->altblkno = bn = (((un->un_g->dkg_ncyl +
  1041.     un->un_g->dkg_acyl) *
  1042.     un->un_g->dkg_nhead) - 1) *
  1043.     un->un_g->dkg_nsect - ns - 1;
  1044. /*
  1045.  * Set state to 'forwarding' and print msg
  1046.  */
  1047. cmdblk->flags |= XY_INFRD;
  1048. if ((xyerrlvl & EL_FORWARD) &&
  1049.     (!(cmdblk->flags & XY_NOMSG))) {
  1050. printf("xy%d: forwarding %d/%d/%d",
  1051.     un->un_md->md_unit,
  1052.     xy->xy_cylinder, xy->xy_head,
  1053.     xy->xy_sector);
  1054. printf(" to alt blk #%dn", ns);
  1055. }
  1056. ns = 1;
  1057. /*
  1058.  * Execute the command on the alternate block
  1059.  */
  1060. goto exec;
  1061. }
  1062. /*
  1063.  * Error was 'real'.  Look up action to take.
  1064.  */
  1065. if (cmdblk->flags & XY_DIAG)
  1066. cmdblk->failed = 1;
  1067. actptr = &xyerracts[errptr->errlevel];
  1068. /*
  1069.  * Attempt to retry the entire operation if appropriate.
  1070.  */
  1071. if (cmdblk->retries++ < actptr->retry) {
  1072. if ((xyerrlvl & EL_RETRY) &&
  1073.     (!(cmdblk->flags & XY_NOMSG)) &&
  1074.     (errptr->errlevel != XY_ERBSY))
  1075. printerr(un, xy->xy_cmd, cmdblk->device,
  1076.     "retry", errptr->errmsg, bn);
  1077. if (cmdblk->flags & XY_INFRD) {
  1078. bn = cmdblk->altblkno;
  1079. ns = 1;
  1080. } else {
  1081. bn = cmdblk->blkno;
  1082. ns = cmdblk->nsect;
  1083. }
  1084. goto exec;
  1085. }
  1086. /*
  1087.  * Attempt to restore the drive if appropriate.  We
  1088.  * set the state to 'restoring' so we know where we
  1089.  * are.  NOTE: there is no check for a recursive
  1090.  * restore, since that is a non-destructive condition.
  1091.  */
  1092. if (cmdblk->restores++ < actptr->restore) {
  1093. if ((xyerrlvl & EL_RESTR) &&
  1094.     (!(cmdblk->flags & XY_NOMSG)))
  1095. printerr(un, xy->xy_cmd, cmdblk->device,
  1096.     "restore", errptr->errmsg, bn);
  1097. cmdblk->retries = 0;
  1098. bn = ns = 0;
  1099. xy->xy_cmd = XY_RESTORE >> 8;
  1100. xy->xy_subfunc = 0;
  1101. cmdblk->flags |= XY_INRST;
  1102. goto exec;
  1103. }
  1104. /*
  1105.  * Attempt to reset the controller if appropriate.
  1106.  * We must busy wait for the controller, since no
  1107.  * interrupt is generated.
  1108.  */
  1109. if (cmdblk->resets++ < actptr->reset) {
  1110. if ((xyerrlvl & EL_RESET) &&
  1111.     (!(cmdblk->flags & XY_NOMSG)))
  1112. printerr(un, xy->xy_cmd, cmdblk->device,
  1113.     "reset", errptr->errmsg, bn);
  1114. cmdblk->retries = cmdblk->restores = 0;
  1115. ns = c->c_io->xy_resupd;
  1116. if (!xywait(c->c_io)) {
  1117. printf("xyc%d: ", c - xyctlrs);
  1118. panic("controller reset failed");
  1119. }
  1120. if (cmdblk->flags & XY_INFRD) {
  1121. bn = cmdblk->altblkno;
  1122. ns = 1;
  1123. } else {
  1124. bn = cmdblk->blkno;
  1125. ns = cmdblk->nsect;
  1126. }
  1127. goto exec;
  1128. }
  1129. /*
  1130.  * Command has failed.  We either fell through to
  1131.  * here by running out of recovery or jumped here
  1132.  * for a good reason.
  1133.  */
  1134. fail:
  1135. #ifdef DKIOCWCHK
  1136. /*
  1137.  * If this was the read portion of a WRITE CHECK
  1138.  * operation, drop down into the code where we
  1139.  * try the write again. Otherwise, give up. That
  1140.  * is, if we get a HARD ECC error on the readback
  1141.  * drop down into the code that rewrites the
  1142.  * block if re-verifies haven't been exhausted
  1143.  * yet.
  1144.  */
  1145. if (cmdblk->flags & XY_INWCHK) {
  1146. if (xy->xy_cmd == XY_READ>>8) {
  1147. goto fail1;
  1148. } else {
  1149. cmdblk->flags &= ~XY_INWCHK;
  1150. }
  1151. }
  1152. #endif DKIOCWCHK
  1153. if ((xyerrlvl & EL_FAIL) &&
  1154.     (!(cmdblk->flags & XY_NOMSG)))
  1155. printerr(un, xy->xy_cmd, cmdblk->device,
  1156.     "failed", errptr->errmsg, bn);
  1157. /*
  1158.  * If the failure was caused by
  1159.  * a 'drive busy' type error, the drive has probably
  1160.  * been taken offline, so we mark it as gone.
  1161.  */
  1162. if ((errptr->errlevel == XY_ERBSY) &&
  1163.     (un != NULL) && (un->un_flags & XY_UN_PRESENT)) {
  1164. un->un_flags &= ~XY_UN_PRESENT;
  1165. if (un->un_md->md_dk >=0)
  1166. dk_bps[un->un_md->md_dk] = 0;
  1167. printf("xy%d: offlinen", un->un_md->md_unit);
  1168. }
  1169. /*
  1170.  * If the failure implies the drive is faulted, do
  1171.  * one final restore in hopes of clearing the fault.
  1172.  */
  1173. if ((errptr->errlevel == XY_ERFLT) &&
  1174.     (!(cmdblk->flags & XY_FNLRST))) {
  1175. bn = ns = 0;
  1176. xy->xy_cmd = XY_RESTORE >> 8;
  1177. xy->xy_subfunc = 0;
  1178. cmdblk->flags &= ~(XY_INFRD | XY_INRST);
  1179. cmdblk->flags |= XY_FNLRST;
  1180. cmdblk->failed = 1;
  1181. goto exec;
  1182. }
  1183. /*
  1184.  * If the failure implies the controller is hung, do
  1185.  * a controller reset in hopes of fixing its state.
  1186.  */
  1187. if (errptr->errlevel == XY_ERHNG) {
  1188. ns = c->c_io->xy_resupd;
  1189. if (!xywait(c->c_io)) {
  1190. printf("xyc%d: ", c - xyctlrs);
  1191. panic("controller reset failed");
  1192. }
  1193. }
  1194. /*
  1195.  * Note the failure for diagnostics and return it.
  1196.  */
  1197. if (cmdblk->flags & XY_DIAG)
  1198. un->un_errsevere = DK_FATAL;
  1199. return (-1);
  1200. }
  1201. /*
  1202.  * A corrected error.  Simply print a message and go on.
  1203.  */
  1204. if (cmdblk->flags & XY_DIAG) {
  1205. cmdblk->failed = 1;
  1206. un->un_errsevere = DK_CORRECTED;
  1207. }
  1208. if ((xyerrlvl & EL_FIXED) && (!(cmdblk->flags & XY_NOMSG)))
  1209. printerr(un, xy->xy_cmd, cmdblk->device,
  1210.     "fixed", errptr->errmsg, bn);
  1211. }
  1212. /*
  1213.  * Command succeeded.  Either there was no error or it was corrected.
  1214.  * We aren't done yet, since the command executed may have been part
  1215.  * of the recovery procedure.  We check for 'restoring' and
  1216.  * 'forwarding' states and restart the original operation if we
  1217.  * find one.
  1218.  */
  1219. if (cmdblk->flags & XY_INRST) {
  1220. xy->xy_cmd = cmdblk->cmd >> 8;
  1221. xy->xy_subfunc = cmdblk->cmd;
  1222. if (cmdblk->flags & XY_INFRD) {
  1223. bn = cmdblk->altblkno;
  1224. ns = 1;
  1225. } else {
  1226. bn = cmdblk->blkno;
  1227. ns = cmdblk->nsect;
  1228. }
  1229. cmdblk->flags &= ~XY_INRST;
  1230. goto exec;
  1231. }
  1232. if (cmdblk->flags & XY_INFRD) {
  1233. cmdblk->baddr += SECSIZE;
  1234. bn = ++cmdblk->blkno;
  1235. ns = --cmdblk->nsect;
  1236. cmdblk->flags &= ~XY_INFRD;
  1237. if (ns > 0)
  1238. goto exec;
  1239. }
  1240. /*
  1241.  * Last command succeeded. However, since the overall command
  1242.  * may have failed, we return the appropriate status.
  1243.  */
  1244. if (cmdblk->failed) {
  1245. /*
  1246.  * Figure out whether or not the work got done so
  1247.  * diagnostics knows what happened.
  1248.  */
  1249. if ((cmdblk->flags & XY_DIAG) &&
  1250.     (un->un_errsevere == DK_NOERROR)) {
  1251. if (cmdblk->flags & XY_FNLRST)
  1252. un->un_errsevere = DK_FATAL;
  1253. else
  1254. un->un_errsevere = DK_RECOVERED;
  1255. }
  1256. #ifdef DKIOCWCHK
  1257. cmdblk->flags &= ~XY_INWCHK;
  1258. #endif DKIOCWCHK
  1259. return (-1);
  1260. #ifdef DKIOCWCHK
  1261. /*
  1262.  * Here seems a good place to stash write-check operations
  1263.  */
  1264. } else if (cmdblk->flags & XY_INWCHK) {
  1265. /*
  1266.  * We have to restore bn, ns, cmdblk->baddr,
  1267.  * cmdblk->blkno && cmdblk->nsect
  1268.  * because the cmdblk fields may have been fiddled with
  1269.  * by bad144 forwarding....
  1270.  */
  1271. cmdblk->baddr = un->un_savaddr;
  1272. bn = cmdblk->blkno = un->un_savbn;
  1273. ns = cmdblk->nsect = un->un_savnsect;
  1274. cmdblk->retries = cmdblk->restores = cmdblk->resets = 0;
  1275. /*
  1276.  * If this portion of the command was a WRITE command,
  1277.  * then turn it into a READ command. We read back into
  1278.  * where we wrote from (because it is mapped). If that
  1279.  * fails to check correctly, we restore that data
  1280.  * from the un->un_savbuf area which contains a copy
  1281.  * of the orignal data.
  1282.  */
  1283. if (cmdblk->cmd == XY_WRITE) {
  1284. cmdblk->cmd = XY_READ;
  1285. xy->xy_cmd = cmdblk->cmd >> 8;
  1286. xy->xy_subfunc = cmdblk->cmd;
  1287. goto exec;
  1288. }
  1289. cmdblk->cmd = XY_WRITE; /* restore write command */
  1290. xy->xy_cmd = cmdblk->cmd >> 8;
  1291. xy->xy_subfunc = cmdblk->cmd;
  1292. if (xywchk_done(un)) {
  1293. fail1:
  1294. /*
  1295.  * If we haven't exhausted our retries,
  1296.  * attempt to rewrite the failing block
  1297.  */
  1298. if (un->un_nverifies++ < XY_REWRITE_MAX) {
  1299. bcopy(un->un_savbuf,
  1300.     (int) un->un_savaddr + DVMA,
  1301.     un->un_savnsect*SECSIZE);
  1302. cmdblk->failed = 0;
  1303. goto exec;
  1304. }
  1305. printerr(un, (u_char) (XY_WRITE>>8),
  1306.     cmdblk->device, "failed", rewrite, bn);
  1307. if (cmdblk->flags & XY_DIAG)
  1308. un->un_errsevere = DK_FATAL;
  1309. cmdblk->flags &= ~XY_INWCHK;
  1310. return (-1);
  1311. }
  1312. /*
  1313.  * Verify done. If we had to rewrite the block, log
  1314.  * it as a fixed error.
  1315.  */
  1316. if (un->un_nverifies) {
  1317. printerr(un, (u_char) (XY_WRITE>>8),
  1318.     cmdblk->device, "fixed", rewrite, bn);
  1319. }
  1320. cmdblk->flags &= ~XY_INWCHK;
  1321. return (0);
  1322. #endif DKIOCWCHK
  1323. } else
  1324. return (0);
  1325. /*
  1326.  * Executes the command set up above.
  1327.  * Only calculate the disk address if block isn't zero.  This is
  1328.  * necessary since some of the operations of block 0 occur before
  1329.  * the disk geometry is known (could result in zero divides).
  1330.  */
  1331. exec:
  1332. if (bn > 0) {
  1333. xy->xy_cylinder = bn / (un->un_g->dkg_nhead *
  1334.     un->un_g->dkg_nsect);
  1335. xy->xy_head = (bn / un->un_g->dkg_nsect) % un->un_g->dkg_nhead;
  1336. xy->xy_sector = bn % un->un_g->dkg_nsect;
  1337. } else
  1338. xy->xy_cylinder = xy->xy_head = xy->xy_sector = 0;
  1339. xy->xy_nsect = ns;
  1340. xy->xy_unit = cmdblk->slave;
  1341. xy->xy_bufoff = XYOFF(cmdblk->baddr);
  1342. xy->xy_bufrel = XYNEWREL(c->c_flags, cmdblk->baddr);
  1343. /*
  1344.  * Clear out the iopb fields that need it.
  1345.  */
  1346. cleariopb(xy);
  1347. /*
  1348.  * Execute the command and return a 'to be continued' status.
  1349.  */
  1350. (*execptr)(cmdblk);
  1351. return (1);
  1352. }
  1353. /*
  1354.  * This routine searches the error structure for the specified error and
  1355.  * returns a pointer to the structure entry.  If the error is not found,
  1356.  * the last entry in the error table is returned (this MUST be left as
  1357.  * unknown error).  It is used by xyrecover().  It is always called at
  1358.  * disk interrupt priority.
  1359.  */
  1360. static struct xyerror *
  1361. finderr(errno)
  1362. register u_char errno;
  1363. {
  1364. register struct xyerror *errptr;
  1365. for (errptr = xyerrors; errptr->errno != XYE_UNKN; errptr++)
  1366. if (errptr->errno == errno)
  1367. break;
  1368. return (errptr);
  1369. }
  1370. /*
  1371.  * This routine prints out an error message containing as much data
  1372.  * as is known.
  1373.  */
  1374. static
  1375. printerr(un, cmd, device, action, msg, bn)
  1376. struct xyunit *un;
  1377. u_char cmd;
  1378. short device;
  1379. char *action, *msg;
  1380. int bn;
  1381. {
  1382. if (device != NOLPART)
  1383. printf("xy%d%c: ", UNIT(device), LPART(device) + 'a');
  1384. else if (un != NULL)
  1385. printf("xy%d: ", un->un_md->md_unit);
  1386. else
  1387. printf("xy: ");
  1388. printf("%s %s (%s) -- ", xycmdnames[cmd], action, msg);
  1389. if ((device != NOLPART) && (un != NULL))
  1390. printf("blk #%d, ", bn - un->un_map[LPART(device)].dkl_cylno *
  1391.     un->un_g->dkg_nsect * un->un_g->dkg_nhead);
  1392. printf("abs blk #%dn", bn);
  1393. }
  1394. /*
  1395.  * This routine is the actual interface to the controller registers.  It
  1396.  * starts the controller up on the iopb passed.  It is used by xychain()
  1397.  * and xysynch().  It is always called at disk interrupt priority.
  1398.  */
  1399. xyexec(xy, xyio, ctlr)
  1400. register struct xyiopb *xy;
  1401. register struct xydevice *xyio;
  1402. int ctlr;
  1403. {
  1404. register int iopbaddr;
  1405. /*
  1406.  * Calculate the address of the iopb in 450 terms.
  1407.  */
  1408. iopbaddr = XYOFF(((char *)xy) - DVMA);
  1409. /*
  1410.  * NOTE : We do not initialize the iopb relocation regs
  1411.  * for every command.  They were set to zero during
  1412.  * initialization.  This approach assumes that all iopb's
  1413.  * are in the first 64K of DVMA space.
  1414.  */
  1415. /*
  1416.  * NOTE: the delay/readback approach to the controller registers
  1417.  * is due to a bug in the 450.  Occasionally the registers will
  1418.  * not respond to a write, so we check every time.
  1419.  */
  1420. /*
  1421.  * Check for an already busy controller.  In the asynchronous
  1422.  * case, this implies that something is corrupted.  In the
  1423.  * synchronous case, we just cleared the controller state so this
  1424.  * should never happen.
  1425.  */
  1426. if (xyio->xy_csr & (XY_BUSY | XY_INTR)) {
  1427. printf("xyc%d: ", ctlr);
  1428. printf("regs accessed while busy, csr = 0x%xn", xyio->xy_csr);
  1429. /* call new wait routine */
  1430. (void)xyintwait(xyio);
  1431. if (xyio->xy_csr & (XY_BUSY | XY_INTR)) {
  1432. printf("xyc%d: ", ctlr);
  1433. panic("regs accessed while busy");
  1434. }
  1435. }
  1436. /*
  1437.  * Set the iopb address registers, checking for glitches.
  1438.  */
  1439. xyio->xy_iopboff[0] = iopbaddr >> 8;
  1440. DELAY(15);
  1441. if (xyio->xy_iopboff[0] != (iopbaddr >> 8)) {
  1442. xyio->xy_iopboff[0] = iopbaddr >> 8;
  1443. DELAY(15);
  1444. if (xyio->xy_iopboff[0] != (iopbaddr >> 8)) {
  1445. printf("xyc%d: ", ctlr);
  1446. panic("iopboff[0] double miscompare");
  1447. }
  1448. }
  1449. xyio->xy_iopboff[1] = iopbaddr & 0xff;
  1450. DELAY(15);
  1451. if (xyio->xy_iopboff[1] != (iopbaddr & 0xff)) {
  1452. xyio->xy_iopboff[1] = iopbaddr & 0xff;
  1453. DELAY(15);
  1454. if (xyio->xy_iopboff[1] != (iopbaddr & 0xff)) {
  1455. printf("xyc%d: ", ctlr);
  1456. panic("iopboff[1] double miscompare");
  1457. }
  1458. }
  1459. /*
  1460.  * Set the go bit, checking for glitches.  Note that we must
  1461.  * check for the case where the command finishes during the delay,
  1462.  * so if the command is done the go bit is allowed to not be set.
  1463.  */
  1464. xyio->xy_csr = XY_GO;
  1465. DELAY(15);
  1466. if (!(xyio->xy_csr & (XY_GO | XY_INTR | XY_DBLERR))) {
  1467. if (xy->xy_complete)
  1468. return;
  1469. xyio->xy_csr = XY_GO;
  1470. DELAY(15);
  1471. if (!(xyio->xy_csr & (XY_GO | XY_INTR | XY_DBLERR))) {
  1472. if (xy->xy_complete)
  1473. return;
  1474. printf("xyc%d: ", ctlr);
  1475. panic("csr double miscompare");
  1476. }
  1477. }
  1478. }
  1479. /*
  1480.  * This routine opens the device.  It is designed so that a disk can
  1481.  * be spun up after the system is running and an open will automatically
  1482.  * attach it as if it had been there all along.  It is called from the
  1483.  * device switch at normal priority.
  1484.  */
  1485. /*
  1486.  * NOTE: there is a synchronization issue that is not resolved here. If
  1487.  * a disk is spun up and two processes attempt to open it at the same time,
  1488.  * they may both attempt to attach the disk. This is extremely unlikely, and
  1489.  * non-fatal in most cases, but should be fixed.
  1490.  */
  1491. xyopen(dev, flag)
  1492. dev_t dev;
  1493. int flag;
  1494. {
  1495. register struct xyunit *un;
  1496. register struct mb_device *md;
  1497. struct xyctlr *c;
  1498. int i, high, low, unit, s;
  1499. unit = UNIT(dev);
  1500. /*
  1501.  * Ensure that the device is configured.
  1502.  */
  1503. if (unit >= nxy)
  1504. return (ENXIO);
  1505. /*
  1506.  * If the disk is not present, we need to look for it.
  1507.  */
  1508. un = &xyunits[unit];
  1509. if (!(un->un_flags & XY_UN_PRESENT)) {
  1510. /*
  1511.  * This is minor overkill, since all we really need to do
  1512.  * is lock out disk interrupts while we are doing disk
  1513.  * commands.  However, there is no easy way to tell what
  1514.  * the disk priority is at this point.  Since this situation
  1515.  * only occurs once at disk spin-up, the extra lock-out
  1516.  * shouldn't hurt very much.
  1517.  */
  1518. s = splr(pritospl(SPLMB));
  1519. /*
  1520.  * Search through the table of devices for a match.
  1521.  */
  1522. for (md = mbdinit; md->md_driver; md++) {
  1523. if (md->md_driver != &xycdriver || md->md_unit != unit)
  1524. continue;
  1525. /*
  1526.  * Found a match.  If the controller is wild-carded,
  1527.  * we will look at each controller in order until
  1528.  * we find a disk.
  1529.  */
  1530. if (md->md_ctlr == '?') {
  1531. low = 0;
  1532. high = nxyc - 1;
  1533. } else
  1534. low = high = md->md_ctlr;
  1535. /*
  1536.  * Do the actual search for an available disk.
  1537.  */
  1538. for (i = low; i <= high; i++) {
  1539. c = &xyctlrs[i];
  1540. if (!(c->c_flags & XY_C_PRESENT))
  1541. continue;
  1542. if (!findslave(md, c, XY_ASYNCHWAIT))
  1543. continue;
  1544. /*
  1545.  * We found an online disk.  If it has
  1546.  * never been attached before, we simulate
  1547.  * the autoconf code and set up the necessary
  1548.  * data.
  1549.  */
  1550. if (!md->md_alive) {
  1551. md->md_alive = 1;
  1552. md->md_ctlr = i;
  1553. md->md_mc = xycinfo[i];
  1554. md->md_hd = md->md_mc->mc_mh;
  1555. md->md_addr = md->md_mc->mc_addr;
  1556. xydinfo[unit] = md;
  1557. if (md->md_dk && dkn < DK_NDRIVE)
  1558. md->md_dk = dkn++;
  1559. else
  1560. md->md_dk = -1;
  1561. }
  1562. /*
  1563.  * Print the found message and attach the
  1564.  * disk to the system.
  1565.  */
  1566. printf("xy%d at xyc%d slave %dn",
  1567.     md->md_unit, md->md_ctlr, md->md_slave);
  1568. doattach(md, XY_ASYNCHWAIT);
  1569. break;
  1570. }
  1571. break;
  1572. }
  1573. (void) splx(s);
  1574. }
  1575. /*
  1576.  * By the time we get here the disk is marked present if it exists
  1577.  * at all.  We simply check to be sure the partition being opened
  1578.  * is nonzero in size.  If a raw partition is opened with the
  1579.  * nodelay flag, we let it succeed even if the size is zero.  This
  1580.  * allows ioctls to later set the geometry and partitions.
  1581.  */
  1582. if (un->un_flags & XY_UN_PRESENT) {
  1583. if (un->un_map[LPART(dev)].dkl_nblk > 0)
  1584. return (0);
  1585. if ((cdevsw[major(dev)].d_open == xyopen) &&
  1586.     (flag & (FNDELAY | FNBIO | FNONBIO)))
  1587. return (0);
  1588. }
  1589. return (ENXIO);
  1590. }
  1591. /*
  1592.  * This routine returns the size of a logical partition.  It is called
  1593.  * from the device switch at normal priority.
  1594.  */
  1595. int
  1596. xysize(dev)
  1597. dev_t dev;
  1598. {
  1599. struct xyunit *un;
  1600. struct dk_map *lp;
  1601. /*
  1602.  * Ensure that the device is configured.
  1603.  */
  1604. if (UNIT(dev) >= nxy)
  1605. return (-1);
  1606. un = &xyunits[UNIT(dev)];
  1607. lp = &un->un_map[LPART(dev)];
  1608. if (!(un->un_flags & XY_UN_PRESENT))
  1609. return (-1);
  1610. return ((int)lp->dkl_nblk);
  1611. }
  1612. /*
  1613.  * This routine is the high level interface to the disk.  It performs
  1614.  * reads and writes on the disk using the buf as the method of communication.
  1615.  * It is called from the device switch for block operations and via physio()
  1616.  * for raw operations.  It is called at normal priority.
  1617.  */
  1618. xystrategy(bp)
  1619. register struct buf *bp;
  1620. {
  1621. register struct xyunit *un;
  1622. register struct dk_map *lp;
  1623. register struct diskhd *dp;
  1624. register int unit, s;
  1625. daddr_t bn;
  1626. unit = dkunit(bp);
  1627. if (unit >= nxy)
  1628. goto bad;
  1629. un = &xyunits[unit];
  1630. lp = &un->un_map[LPART(bp->b_dev)];
  1631. bn = dkblock(bp);
  1632. /*
  1633.  * Basic error checking.  If the disk isn't there or the operation
  1634.  * is past the end of the partition, it's an error.
  1635.  */
  1636. if (!(un->un_flags & XY_UN_PRESENT))
  1637. goto bad;
  1638. if (bn > lp->dkl_nblk || lp->dkl_nblk == 0)
  1639. goto bad;
  1640. /*
  1641.  * If the operation is at the end of the partition, we save time
  1642.  * by skipping out now.
  1643.  */
  1644. if (bn == lp->dkl_nblk) {
  1645. bp->b_resid = bp->b_bcount;
  1646. iodone(bp);
  1647. return;
  1648. }
  1649. /*
  1650.  * Calculate which cylinder the operation starts on.
  1651.  */
  1652. bp->b_cylin = bn / (un->un_g->dkg_nsect * un->un_g->dkg_nhead) +
  1653.     lp->dkl_cylno + un->un_g->dkg_bcyl;
  1654. /*
  1655.  * If the operation is off the end of the disk, it's an error.
  1656.  */
  1657. if (bp->b_cylin >= un->un_g->dkg_ncyl)
  1658. goto bad;
  1659. dp = &un->un_md->md_utab;
  1660. /*
  1661.  * Ready to queue the request - allocate DVMA resources
  1662.  * now if possible to avoid the overhead of doing it in
  1663.  * the interrupt routine.
  1664.  *
  1665.  * XXX - We let mbpresetup sleep if there's no resources
  1666.  * right now.  Better might be to keep a queue of requests
  1667.  * that don't yet have mb resources and as resources become
  1668.  * available assign them to the request at the head of the
  1669.  * queue.  It's important that the driver queue only contain
  1670.  * requests with resources allocated, otherwise it might
  1671.  * deadlock trying to process a request when no resources are
  1672.  * available because they are all held by requests further
  1673.  * back in the queue.
  1674.  */
  1675. mbpresetup(un->un_md->md_hd, bp, 0);
  1676. /*
  1677.  * We're playing with queues, so we lock out interrupts.  Sort the
  1678.  * operation into the queue for that disk and start up an operation
  1679.  * if the disk isn't busy.
  1680.  */
  1681. s = splr(pritospl(un->un_mc->mc_intpri));
  1682. disksort(dp, bp);
  1683. if (!(un->un_cmd.flags & XY_FBSY))
  1684. xyustart(un);
  1685. (void) splx(s);
  1686. return;
  1687. /*
  1688.  * The operation was erroneous for some reason.  Mark the buffer
  1689.  * with the error and call it done.
  1690.  */
  1691. bad:
  1692. bp->b_flags |= B_ERROR;
  1693. iodone(bp);
  1694. return;
  1695. }
  1696. /*
  1697.  * This routine starts an operation for a specific unit.  It is used only
  1698.  * in the normal asynchronous case, and is only called if the unit's iopb
  1699.  * is not busy.  It is ok to call this routine even if there are no
  1700.  * outstanding operations, so it is called whenever the unit becomes free.
  1701.  * It is used by xycmd(), xyintr() and xystrategy().  It is always called
  1702.  * at disk interrupt priority.
  1703.  */
  1704. xyustart(un)
  1705. register struct xyunit *un;
  1706. {
  1707. register struct diskhd *dp;
  1708. register struct buf *bp;
  1709. register short dk;
  1710. /*
  1711.  * Mark the unit as idle and return if there are no waiting operations.
  1712.  */
  1713. dk = un->un_md->md_dk;
  1714. dk_busy &= ~(1 << dk);
  1715. dp = &un->un_md->md_utab;
  1716. if ((bp = dp->b_actf) == NULL)
  1717. return;
  1718. /*
  1719.  * Mark the unit as busy.
  1720.  */
  1721. if (dk >= 0) {
  1722. dk_busy |= 1 << dk;
  1723. dk_seek[dk]++;
  1724. }
  1725. /*
  1726.  * Put the operation in the currently active slot.
  1727.  */
  1728. dp->b_forw = bp;
  1729. /*
  1730.  * Mark the iopb busy so no one takes it while we are waiting for
  1731.  * mainbus space.  Call the unit-oriented mb routine to give us
  1732.  * space.
  1733.  */
  1734. un->un_cmd.flags = XY_FBSY;
  1735. (void) mbugo(un->un_md);
  1736. }
  1737. /*
  1738.  * This routine translates a buf oriented command down to a level where it
  1739.  * can actually be executed.  It is called via mbugo() after the necessary
  1740.  * mainbus space has been allocated.  It is always called at disk interrupt
  1741.  * priority.
  1742.  */
  1743. xygo(md)
  1744. register struct mb_device *md;
  1745. {
  1746. register struct xyunit *un = &xyunits[md->md_unit];
  1747. register struct dk_map *lp;
  1748. register struct buf *bp;
  1749. int bufaddr, secnt, dk;
  1750. u_short cmd;
  1751. daddr_t blkno;
  1752. /*
  1753.  * Check to be sure there's a real command waiting.
  1754.  */
  1755. bp = md->md_utab.b_forw;
  1756. if (bp == NULL) {
  1757. printf("xy%d: ", md->md_unit);
  1758. panic("queueing error 1");
  1759. }
  1760. if (dkunit(bp) != md->md_unit) {
  1761. printf("xy%d: ", md->md_unit);
  1762. panic("queueing error 2");
  1763. }
  1764. /*
  1765.  * Extract the address of the mainbus space for the operation.
  1766.  */
  1767. bufaddr = MBI_ADDR(md->md_mbinfo);
  1768. /*
  1769.  * Calculate how many sectors we really want to operate on and
  1770.  * set resid to reflect it.
  1771.  */
  1772. lp = &un->un_map[LPART(bp->b_dev)];
  1773. secnt = howmany(bp->b_bcount, SECSIZE);
  1774. secnt = MIN(secnt, lp->dkl_nblk - dkblock(bp));
  1775. un->un_residual = bp->b_bcount - secnt * SECSIZE;
  1776. /*
  1777.  * Calculate all the parameters needed to execute the command.
  1778.  */
  1779. if (bp->b_flags & B_READ)
  1780. cmd = XY_READ;
  1781. else
  1782. cmd = XY_WRITE;
  1783. blkno = dkblock(bp);
  1784. blkno += lp->dkl_cylno * un->un_g->dkg_nhead * un->un_g->dkg_nsect;
  1785. /*
  1786.  * Make sure we didn't run over the address space limit.
  1787.  */
  1788. if ((bufaddr + secnt * SECSIZE) > 0x100000 &&
  1789.     (!(un->un_cmd.c->c_flags & XY_C_24BIT))) {
  1790. printf("xy%d: ", md->md_unit);
  1791. panic("exceeded 20 bit address");
  1792. }
  1793. if ((bufaddr + secnt * SECSIZE) > 0x1000000) {
  1794. printf("xy%d: ", md->md_unit);
  1795. panic("exceeded 24 bit address");
  1796. }
  1797. /*
  1798.  * Update stuff for iostat.
  1799.  */
  1800. if ((dk = md->md_dk) >= 0) {
  1801. dk_busy |= 1 << dk;
  1802. dk_xfer[dk]++;
  1803. if (bp->b_flags & B_READ)
  1804. dk_read[dk]++;
  1805. dk_wds[dk] += bp->b_bcount >> 6;
  1806. }
  1807. /*
  1808.  * Execute the command.
  1809.  */
  1810. (void) xycmd(&un->un_cmd, cmd, minor(bp->b_dev), (caddr_t)bufaddr,
  1811.     md->md_slave, blkno, secnt, XY_ASYNCH, 0);
  1812. }
  1813. /*
  1814.  * This routine polls all the controllers to see if one is interrupting.
  1815.  * It is called whenever a non-vectored interrupt of the correct priority
  1816.  * is received.  It is always called at disk interrupt priority.
  1817.  */
  1818. xypoll()
  1819. {
  1820. register struct xyctlr *c;
  1821. register int serviced = 0;
  1822. for (c = xyctlrs; c < &xyctlrs[nxyc]; c++) {
  1823. if (!(c->c_flags & XY_C_PRESENT) || !xycsrvalid(c->c_io) ||
  1824.     (c->c_io->xy_csr & XY_INTR) == 0)
  1825. continue;
  1826. serviced = 1;
  1827. xyintr(c);
  1828. }
  1829. return (serviced);
  1830. }
  1831. /*
  1832.  * This routine handles controller interrupts.  It is called by xypoll(),
  1833.  * xywatch() or whenever a vectored interrupt for a 450 is received.
  1834.  * It is always called at disk interrupt priority.
  1835.  */
  1836. xyintr(c)
  1837. register struct xyctlr *c;
  1838. {
  1839. register struct xycmdblock *cmdblk, *nextcmd;
  1840. register struct xyunit *un;
  1841. register struct xydevice *xyio;
  1842. int stat;
  1843. u_char errno = 0;
  1844. xyio = c->c_io;
  1845. /* wait for controller to settle down  */
  1846. XYCSRVALID(xyio);
  1847.         /*
  1848.  * validate interrupt by checking csr for a pending interrupt.
  1849.  * if NOT valid then just return.
  1850.          */
  1851.         if ((xyio->xy_csr & XY_INTR) == 0) {
  1852.                 return;
  1853.         }
  1854. /*
  1855.  * Clear the interrupt.  If we weren't expecting it, just return.
  1856.  */
  1857. xyio->xy_csr = XY_INTR;
  1858. DELAY(15);
  1859. /*
  1860.  * Use new wait routine called xyintwait which waits for INTR and
  1861.  * BUSY to be deasserted defore proceeding.
  1862.  */
  1863. (void)xyintwait(xyio);
  1864.         /*
  1865.          * make sure the busy bit goes ON before we wait until it clears..
  1866.          * This is a problem with faster machines where the controller does
  1867.          * not have enough time to react to the command.
  1868.          * Changed by EK 9/10/89
  1869.         while (!(xyio->xy_csr & (XY_BUSY|XY_DBLERR|XY_ERROR)));
  1870.         DELAY(10);
  1871. /*  (void) xycsrvalid(xyio); */
  1872.         if (!c->c_wantint) {
  1873.                 DELAY(30);
  1874.                 return;
  1875.         }
  1876. /*
  1877.  * If the controller claims an error occured, we need to assign
  1878.  * it to an iopb so the error recovery will see it.
  1879.  */
  1880. if (xyio->xy_csr & XY_DBLERR)
  1881. errno = XYE_DERR;
  1882. else if (xyio->xy_csr & XY_ERROR)
  1883. errno = XYE_ERR;
  1884. if (errno != 0) {
  1885. /*
  1886.  * Clear the error.  If we find an iopb with the error flag
  1887.  * set, that is all we need.
  1888.  */
  1889. xyio->xy_csr = XY_ERROR;
  1890. for (cmdblk = c->c_chain; cmdblk != NULL; cmdblk = cmdblk->next)
  1891. if (cmdblk->iopb->xy_iserr)
  1892. break;
  1893. /*
  1894.  * If no one claimed the error, we blow away all the
  1895.  * operations since we don't know which one failed.
  1896.  */
  1897. if (cmdblk == NULL) {
  1898. for (cmdblk = c->c_chain; cmdblk != NULL;
  1899.     cmdblk = cmdblk->next) {
  1900. cmdblk->iopb->xy_iserr = 1;
  1901. cmdblk->iopb->xy_errno = errno;
  1902. cmdblk->iopb->xy_complete = 1;
  1903. }
  1904. }
  1905. (void) xycsrvalid(xyio);
  1906. }
  1907. /*
  1908.  * At this point, any register error has been correctly folded
  1909.  * into the iopbs.  We now walk through the chain, handling each
  1910.  * iopb individually.  The chain is dismantled as it is traversed.
  1911.  */
  1912. for (cmdblk = c->c_chain; cmdblk != NULL;
  1913.     nextcmd = cmdblk->next, cmdblk->next = NULL, cmdblk = nextcmd) {
  1914. /*
  1915.  * If the done bit isn't set, we just ignore the iopb; it
  1916.  * will get chained up and executed again.
  1917.  */
  1918. if (!cmdblk->iopb->xy_complete)
  1919. continue;
  1920. un = c->c_units[cmdblk->slave];
  1921. /*
  1922.  * Mark the unit as used and not busy.
  1923.  */
  1924. if (un != NULL) {
  1925. un->un_ltick = xyticks;
  1926. dk_busy &= ~(1 << un->un_md->md_dk);
  1927. }
  1928. /*
  1929.  * Execute the error recovery on the iopb.
  1930.  */
  1931. stat = xyrecover(cmdblk, xyasynch);
  1932. /*
  1933.  * If stat came back greater than zero, the
  1934.  * error recovery has re-executed the command.
  1935.  * In that case, we ignore it since it will get chained
  1936.  * up later.
  1937.  */
  1938. if (stat > 0)
  1939. continue;
  1940. /*
  1941.  * In the ASYNCHWAIT case, we pass back
  1942.  * status via the flags and wakeup the
  1943.  * calling process.
  1944.  */
  1945. if (cmdblk->flags & XY_WAIT) {
  1946. cmdblk->flags &= ~XY_WAIT;
  1947. if (stat == -1)
  1948. cmdblk->flags |= XY_FAILED;
  1949. cmdblk->flags |= XY_DONE;
  1950. wakeup((caddr_t)cmdblk);
  1951. /*
  1952.  * In the ASYNCH case, we pass back status
  1953.  * via the buffer.  If the command used
  1954.  * mainbus space, we release that.  If
  1955.  * someone wants the iopb, wake
  1956.  * them up, otherwise start up the next
  1957.  * buf operation.
  1958.  */
  1959. } else {
  1960. cmdblk->flags &= ~XY_FBSY;
  1961. if ((cmdblk->cmd == XY_READ) ||
  1962.     (cmdblk->cmd == XY_WRITE)) {
  1963. if (stat == -1)
  1964. un->un_md->md_utab.b_forw->b_flags |=
  1965.     B_ERROR;
  1966. mbudone(un->un_md);
  1967. }
  1968. if (cmdblk->flags & XY_WANTED) {
  1969. cmdblk->flags &= ~XY_WANTED;
  1970. wakeup((caddr_t)cmdblk);
  1971. } else
  1972. xyustart(un);
  1973. }
  1974. }
  1975. /*
  1976.  * Chain together the ready iopbs and execute them.
  1977.  */
  1978. c->c_chain = NULL;
  1979. c->c_wantint = 0;
  1980. xychain(c);
  1981. }
  1982. #ifdef DKIOCWCHK
  1983. static void
  1984. xywchk_start(un)
  1985. register struct xyunit *un;
  1986. {
  1987. /*
  1988.  * Somebody may have disable write checking, and un_savbuf
  1989.  * may have gone away.
  1990.  */
  1991. if (un->un_savbuf) {
  1992. bcopy((int) un->un_savaddr + DVMA, un->un_savbuf,
  1993. MIN(un->un_savnsect*SECSIZE, maxphys));
  1994. return;
  1995. }
  1996. }
  1997. #ifdef DDD
  1998. static int xy_generr = 0;
  1999. static int xy_errmod;
  2000. #endif DDD
  2001. static int
  2002. xywchk_done(un)
  2003. register struct xyunit *un;
  2004. {
  2005. /*
  2006.  * Somebody may have disable write checking, and un_savbuf
  2007.  * may have gone away.
  2008.  */
  2009. if (un->un_savbuf) {
  2010. #ifdef DDD
  2011. if (xy_generr) {
  2012. if (xy_errmod++ == xy_generr || xy_generr == -1) {
  2013. caddr_t p;
  2014. while (xy_errmod >= un->un_savnsect*SECSIZE)
  2015. xy_errmod -= un->un_savnsect *SECSIZE;
  2016. p = (caddr_t) (xy_errmod +
  2017.     (int) un->un_savaddr + (int) DVMA);
  2018. *p ^= 0xff;
  2019. xy_errmod = 0;
  2020. }
  2021. }
  2022. #endif DDD
  2023. return (bcmp((int) un->un_savaddr + DVMA, un->un_savbuf,
  2024. (int)MIN(un->un_savnsect*SECSIZE, maxphys)));
  2025. }
  2026. return (0);
  2027. }
  2028. #endif DKIOCWCHK
  2029. /*
  2030.  * Wait for controller csr to become valid.
  2031.  * Waits for at most 200 usec. Returns true if wait succeeded.
  2032.  */
  2033. int
  2034. xycsrvalid(xyio)
  2035. register struct xydevice *xyio;
  2036. {
  2037. register int i;
  2038. for (i = 20; i && xyio->xy_csr & (XY_BUSY|XY_DBLERR); i--)
  2039. DELAY(10);
  2040. DELAY(10);
  2041.         return ((xyio->xy_csr & (XY_BUSY|XY_DBLERR)) == 0);
  2042. }
  2043. /*
  2044.  * Wait for controller become ready. Used after reset or interrupt.
  2045.  * Waits for at most .1 sec. Returns true if wait succeeded.
  2046.  * A reset should never take more than .1 sec
  2047.  */
  2048. int
  2049. xywait(xyio)
  2050. register struct xydevice *xyio;
  2051. {
  2052. register int i;
  2053. for (i = 10000; i && (xyio->xy_csr & XY_BUSY); i--)
  2054. DELAY(10);
  2055. DELAY(10);
  2056. return ((xyio->xy_csr & XY_BUSY) == 0);
  2057. }
  2058. /*
  2059.  * Wait for controller become ready after an interrupt.
  2060.  */
  2061. int
  2062. xyintwait(xyio)
  2063. register struct xydevice *xyio;
  2064. {
  2065. register int i;
  2066. for (i = 20; i && (xyio->xy_csr & (XY_BUSY | XY_INTR)); i--)
  2067. DELAY(10);
  2068. DELAY(10);
  2069. return ((xyio->xy_csr & (XY_BUSY | XY_INTR)) == 0);
  2070. }
  2071. /*
  2072.  * This routine performs raw read operations.  It is called from the
  2073.  * device switch at normal priority.  It uses a per-unit buffer for the
  2074.  * operation.
  2075.  */
  2076. xyread(dev, uio)
  2077. dev_t dev;
  2078. struct uio *uio;
  2079. {
  2080. if (UNIT(dev) >= nxy)
  2081. return (ENXIO);
  2082. return (physio(xystrategy, (struct buf *)NULL,
  2083.     dev, B_READ, minphys, uio));
  2084. }
  2085. /*
  2086.  * This routine performs raw write operations.  It is called from the
  2087.  * device switch at normal priority.  It uses a per-unit buffer for the
  2088.  * operation.
  2089.  */
  2090. xywrite(dev, uio)
  2091. dev_t dev;
  2092. struct uio *uio;
  2093. {
  2094. if (UNIT(dev) >= nxy)
  2095. return (ENXIO);
  2096. return (physio(xystrategy, (struct buf *)NULL,
  2097.     dev, B_WRITE, minphys, uio));
  2098. }
  2099. /*
  2100.  * This routine finishes a buf-oriented operation.  It is called from
  2101.  * mbudone() after the mainbus space has been reclaimed.  It is always
  2102.  * called at disk interrupt priority.
  2103.  */
  2104. xydone(md)
  2105. register struct mb_device *md;
  2106. {
  2107. /*
  2108.  * Advance device buffer queue
  2109.  * Set residual i/o count
  2110.  * Release the buffer back to the world
  2111.  * Clear active slot.
  2112.  */
  2113. register struct diskhd *dp = &md->md_utab;
  2114. struct buf *bp = dp->b_forw;
  2115. dp->b_actf = bp->av_forw;
  2116. if (dp->b_actl == bp)
  2117.     dp->b_actl = NULL;
  2118. bp->b_resid = xyunits[md->md_unit].un_residual;
  2119. iodone(bp);
  2120. dp->b_forw = NULL;
  2121. }
  2122. /*
  2123.  * These defines are used by some of the ioctl calls.
  2124.  */
  2125. #define ONTRACK(x) (!((x) % un->un_g->dkg_nsect))
  2126. #define XY_MAXBUFSIZE (63 * 1024)
  2127. /*
  2128.  * This routine implements the ioctl calls for the 450.  It is called
  2129.  * from the device switch at normal priority.
  2130.  */
  2131. /* ARGSUSED */
  2132. xyioctl(dev, cmd, data, flag)
  2133. dev_t dev;
  2134. int cmd, flag;
  2135. caddr_t data;
  2136. {
  2137. register struct xyunit *un = &xyunits[UNIT(dev)];
  2138. register struct dk_map *lp = &un->un_map[LPART(dev)];
  2139. struct dk_info *inf;
  2140. struct dk_conf *conf;
  2141. struct dk_type *typ;
  2142. struct dk_badmap *bad;
  2143. struct dk_cmd *com;
  2144. struct dk_diag *diag;
  2145. int i, s, flags = 0, err, hsect, mbcookie, bfr = 0, exec = 0;
  2146. char cmddir;
  2147. struct buf *bp = un->un_rtab;
  2148. faultcode_t fault_err;
  2149. switch (cmd) {
  2150. #ifdef DKIOCWCHK
  2151. case DKIOCWCHK:
  2152. if (!suser())
  2153. return (u.u_error);
  2154. if (!un || lp->dkl_nblk == 0)
  2155. return (ENXIO);
  2156. i = (*((int *) data));
  2157. if (i) {
  2158. s = splr(pritospl(un->un_mc->mc_intpri));
  2159. (*((int *) data)) =
  2160.     ((un->un_wchkmap & (1<<LPART(dev))) != 0);
  2161. un->un_wchkmap |= (1 << LPART(dev));
  2162. if (!un->un_savbuf) {
  2163. un->un_savbuf =
  2164.     new_kmem_alloc((u_int) maxphys,
  2165. KMEM_SLEEP);
  2166. }
  2167. /*
  2168.  * VM hack: turn on nopagereclaim, so that
  2169.  * vm doesn't thwack on data while it is
  2170.  * intransit going out (to avoid spurious
  2171.  * verify errors).
  2172.  */
  2173. {
  2174. extern int nopagereclaim;
  2175. nopagereclaim = 1;
  2176. }
  2177. (void) splx(s);
  2178. printf("xy%d%c: write check enabledn",
  2179. un->un_md->md_unit, 'a'+LPART(dev));
  2180. } else  {
  2181. s = splr(pritospl(un->un_mc->mc_intpri));
  2182. (*((int *) data)) =
  2183.     ((un->un_wchkmap & (1<<LPART(dev))) != 0);
  2184. un->un_wchkmap &= ~(1<<LPART(dev));
  2185. if (un->un_wchkmap == 0) {
  2186. if (un->un_savbuf) {
  2187. kmem_free (un->un_savbuf,
  2188.     (u_int) maxphys);
  2189. un->un_savbuf = (caddr_t) 0;
  2190. }
  2191. }
  2192. (void) splx(s);
  2193. printf("xy%d%c: write check disabledn",
  2194. un->un_md->md_unit, 'a' + LPART(dev));
  2195. }
  2196. break;
  2197. #endif DKIOCWCHK
  2198. /*
  2199.  * Return info concerning the controller.
  2200.  */
  2201. case DKIOCINFO:
  2202. inf = (struct dk_info *)data;
  2203. inf->dki_ctlr = getdevaddr(un->un_mc->mc_addr);
  2204. inf->dki_unit = un->un_md->md_slave;
  2205. inf->dki_ctype = DKC_XY450;
  2206. inf->dki_flags = DKI_BAD144 | DKI_FMTTRK;
  2207. break;
  2208. /*
  2209.  * Return configuration info
  2210.  */
  2211. case DKIOCGCONF:
  2212. conf = (struct dk_conf *)data;
  2213. (void) strncpy(conf->dkc_cname, xycdriver.mdr_cname,
  2214.     DK_DEVLEN);
  2215. conf->dkc_ctype = DKC_XY450;
  2216. conf->dkc_flags = DKI_BAD144 | DKI_FMTTRK;
  2217. conf->dkc_cnum = un->un_mc->mc_ctlr;
  2218. conf->dkc_addr = getdevaddr(un->un_mc->mc_addr);
  2219. conf->dkc_space = un->un_mc->mc_space;
  2220. conf->dkc_prio = un->un_mc->mc_intpri;
  2221. if (un->un_mc->mc_intr)
  2222. conf->dkc_vec = un->un_mc->mc_intr->v_vec;
  2223. else
  2224. conf->dkc_vec = 0;
  2225. (void) strncpy(conf->dkc_dname, xycdriver.mdr_dname,
  2226.     DK_DEVLEN);
  2227. conf->dkc_unit = un->un_md->md_unit;
  2228. conf->dkc_slave = un->un_md->md_slave;
  2229. break;
  2230. /*
  2231.  * Return drive info
  2232.  */
  2233. case DKIOCGTYPE:
  2234. typ = (struct dk_type *)data;
  2235. typ->dkt_drtype = un->un_drtype;
  2236. s = splr(pritospl(un->un_mc->mc_intpri));
  2237. err = xycmd(&un->un_cmd, XY_STATUS, minor(dev),
  2238.     (caddr_t)0, un->un_md->md_slave, (daddr_t)0, 0,
  2239.     XY_ASYNCHWAIT, 0);
  2240. typ->dkt_hsect = un->un_cmd.iopb->xy_bufrel & 0xff;
  2241. typ->dkt_promrev = un->un_cmd.iopb->xy_nsect >> 8;
  2242. typ->dkt_drstat = un->un_cmd.iopb->xy_status;
  2243. (void) splx(s);
  2244. if (err)
  2245. return (EIO);
  2246. break;
  2247. /*
  2248.  * Set drive info -- only affects drive type.  NOTE: we
  2249.  * must raise the priority around usegeom() because we
  2250.  * may execute an actual command.
  2251.  */
  2252. case DKIOCSTYPE:
  2253. typ = (struct dk_type *)data;
  2254. s = splr(pritospl(un->un_mc->mc_intpri));
  2255. un->un_drtype = typ->dkt_drtype;
  2256. err = usegeom(un, XY_ASYNCHWAIT);
  2257. (void) splx(s);
  2258. if (err)
  2259. return (EINVAL);
  2260. break;
  2261. /*
  2262.  * Return the geometry of the specified unit.
  2263.  */
  2264. case DKIOCGGEOM:
  2265. *(struct dk_geom *)data = *un->un_g;
  2266. break;
  2267. /*
  2268.  * Set the geometry of the specified unit.  NOTE: we
  2269.  * must raise the priority around usegeom() because we
  2270.  * may execute an actual command.
  2271.  */
  2272. case DKIOCSGEOM:
  2273. s = splr(pritospl(un->un_mc->mc_intpri));
  2274. *un->un_g = *(struct dk_geom *)data;
  2275. err = usegeom(un, XY_ASYNCHWAIT);
  2276. (void) splx(s);
  2277. if (err)
  2278. return (EINVAL);
  2279. break;
  2280. /*
  2281.  * Return the map for the specified logical partition.
  2282.  * This has been made obsolete by the get all partitions
  2283.  * command.
  2284.  */
  2285. case DKIOCGPART:
  2286. *(struct dk_map *)data = *lp;
  2287. break;
  2288. /*
  2289.  * Set the map for the specified logical partition.
  2290.  * This has been made obsolete by the set all partitions
  2291.  * command.  We raise the priority just to make sure
  2292.  * an interrupt doesn't come in while the map is
  2293.  * half updated.
  2294.  */
  2295. case DKIOCSPART:
  2296. s = splr(pritospl(un->un_mc->mc_intpri));
  2297. *lp = *(struct dk_map *)data;
  2298. (void) splx(s);
  2299. break;
  2300. /*
  2301.  * Return the map for all logical partitions.
  2302.  */
  2303. case DKIOCGAPART:
  2304. for (i = 0; i < XYNLPART; i++)
  2305. ((struct dk_map *)data)[i] = un->un_map[i];
  2306. break;
  2307. /*
  2308.  * Set the map for all logical partitions.  We raise
  2309.  * the priority just to make sure an interrupt doesn't
  2310.  * come in while the map is half updated.
  2311.  */
  2312. case DKIOCSAPART:
  2313. s = splr(pritospl(un->un_mc->mc_intpri));
  2314. for (i = 0; i < XYNLPART; i++)
  2315. un->un_map[i] = ((struct dk_map *)data)[i];
  2316. (void) splx(s);
  2317. break;
  2318. /*
  2319.  * Get the bad sector map.
  2320.  */
  2321. case DKIOCGBAD:
  2322. bad = (struct dk_badmap *)data;
  2323. err = copyout((caddr_t)un->un_bad, bad->dkb_bufaddr,
  2324.     (u_int)sizeof (struct dkbad));
  2325. return (err);
  2326. /*
  2327.  * Set the bad sector map.  We raise the priority just
  2328.  * to make sure an interrupt doesn't come in while the
  2329.  * table is half updated.
  2330.  */
  2331. case DKIOCSBAD:
  2332. bad = (struct dk_badmap *)data;
  2333. s = splr(pritospl(un->un_mc->mc_intpri));
  2334. err = copyin(bad->dkb_bufaddr, (caddr_t)un->un_bad,
  2335.     (u_int)sizeof (struct dkbad));
  2336. (void) splx(s);
  2337. return (err);
  2338. /*
  2339.  * Generic command
  2340.  */
  2341. case DKIOCSCMD:
  2342. com = (struct dk_cmd *)data;
  2343. cmddir = XY_OUT;
  2344. /*
  2345.  * Check the parameters.
  2346.  */
  2347. switch (com->dkc_cmd) {
  2348.     case XY_READ:
  2349. cmddir = XY_IN;
  2350. /* fall through */
  2351.     case XY_WRITE:
  2352. if (com->dkc_buflen != (com->dkc_secnt *
  2353.     SECSIZE)) {
  2354. err = EINVAL;
  2355. goto errout;
  2356. }
  2357. break;
  2358.     case XY_RESTORE:
  2359. if (com->dkc_buflen != 0) {
  2360. err = EINVAL;
  2361. goto errout;
  2362. }
  2363. break;
  2364.     case XY_FORMAT:
  2365. if ((com->dkc_buflen != 0) ||
  2366.     (!ONTRACK(com->dkc_blkno)) ||
  2367.     (!ONTRACK(com->dkc_secnt))) {
  2368. err = EINVAL;
  2369. goto errout;
  2370. }
  2371. break;
  2372.     case XY_READHDR:
  2373. cmddir = XY_IN;
  2374. /* fall through */
  2375.     case XY_WRITEHDR:
  2376. s = splr(pritospl(un->un_mc->mc_intpri));
  2377. err = xycmd(&un->un_cmd, XY_STATUS, minor(dev),
  2378.     (caddr_t)0, un->un_md->md_slave, (daddr_t)0,
  2379.     0, XY_ASYNCHWAIT, XY_NOMSG);
  2380. hsect = un->un_cmd.iopb->xy_bufrel & 0xff;
  2381. (void) splx(s);
  2382. if (err) {
  2383. err = EIO;
  2384. goto errout;
  2385. }
  2386. if ((!ONTRACK(com->dkc_blkno)) ||
  2387.     (com->dkc_buflen != hsect * XY_HDRSIZE)) {
  2388. err = EINVAL;
  2389. goto errout;
  2390. }
  2391. break;
  2392.     case XY_READALL | XY_DEFLST:
  2393. cmddir = XY_IN;
  2394. if ((!ONTRACK(com->dkc_blkno)) ||
  2395.     (com->dkc_buflen != XY_MANDEFSIZE)) {
  2396. err = EINVAL;
  2397. goto errout;
  2398. }
  2399. break;
  2400.     default:
  2401. err = EINVAL;
  2402. goto errout;
  2403. }
  2404. /*
  2405.  * Don't allow more than max at once.
  2406.  */
  2407. if (com->dkc_buflen > XY_MAXBUFSIZE)
  2408. return (EINVAL);
  2409. /*
  2410.  * If this command moves data, we need to map
  2411.  * the user buffer into DVMA space.
  2412.  */
  2413. if (com->dkc_buflen != 0) {
  2414. /*
  2415.  * Get the unit's raw I/O buf.
  2416.  */
  2417. s = spl6();
  2418. while (bp->b_flags & B_BUSY) {
  2419. bp->b_flags |= B_WANTED;
  2420. (void) sleep((caddr_t)bp, PRIBIO+1);
  2421. }
  2422. (void) splx(s);
  2423. /*
  2424.  * Make the buf look real.
  2425.  */
  2426. bp->b_flags = B_BUSY | B_PHYS;
  2427. bp->b_flags |=
  2428. (cmddir == XY_IN ? B_READ : B_WRITE);
  2429. bp->b_un.b_addr = com->dkc_bufaddr;
  2430. bp->b_bcount = com->dkc_buflen;
  2431. bp->b_proc = u.u_procp;
  2432. u.u_procp->p_flag |= SPHYSIO;
  2433. /*
  2434.  * Fault lock the address range of the buffer.
  2435.  */
  2436. fault_err = as_fault(u.u_procp->p_as,
  2437.     bp->b_un.b_addr, (u_int)bp->b_bcount,
  2438.     F_SOFTLOCK,
  2439.     cmddir == XY_OUT ? S_READ : S_WRITE);
  2440. if (fault_err != 0) {
  2441. if (FC_CODE(fault_err) == FC_OBJERR)
  2442. err = FC_ERRNO(fault_err);
  2443. else
  2444. err = EFAULT;
  2445. goto out;
  2446. }
  2447. /*
  2448.  * Make sure the address range has legal
  2449.  * properties for the mb routines.
  2450.  */
  2451. if (buscheck(bp) < 0) {
  2452. err = EFAULT;
  2453. goto out;
  2454. }
  2455. /*
  2456.  * Map the buffer into DVMA space.
  2457.  */
  2458. mbcookie = mbsetup(un->un_md->md_hd, bp, 0);
  2459. bfr = MBI_ADDR(mbcookie);
  2460. }
  2461. /*
  2462.  * Execute the command.
  2463.  */
  2464. if (com->dkc_flags & DK_SILENT)
  2465. flags |= XY_NOMSG;
  2466. if (com->dkc_flags & DK_DIAGNOSE)
  2467. flags |= XY_DIAG;
  2468. if (com->dkc_flags & DK_ISOLATE)
  2469. flags |= XY_NOCHN;
  2470. s = splr(pritospl(un->un_mc->mc_intpri));
  2471. err = xycmd(&un->un_cmd, com->dkc_cmd, minor(dev),
  2472.     (caddr_t)bfr, un->un_md->md_slave, com->dkc_blkno,
  2473.     com->dkc_secnt, XY_ASYNCHWAIT, flags);
  2474. exec = 1;
  2475. (void) splx(s);
  2476. if (err)
  2477. err = EIO;
  2478. /*
  2479.  * Release memory and DVMA resources.
  2480.  */
  2481. if (com->dkc_buflen != 0) {
  2482. mbrelse(un->un_md->md_hd, &mbcookie);
  2483. out:
  2484. if (fault_err == 0)
  2485. (void) as_fault(u.u_procp->p_as,
  2486.     bp->b_un.b_addr,
  2487.     (u_int)bp->b_bcount, F_SOFTUNLOCK,
  2488.     cmddir == XY_OUT? S_READ : S_WRITE);
  2489. (void) spl6();
  2490. u.u_procp->p_flag &= ~SPHYSIO;
  2491. if (bp->b_flags & B_WANTED)
  2492. wakeup((caddr_t)bp);
  2493. (void) splx(s);
  2494. bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);
  2495. }
  2496. errout:
  2497. if (exec == 0 && err &&
  2498.     (com->dkc_flags & DK_DIAGNOSE)) {
  2499. un->un_errsect = 0;
  2500. un->un_errno = XYE_UNKN;
  2501. un->un_errcmd = com->dkc_cmd;
  2502. un->un_errsevere = DK_FATAL;
  2503. }
  2504. return (err);
  2505. /*
  2506.  * Get diagnostics
  2507.  */
  2508. case DKIOCGDIAG:
  2509. diag = (struct dk_diag *)data;
  2510. diag->dkd_errsect = un->un_errsect;
  2511. diag->dkd_errno = un->un_errno;
  2512. diag->dkd_errcmd = un->un_errcmd;
  2513. diag->dkd_severe = un->un_errsevere;
  2514. break;
  2515. /*
  2516.  * This ain't no party, this ain't no disco.
  2517.  */
  2518. default:
  2519. return (ENOTTY);
  2520. }
  2521. return (0);
  2522. }
  2523. /* This routine runs at regular intervals and checks to make sure a
  2524.  * controller isn't hung and a disk hasn't gone offline.  It is called
  2525.  * by itself and xyattach() via the timeout facility.  It is always
  2526.  * called at normal priority.
  2527.  */
  2528. xywatch()
  2529. {
  2530. register struct xyunit *un;
  2531. register struct xycmdblock *cmdblk;
  2532. register struct xyctlr *c;
  2533. int s, junk, len;
  2534. /*
  2535.  * Advance time.
  2536.  */
  2537. xyticks++;
  2538. /*
  2539.  * Search the controllers for one who has wanted an interrupt
  2540.  * for too long.
  2541.  */
  2542. for (c = xyctlrs; c < &xyctlrs[nxyc]; c++) {
  2543. /*
  2544.  * Raise priority while looking at these guys....
  2545.  *
  2546.  * This is tricky here, as the controller may,
  2547.  * at any point, wake up and attempt to issue
  2548.  * an interrupt. We will try the best as we
  2549.  * can to avoid this by continuing to look at
  2550.  * the csr to see if an interrupt is pending..
  2551.  *
  2552.  */
  2553. if (!(c->c_flags & XY_C_PRESENT))
  2554. continue;
  2555. s = splr(pritospl(xycinfo[c - xyctlrs]->mc_intpri));
  2556. if (c->c_wantint) {
  2557. /*
  2558.  * Step through the outstanding commands.  For each
  2559.  * one, calculate about how many tracks the command
  2560.  * is for and sum the number of tracks.
  2561.  */
  2562. len = 0;
  2563. for (cmdblk = c->c_chain; cmdblk != NULL;
  2564.     cmdblk = cmdblk->next) {
  2565. un = cmdblk->c->c_units[cmdblk->slave];
  2566. if (un == NULL || un->un_g == NULL) {
  2567. len += 1;
  2568. continue;
  2569. }
  2570. len += cmdblk->nsect / un->un_g->dkg_nsect + 1;
  2571. }
  2572. /*
  2573.  * If the ctlr has been working for less than
  2574.  * XYLOSTINTTIMO times the total number of tracks
  2575.  * outstanding, we give it more time.
  2576.  */
  2577. if (xyticks - c->c_wantint < XYLOSTINTTIMO * len) {
  2578. (void) splx(s);
  2579. continue;
  2580. }
  2581. /*
  2582.  * Found a (possibly) hung one.
  2583.  *
  2584.  * Look for a command on the controller that isn't
  2585.  * done.  If we find one, give it a lost interrupt
  2586.  * error.
  2587.  */
  2588. junk = 0;
  2589. for (cmdblk = c->c_chain; cmdblk != NULL;
  2590. cmdblk = cmdblk->next) {
  2591. if (cmdblk->iopb->xy_complete)
  2592. continue;
  2593. if (c->c_io->xy_csr & XY_INTR) {
  2594. junk = 1;
  2595. break;
  2596. }
  2597. /*
  2598.  * At this point, we are now committed
  2599.  * to giving an error to an iopb
  2600.  * no matter whether or not the
  2601.  * controller woke up and tried
  2602.  * to get at us..
  2603.  */
  2604. cmdblk->iopb->xy_iserr = 1;
  2605. cmdblk->iopb->xy_errno = XYE_LINT;
  2606. cmdblk->iopb->xy_complete = 1;
  2607. break;
  2608. }
  2609. if (junk) {
  2610. /*
  2611.  * an interrupt was pending. accept it.
  2612.  */
  2613. (void) splx(s);
  2614. continue;
  2615. } else if (cmdblk == NULL) {
  2616. if (c->c_io->xy_csr & XY_INTR) {
  2617. /*
  2618.  * an interrupt is pending. accept it.
  2619.  */
  2620. (void) splx(s);
  2621. continue;
  2622. }
  2623. /*
  2624.  * If they were all marked done, we just reset
  2625.  * the controller.
  2626.  */
  2627. /*
  2628.  * We're now committed to a reset
  2629.  */
  2630. junk = c->c_io->xy_resupd;
  2631. if (!xywait(c->c_io)) {
  2632. printf("xyc%d: ", c - xyctlrs);
  2633. panic("controller reset failed");
  2634. }
  2635. }
  2636. /*
  2637.  * Have the controller serviced as if it had
  2638.  * interrupted.
  2639.  */
  2640. xyintr(c);
  2641. }
  2642. (void) splx(s);
  2643. }
  2644. #ifdef lint
  2645. junk = junk;
  2646. #endif
  2647. /*
  2648.  * Search the disks for one that's online but hasn't been used
  2649.  * for too long.
  2650.  */
  2651. for (un = xyunits; un < &xyunits[nxy]; un++) {
  2652. if (!(un->un_flags & XY_UN_PRESENT))
  2653. continue;
  2654. /*
  2655.  * Raise the priority while we're looking at this unit
  2656.  */
  2657. s = splr(pritospl(un->un_mc->mc_intpri));
  2658. if (xyticks - un->un_ltick < XYWATCHTIMO) {
  2659. (void) splx(s);
  2660. continue;
  2661. }
  2662. /*
  2663.  * If the unit's iopb isn't busy, send the drive a reset
  2664.  * command just to make sure it's still online.
  2665.  */
  2666. if (!(un->un_cmd.flags & XY_FBSY))
  2667. (void) xycmd(&un->un_cmd, XY_RESTORE, NOLPART,
  2668.     (caddr_t)0, un->un_md->md_slave, (daddr_t)0, 0,
  2669.     XY_ASYNCH, 0);
  2670. (void) splx(s);
  2671. }
  2672. /*
  2673.  * Schedule ourself to run again in a little while.
  2674.  */
  2675. timeout(xywatch, (caddr_t)0, hz);
  2676. }
  2677. /*
  2678.  * This routine dumps memory to the disk.  It assumes that the memory has
  2679.  * already been mapped into mainbus space.  It is called at disk interrupt
  2680.  * priority when the system is in trouble.
  2681.  */
  2682. xydump(dev, addr, blkno, nblk)
  2683. dev_t dev;
  2684. caddr_t addr;
  2685. daddr_t blkno, nblk;
  2686. {
  2687. register struct xyunit *un = &xyunits[UNIT(dev)];
  2688. register struct dk_map *lp = &un->un_map[LPART(dev)];
  2689. int unit = un->un_md->md_slave;
  2690. int err;
  2691. /*
  2692.  * Check to make sure the operation makes sense.
  2693.  */
  2694. if (!(un->un_flags & XY_UN_PRESENT))
  2695. return (ENXIO);
  2696. if (blkno >= lp->dkl_nblk || (blkno + nblk) > lp->dkl_nblk)
  2697. return (EINVAL);
  2698. /*
  2699.  * Offset into the correct partition.
  2700.  */
  2701. blkno += (lp->dkl_cylno + un->un_g->dkg_bcyl) * un->un_g->dkg_nhead *
  2702.     un->un_g->dkg_nsect;
  2703. /*
  2704.  * Synchronously execute the dump and return the status.
  2705.  */
  2706. err = xycmd(&un->un_cmd, XY_WRITE, minor(dev),
  2707.     (caddr_t)((char *)addr - DVMA), unit, blkno, (int)nblk,
  2708.     XY_SYNCH, 0);
  2709. return (err ? EIO : 0);
  2710. }