123353Smckusick /* 232523Sbostic * Copyright (c) 1987 Regents of the University of California. 332523Sbostic * All rights reserved. The Berkeley software License Agreement 432523Sbostic * specifies the terms and conditions for redistribution. 532523Sbostic * 6*33444Sbostic * @(#)uda.c 7.13 (Berkeley) 02/06/88 732523Sbostic * 823353Smckusick */ 923353Smckusick 1032523Sbostic /* 1132523Sbostic * UDA50/MSCP device driver 1217553Skarels */ 1317553Skarels 1432523Sbostic #define POLLSTATS 1532523Sbostic 1632523Sbostic /* 1732523Sbostic * TODO 1832523Sbostic * write bad block forwarding code 1932523Sbostic */ 2032523Sbostic 214743Swnj #include "ra.h" 2232523Sbostic 2317642Skarels #if NUDA > 0 2432523Sbostic 254743Swnj /* 2632523Sbostic * CONFIGURATION OPTIONS. The next three defines are tunable -- tune away! 274743Swnj * 2832523Sbostic * COMPAT_42 enables 4.2/4.3 compatibility (label mapping) 2932523Sbostic * 3032523Sbostic * NRSPL2 and NCMDL2 control the number of response and command 3132523Sbostic * packets respectively. They may be any value from 0 to 7, though 3232523Sbostic * setting them higher than 5 is unlikely to be of any value. 3332523Sbostic * If you get warnings about your command ring being too small, 3432523Sbostic * try increasing the values by one. 3532523Sbostic * 3632523Sbostic * MAXUNIT controls the maximum unit number (number of drives per 3732523Sbostic * controller) we are prepared to handle. 3832523Sbostic * 3932523Sbostic * DEFAULT_BURST must be at least 1. 404743Swnj */ 4132523Sbostic #define COMPAT_42 4232523Sbostic 4332523Sbostic #define NRSPL2 5 /* log2 number of response packets */ 4432523Sbostic #define NCMDL2 5 /* log2 number of command packets */ 4532523Sbostic #define MAXUNIT 8 /* maximum allowed unit number */ 4632523Sbostic #define DEFAULT_BURST 4 /* default DMA burst size */ 4732523Sbostic 489781Ssam #include "../machine/pte.h" 494743Swnj 5017553Skarels #include "param.h" 5117553Skarels #include "systm.h" 5217553Skarels #include "buf.h" 5317553Skarels #include "conf.h" 5417553Skarels #include "dir.h" 5530536Skarels #include "file.h" 5630536Skarels #include "ioctl.h" 5717553Skarels #include "user.h" 5817553Skarels #include "map.h" 5917553Skarels #include "vm.h" 6030536Skarels #include "dkstat.h" 6117553Skarels #include "cmap.h" 6230536Skarels #include "disklabel.h" 6330536Skarels #include "syslog.h" 6430773Skarels #include "stat.h" 654743Swnj 668482Sroot #include "../vax/cpu.h" 6717553Skarels #include "ubareg.h" 6817553Skarels #include "ubavar.h" 698613Sroot 7032523Sbostic #define NRSP (1 << NRSPL2) 7132523Sbostic #define NCMD (1 << NCMDL2) 728613Sroot 7332523Sbostic #include "udareg.h" 748482Sroot #include "../vax/mscp.h" 7532523Sbostic #include "../vax/mscpvar.h" 7632523Sbostic #include "../vax/mtpr.h" 774743Swnj 7832523Sbostic /* 7932523Sbostic * Backwards compatibility: Reuse the old names. Should fix someday. 8032523Sbostic */ 8132523Sbostic #define udaprobe udprobe 8232523Sbostic #define udaslave udslave 8332523Sbostic #define udaattach udattach 8432523Sbostic #define udaopen udopen 8532523Sbostic #define udaclose udclose 8632523Sbostic #define udastrategy udstrategy 8732523Sbostic #define udaread udread 8832523Sbostic #define udawrite udwrite 8932523Sbostic #define udaioctl udioctl 9032523Sbostic #define udareset udreset 9132523Sbostic #define udaintr udintr 9232523Sbostic #define udadump uddump 9332523Sbostic #define udasize udsize 9417553Skarels 9532523Sbostic /* 9632523Sbostic * UDA communications area and MSCP packet pools, per controller. 9732523Sbostic */ 9832523Sbostic struct uda { 9932523Sbostic struct udaca uda_ca; /* communications area */ 10032523Sbostic struct mscp uda_rsp[NRSP]; /* response packets */ 10132523Sbostic struct mscp uda_cmd[NCMD]; /* command packets */ 1024743Swnj } uda[NUDA]; 1034743Swnj 10432523Sbostic /* 10532523Sbostic * Software status, per controller. 10632523Sbostic */ 10732523Sbostic struct uda_softc { 10832523Sbostic struct uda *sc_uda; /* Unibus address of uda struct */ 10932523Sbostic short sc_state; /* UDA50 state; see below */ 11032523Sbostic short sc_flags; /* flags; see below */ 11132523Sbostic int sc_micro; /* microcode revision */ 11232523Sbostic int sc_ivec; /* interrupt vector address */ 11332523Sbostic struct mscp_info sc_mi;/* MSCP info (per mscpvar.h) */ 11432523Sbostic #ifndef POLLSTATS 11532523Sbostic int sc_wticks; /* watchdog timer ticks */ 11632523Sbostic #else 11732523Sbostic short sc_wticks; 11832523Sbostic short sc_ncmd; 11932523Sbostic #endif 12032523Sbostic } uda_softc[NUDA]; 12124742Sbloom 12232523Sbostic #ifdef POLLSTATS 12332523Sbostic struct udastats { 12432523Sbostic int ncmd; 12532523Sbostic int cmd[NCMD + 1]; 12632523Sbostic } udastats = { NCMD + 1 }; 12732523Sbostic #endif 12817553Skarels 12932523Sbostic /* 13032523Sbostic * Controller states 13132523Sbostic */ 13232523Sbostic #define ST_IDLE 0 /* uninitialised */ 13332523Sbostic #define ST_STEP1 1 /* in `STEP 1' */ 13432523Sbostic #define ST_STEP2 2 /* in `STEP 2' */ 13532523Sbostic #define ST_STEP3 3 /* in `STEP 3' */ 13632523Sbostic #define ST_SETCHAR 4 /* in `Set Controller Characteristics' */ 13732523Sbostic #define ST_RUN 5 /* up and running */ 1384743Swnj 13932523Sbostic /* 14032523Sbostic * Flags 14132523Sbostic */ 14232523Sbostic #define SC_MAPPED 0x01 /* mapped in Unibus I/O space */ 14332523Sbostic #define SC_INSTART 0x02 /* inside udastart() */ 14432523Sbostic #define SC_GRIPED 0x04 /* griped about cmd ring too small */ 14532523Sbostic #define SC_INSLAVE 0x08 /* inside udaslave() */ 14632523Sbostic #define SC_DOWAKE 0x10 /* wakeup when ctlr init done */ 14732523Sbostic #define SC_STARTPOLL 0x20 /* need to initiate polling */ 14812421Ssam 14932523Sbostic /* 15032523Sbostic * Device to unit number and partition and back 15132523Sbostic */ 15232523Sbostic #define UNITSHIFT 3 15332523Sbostic #define UNITMASK 7 15432523Sbostic #define udaunit(dev) (minor(dev) >> UNITSHIFT) 15532523Sbostic #define udapart(dev) (minor(dev) & UNITMASK) 15632523Sbostic #define udaminor(u, p) (((u) << UNITSHIFT) | (p)) 1574743Swnj 15817553Skarels /* 15932523Sbostic * Drive status, per drive 16017553Skarels */ 16132523Sbostic struct ra_info { 16232523Sbostic daddr_t ra_dsize; /* size in sectors */ 163*33444Sbostic /* u_long ra_type; /* drive type */ 16433195Sbostic #define RA_TYPE_RX50 7 /* special: see udaopen */ 16532523Sbostic u_long ra_mediaid; /* media id */ 16632523Sbostic int ra_state; /* open/closed state */ 16732523Sbostic struct ra_geom { /* geometry information */ 16832523Sbostic u_short rg_nsectors; /* sectors/track */ 16932523Sbostic u_short rg_ngroups; /* track groups */ 17032523Sbostic u_short rg_ngpc; /* groups/cylinder */ 17132523Sbostic u_short rg_ntracks; /* ngroups*ngpc */ 17232523Sbostic u_short rg_ncyl; /* ra_dsize/ntracks/nsectors */ 17332523Sbostic #ifdef notyet 17432523Sbostic u_short rg_rctsize; /* size of rct */ 17532523Sbostic u_short rg_rbns; /* replacement blocks per track */ 17632523Sbostic u_short rg_nrct; /* number of rct copies */ 17732523Sbostic #endif 17832523Sbostic } ra_geom; 17933443Skarels int ra_wlabel; /* label sector is currently writable */ 18032523Sbostic u_long ra_openpart; /* partitions open */ 18132523Sbostic u_long ra_bopenpart; /* block partitions open */ 18232523Sbostic u_long ra_copenpart; /* character partitions open */ 18332523Sbostic } ra_info[NRA]; 18417553Skarels 18530536Skarels /* 18630536Skarels * Software state, per drive 18730536Skarels */ 18830536Skarels #define CLOSED 0 18930536Skarels #define WANTOPEN 1 19030536Skarels #define RDLABEL 2 19130536Skarels #define OPEN 3 19230536Skarels #define OPENRAW 4 19317553Skarels 19432523Sbostic /* 19532523Sbostic * Definition of the driver for autoconf. 19632523Sbostic */ 19732523Sbostic int udaprobe(), udaslave(), udaattach(), udadgo(), udaintr(); 19832523Sbostic struct uba_ctlr *udaminfo[NUDA]; 19932523Sbostic struct uba_device *udadinfo[NRA]; 20032523Sbostic struct disklabel udalabel[NRA]; 20117553Skarels 20232523Sbostic u_short udastd[] = { 0772150, 0772550, 0777550, 0 }; 20332523Sbostic struct uba_driver udadriver = 20432523Sbostic { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda", 20532523Sbostic udaminfo }; 20617553Skarels 20732523Sbostic /* 20832523Sbostic * More driver definitions, for generic MSCP code. 20932523Sbostic */ 21032523Sbostic int udadgram(), udactlrdone(), udaunconf(), udaiodone(); 21132523Sbostic int udaonline(), udagotstatus(), udaioerror(), udareplace(), udabb(); 2124743Swnj 21332523Sbostic struct buf udautab[NRA]; /* per drive transfer queue */ 2144743Swnj 21532523Sbostic struct mscp_driver udamscpdriver = 21632523Sbostic { MAXUNIT, NRA, UNITSHIFT, udautab, udadinfo, 21732523Sbostic udadgram, udactlrdone, udaunconf, udaiodone, 21832523Sbostic udaonline, udagotstatus, udareplace, udaioerror, udabb, 21932523Sbostic "uda", "ra" }; 22032523Sbostic 22132523Sbostic /* 22232523Sbostic * Miscellaneous private variables. 22332523Sbostic */ 22432523Sbostic char udasr_bits[] = UDASR_BITS; 22532523Sbostic 22632523Sbostic struct uba_device *udaip[NUDA][MAXUNIT]; 22732523Sbostic /* inverting pointers: ctlr & unit => Unibus 22832523Sbostic device pointer */ 22932523Sbostic 23032523Sbostic int udaburst[NUDA] = { 0 }; /* burst size, per UDA50, zero => default; 23132523Sbostic in data space so patchable via adb */ 23232523Sbostic 23332523Sbostic struct mscp udaslavereply; /* get unit status response packet, set 23432523Sbostic for udaslave by udaunconf, via udaintr */ 23532523Sbostic 23632523Sbostic static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr 23732523Sbostic info to slave routine; instead, we remember 23832523Sbostic the last ctlr argument to probe */ 23932523Sbostic 24032523Sbostic int udawstart, udawatch(); /* watchdog timer */ 24132523Sbostic 24232523Sbostic /* 24332523Sbostic * Externals 24432523Sbostic */ 24532523Sbostic int wakeup(); 24632523Sbostic int hz; 24732523Sbostic 24832523Sbostic /* 24932523Sbostic * Poke at a supposed UDA50 to see if it is there. 25032523Sbostic * This routine duplicates some of the code in udainit() only 25132523Sbostic * because autoconf has not set up the right information yet. 25232523Sbostic * We have to do everything `by hand'. 25332523Sbostic */ 25432523Sbostic udaprobe(reg, ctlr, um) 2554743Swnj caddr_t reg; 2564743Swnj int ctlr; 25732523Sbostic struct uba_ctlr *um; 2584743Swnj { 2594743Swnj register int br, cvec; 26032523Sbostic register struct uda_softc *sc; 26132523Sbostic register struct udadevice *udaddr; 26232523Sbostic register struct mscp_info *mi; 26332523Sbostic int timeout, tries; 2644743Swnj 26532523Sbostic #ifdef VAX750 26632523Sbostic /* 26732523Sbostic * The UDA50 wants to share BDPs on 750s, but not on 780s or 26832523Sbostic * 8600s. (730s have no BDPs anyway.) Toward this end, we 26932523Sbostic * here set the `keep bdp' flag in the per-driver information 27032523Sbostic * if this is a 750. (We just need to do it once, but it is 27132523Sbostic * easiest to do it now, for each UDA50.) 27232523Sbostic */ 27332523Sbostic if (cpu == VAX_750) 27432523Sbostic udadriver.ud_keepbdp = 1; 27532523Sbostic #endif 27617553Skarels 27732523Sbostic probeum = um; /* remember for udaslave() */ 2784743Swnj #ifdef lint 27932523Sbostic br = 0; cvec = br; br = cvec; udaintr(0); 2804743Swnj #endif 28132523Sbostic /* 28232523Sbostic * Set up the controller-specific generic MSCP driver info. 28332523Sbostic * Note that this should really be done in the (nonexistent) 28432523Sbostic * controller attach routine. 28532523Sbostic */ 28632523Sbostic sc = &uda_softc[ctlr]; 28732523Sbostic mi = &sc->sc_mi; 28832523Sbostic mi->mi_md = &udamscpdriver; 28932523Sbostic mi->mi_ctlr = um->um_ctlr; 29032523Sbostic mi->mi_tab = &um->um_tab; 29132523Sbostic mi->mi_ip = udaip[ctlr]; 29232523Sbostic mi->mi_cmd.mri_size = NCMD; 29332523Sbostic mi->mi_cmd.mri_desc = uda[ctlr].uda_ca.ca_cmddsc; 29432523Sbostic mi->mi_cmd.mri_ring = uda[ctlr].uda_cmd; 29532523Sbostic mi->mi_rsp.mri_size = NRSP; 29632523Sbostic mi->mi_rsp.mri_desc = uda[ctlr].uda_ca.ca_rspdsc; 29732523Sbostic mi->mi_rsp.mri_ring = uda[ctlr].uda_rsp; 29832523Sbostic mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; 29932523Sbostic 30032523Sbostic /* 30132523Sbostic * More controller specific variables. Again, this should 30232523Sbostic * be in the controller attach routine. 30332523Sbostic */ 30432523Sbostic if (udaburst[ctlr] == 0) 30532523Sbostic udaburst[ctlr] = DEFAULT_BURST; 30632523Sbostic 30732523Sbostic /* 30832523Sbostic * Get an interrupt vector. Note that even if the controller 30932523Sbostic * does not respond, we keep the vector. This is not a serious 31032523Sbostic * problem; but it would be easily fixed if we had a controller 31132523Sbostic * attach routine. Sigh. 31232523Sbostic */ 31332523Sbostic sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 31417553Skarels udaddr = (struct udadevice *) reg; 31517553Skarels 31632523Sbostic /* 31732523Sbostic * Initialise the controller (partially). The UDA50 programmer's 31832523Sbostic * manual states that if initialisation fails, it should be retried 31932523Sbostic * at least once, but after a second failure the port should be 32032523Sbostic * considered `down'; it also mentions that the controller should 32132523Sbostic * initialise within ten seconds. Or so I hear; I have not seen 32232523Sbostic * this manual myself. 32332523Sbostic */ 32432523Sbostic tries = 0; 32532523Sbostic again: 32632523Sbostic udaddr->udaip = 0; /* start initialisation */ 32732523Sbostic timeout = todr() + 1000; /* timeout in 10 seconds */ 32832523Sbostic while ((udaddr->udasa & UDA_STEP1) == 0) 32932523Sbostic if (todr() > timeout) 33032523Sbostic goto bad; 33132523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 33232523Sbostic (sc->sc_ivec >> 2); 33332523Sbostic while ((udaddr->udasa & UDA_STEP2) == 0) 33432523Sbostic if (todr() > timeout) 33532523Sbostic goto bad; 33632523Sbostic 33732523Sbostic /* should have interrupted by now */ 33832523Sbostic #ifdef VAX630 33932523Sbostic if (cpu == VAX_630) 34032523Sbostic br = 0x15; /* screwy interrupt structure */ 34127254Skridle #endif 34232523Sbostic return (sizeof (struct udadevice)); 34332523Sbostic bad: 34432523Sbostic if (++tries < 2) 34532523Sbostic goto again; 34632523Sbostic return (0); 3474743Swnj } 3484743Swnj 34932523Sbostic /* 35032523Sbostic * Find a slave. We allow wildcard slave numbers (something autoconf 35132523Sbostic * is not really prepared to deal with); and we need to know the 35232523Sbostic * controller number to talk to the UDA. For the latter, we keep 35332523Sbostic * track of the last controller probed, since a controller probe 35432523Sbostic * immediately precedes all slave probes for that controller. For the 35532523Sbostic * former, we simply put the unit number into ui->ui_slave after we 35632523Sbostic * have found one. 35732523Sbostic * 35832523Sbostic * Note that by the time udaslave is called, the interrupt vector 35932523Sbostic * for the UDA50 has been set up (so that udaunconf() will be called). 36032523Sbostic */ 36132523Sbostic udaslave(ui, reg) 36232523Sbostic register struct uba_device *ui; 3634743Swnj caddr_t reg; 3644743Swnj { 36532523Sbostic register struct uba_ctlr *um = probeum; 36632523Sbostic register struct mscp *mp; 36732523Sbostic register struct uda_softc *sc; 36832523Sbostic register struct ra_info *ra; 36933443Skarels int next = 0, timeout, tries, i; 37017553Skarels 37132523Sbostic #ifdef lint 37232523Sbostic i = 0; i = i; 37332523Sbostic #endif 37432523Sbostic /* 37532523Sbostic * Make sure the controller is fully initialised, by waiting 37632523Sbostic * for it if necessary. 37732523Sbostic */ 37832523Sbostic sc = &uda_softc[um->um_ctlr]; 37932523Sbostic if (sc->sc_state == ST_RUN) 38032523Sbostic goto findunit; 38132523Sbostic tries = 0; 38232523Sbostic again: 38332523Sbostic if (udainit(ui->ui_ctlr)) 38432523Sbostic return (0); 38532523Sbostic timeout = todr() + 1000; /* 10 seconds */ 38632523Sbostic while (todr() < timeout) 38732523Sbostic if (sc->sc_state == ST_RUN) /* made it */ 38832523Sbostic goto findunit; 38932523Sbostic if (++tries < 2) 39032523Sbostic goto again; 39132523Sbostic printf("uda%d: controller hung\n", um->um_ctlr); 39232523Sbostic return (0); 39317553Skarels 39432523Sbostic /* 39532523Sbostic * The controller is all set; go find the unit. Grab an 39632523Sbostic * MSCP packet and send out a Get Unit Status command, with 39732523Sbostic * the `next unit' modifier if we are looking for a generic 39832523Sbostic * unit. We set the `in slave' flag so that udaunconf() 39932523Sbostic * knows to copy the response to `udaslavereply'. 40032523Sbostic */ 40132523Sbostic findunit: 40232523Sbostic udaslavereply.mscp_opcode = 0; 40332523Sbostic sc->sc_flags |= SC_INSLAVE; 40432523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) 40532523Sbostic panic("udaslave"); /* `cannot happen' */ 40632523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 40732523Sbostic if (ui->ui_slave == '?') { 40832523Sbostic mp->mscp_unit = next; 40932523Sbostic mp->mscp_modifier = M_GUM_NEXTUNIT; 41032523Sbostic } else { 41132523Sbostic mp->mscp_unit = ui->ui_slave; 41232523Sbostic mp->mscp_modifier = 0; 41317553Skarels } 41432523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 41532523Sbostic i = ((struct udadevice *) reg)->udaip; /* initiate polling */ 41632523Sbostic mp = &udaslavereply; 41732523Sbostic timeout = todr() + 1000; 41832523Sbostic while (todr() < timeout) 41932523Sbostic if (mp->mscp_opcode) 42032523Sbostic goto gotit; 42132523Sbostic printf("uda%d: no response to Get Unit Status request\n", 42232523Sbostic um->um_ctlr); 42332523Sbostic sc->sc_flags &= ~SC_INSLAVE; 42432523Sbostic return (0); 42532523Sbostic 42632523Sbostic gotit: 42732523Sbostic sc->sc_flags &= ~SC_INSLAVE; 42832523Sbostic 42932523Sbostic /* 43032523Sbostic * Got a slave response. If the unit is there, use it. 43132523Sbostic */ 43232523Sbostic switch (mp->mscp_status & M_ST_MASK) { 43332523Sbostic 43432523Sbostic case M_ST_SUCCESS: /* worked */ 43532523Sbostic case M_ST_AVAILABLE: /* found another drive */ 43632523Sbostic break; /* use it */ 43732523Sbostic 43832523Sbostic case M_ST_OFFLINE: 43932523Sbostic /* 44032523Sbostic * Figure out why it is off line. It may be because 44132523Sbostic * it is nonexistent, or because it is spun down, or 44232523Sbostic * for some other reason. 44332523Sbostic */ 44432523Sbostic switch (mp->mscp_status & ~M_ST_MASK) { 44532523Sbostic 44632523Sbostic case M_OFFLINE_UNKNOWN: 44732523Sbostic /* 44832523Sbostic * No such drive, and there are none with 44932523Sbostic * higher unit numbers either, if we are 45032523Sbostic * using M_GUM_NEXTUNIT. 45132523Sbostic */ 45232523Sbostic return (0); 45332523Sbostic 45432523Sbostic case M_OFFLINE_UNMOUNTED: 45532523Sbostic /* 45632523Sbostic * The drive is not spun up. Use it anyway. 45732523Sbostic * 45832523Sbostic * N.B.: this seems to be a common occurrance 45932523Sbostic * after a power failure. The first attempt 46032523Sbostic * to bring it on line seems to spin it up 46132523Sbostic * (and thus takes several minutes). Perhaps 46232523Sbostic * we should note here that the on-line may 46332523Sbostic * take longer than usual. 46432523Sbostic */ 46532523Sbostic break; 46632523Sbostic 46732523Sbostic default: 46832523Sbostic /* 46932523Sbostic * In service, or something else equally unusable. 47032523Sbostic */ 47132523Sbostic printf("uda%d: unit %d off line: ", um->um_ctlr, 47232523Sbostic mp->mscp_unit); 47332523Sbostic mscp_printevent(mp); 47432523Sbostic goto try_another; 47532523Sbostic } 47632523Sbostic break; 47732523Sbostic 47832523Sbostic default: 47932523Sbostic printf("uda%d: unable to get unit status: ", um->um_ctlr); 48032523Sbostic mscp_printevent(mp); 48132523Sbostic return (0); 48217553Skarels } 48332523Sbostic 48432523Sbostic /* 48532523Sbostic * Does this ever happen? What (if anything) does it mean? 48632523Sbostic */ 48732523Sbostic if (mp->mscp_unit < next) { 48832523Sbostic printf("uda%d: unit %d, next %d\n", 48932523Sbostic um->um_ctlr, mp->mscp_unit, next); 49032523Sbostic return (0); 49117553Skarels } 49232523Sbostic 49332523Sbostic if (mp->mscp_unit >= MAXUNIT) { 49432523Sbostic printf("uda%d: cannot handle unit number %d (max is %d)\n", 49532523Sbostic um->um_ctlr, mp->mscp_unit, MAXUNIT - 1); 49632523Sbostic return (0); 49732523Sbostic } 49832523Sbostic 49932523Sbostic /* 50032523Sbostic * See if we already handle this drive. 50132523Sbostic * (Only likely if ui->ui_slave=='?'.) 50232523Sbostic */ 50332523Sbostic if (udaip[um->um_ctlr][mp->mscp_unit] != NULL) { 50432523Sbostic try_another: 50532523Sbostic if (ui->ui_slave != '?') 50632523Sbostic return (0); 50732523Sbostic next = mp->mscp_unit + 1; 50832523Sbostic goto findunit; 50932523Sbostic } 51032523Sbostic 51132523Sbostic /* 51232523Sbostic * Voila! 51332523Sbostic */ 51432523Sbostic uda_rasave(ui->ui_unit, mp, 0); 51532523Sbostic ui->ui_flags = 0; /* not on line, nor anything else */ 51632523Sbostic ui->ui_slave = mp->mscp_unit; 51732523Sbostic return (1); 5184743Swnj } 5194743Swnj 52032523Sbostic /* 52132523Sbostic * Attach a found slave. Make sure the watchdog timer is running. 52232523Sbostic * If this disk is being profiled, fill in the `mspw' value (used by 52332523Sbostic * what?). Set up the inverting pointer, and attempt to bring the 52432523Sbostic * drive on line and read its label. 52532523Sbostic */ 52632523Sbostic udaattach(ui) 5274743Swnj register struct uba_device *ui; 5284743Swnj { 52932523Sbostic register int unit = ui->ui_unit; 53032523Sbostic 53132523Sbostic if (udawstart == 0) { 53232523Sbostic timeout(udawatch, (caddr_t) 0, hz); 53332523Sbostic udawstart++; 53432523Sbostic } 53512443Ssam if (ui->ui_dk >= 0) 536*33444Sbostic 537*33444Sbostic /* 538*33444Sbostic * Floppies cannot be brought on line unless there is 539*33444Sbostic * a disk in the drive. Since an ONLINE while cold 540*33444Sbostic * takes ten seconds to fail, and (when notyet becomes now) 541*33444Sbostic * no sensible person will swap to one, we just 542*33444Sbostic * defer the ONLINE until someone tries to use the drive. 543*33444Sbostic * 544*33444Sbostic * THIS ASSUMES THAT DRIVE TYPES ?X? ARE FLOPPIES 545*33444Sbostic */ 546*33444Sbostic if (MSCP_MID_ECH(1, ra_info[unit].ra_mediaid) == 'X' - '@') { 547*33444Sbostic printf("ra%d: floppy\n", unit); 548*33444Sbostic return; 549*33444Sbostic } 55032523Sbostic dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ 55132523Sbostic udaip[ui->ui_ctlr][ui->ui_slave] = ui; 55233195Sbostic 55333195Sbostic /* 55433195Sbostic * RX50s cannot be brought on line unless there is 55533195Sbostic * a floppy in the drive. Since an ONLINE while cold 55633195Sbostic * takes ten seconds to fail, and (when notyet becomes now) 55733195Sbostic * no sensible person will swap to an RX50, we just 55833195Sbostic * defer the ONLINE until someone tries to use the drive. 55933195Sbostic */ 56033195Sbostic if (ra_info[unit].ra_type == RA_TYPE_RX50) { 56133195Sbostic printf("ra%d: rx50\n", unit); 56233195Sbostic return; 56333195Sbostic } 56432523Sbostic if (uda_rainit(ui, 0)) 56532574Skarels printf("ra%d: offline\n", unit); 56632523Sbostic else { 56732523Sbostic printf("ra%d: %s\n", unit, udalabel[unit].d_typename); 56832523Sbostic #ifdef notyet 56932523Sbostic addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]); 57026295Skarels #endif 57130536Skarels } 57232523Sbostic } 57332523Sbostic 57432523Sbostic /* 57532523Sbostic * Initialise a UDA50. Return true iff something goes wrong. 57632523Sbostic */ 57732523Sbostic udainit(ctlr) 57832523Sbostic int ctlr; 57932523Sbostic { 58032523Sbostic register struct uda_softc *sc; 58132523Sbostic register struct udadevice *udaddr; 58232523Sbostic struct uba_ctlr *um; 58332523Sbostic int timo, ubinfo; 58432523Sbostic 58532523Sbostic sc = &uda_softc[ctlr]; 58632523Sbostic um = udaminfo[ctlr]; 58732523Sbostic if ((sc->sc_flags & SC_MAPPED) == 0) { 58832523Sbostic /* 58932523Sbostic * Map the communication area and command and 59032523Sbostic * response packets into Unibus space. 59132523Sbostic */ 59232523Sbostic ubinfo = uballoc(um->um_ubanum, (caddr_t) &uda[ctlr], 59332523Sbostic sizeof (struct uda), UBA_CANTWAIT); 59432523Sbostic if (ubinfo == 0) { 59532523Sbostic printf("uda%d: uballoc map failed\n", ctlr); 59632523Sbostic return (-1); 59732523Sbostic } 59832523Sbostic sc->sc_uda = (struct uda *) (ubinfo & 0x3ffff); 59932523Sbostic sc->sc_flags |= SC_MAPPED; 60032523Sbostic } 60132523Sbostic 60230536Skarels /* 60332523Sbostic * While we are thinking about it, reset the next command 60432523Sbostic * and response indicies. 60530536Skarels */ 60632523Sbostic sc->sc_mi.mi_cmd.mri_next = 0; 60732523Sbostic sc->sc_mi.mi_rsp.mri_next = 0; 60832523Sbostic 60932523Sbostic /* 61032523Sbostic * Start up the hardware initialisation sequence. 61132523Sbostic */ 61232523Sbostic #define STEP0MASK (UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \ 61332523Sbostic UDA_STEP1 | UDA_NV) 61432523Sbostic 61532523Sbostic sc->sc_state = ST_IDLE; /* in case init fails */ 616*33444Sbostic udaddr = (struct udadevice *)um->um_addr; 61732523Sbostic udaddr->udaip = 0; 61832523Sbostic timo = todr() + 1000; 61932523Sbostic while ((udaddr->udasa & STEP0MASK) == 0) { 62032523Sbostic if (todr() > timo) { 62132523Sbostic printf("uda%d: timeout during init\n", ctlr); 62232523Sbostic return (-1); 62332523Sbostic } 62432523Sbostic } 62532523Sbostic if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) { 62632523Sbostic printf("uda%d: init failed, sa=%b\n", ctlr, 62732523Sbostic udaddr->udasa, udasr_bits); 628*33444Sbostic udasaerror(um, 0); 62932523Sbostic return (-1); 63032523Sbostic } 63132523Sbostic 63232523Sbostic /* 63332523Sbostic * Success! Record new state, and start step 1 initialisation. 63432523Sbostic * The rest is done in the interrupt handler. 63532523Sbostic */ 63632523Sbostic sc->sc_state = ST_STEP1; 63732523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 63832523Sbostic (sc->sc_ivec >> 2); 63932523Sbostic return (0); 6404743Swnj } 6414743Swnj 6424743Swnj /* 64332523Sbostic * Open a drive. 6444743Swnj */ 64532523Sbostic /*ARGSUSED*/ 64632523Sbostic udaopen(dev, flag, fmt) 6474743Swnj dev_t dev; 64830773Skarels int flag, fmt; 6494743Swnj { 65032523Sbostic register int unit; 6514743Swnj register struct uba_device *ui; 6524743Swnj register struct uda_softc *sc; 65330536Skarels register struct disklabel *lp; 65430536Skarels register struct partition *pp; 65530916Skarels register struct ra_info *ra; 65632523Sbostic int s, i, part, mask, error = 0; 65730536Skarels daddr_t start, end; 65830536Skarels 65932523Sbostic /* 66032523Sbostic * Make sure this is a reasonable open request. 66132523Sbostic */ 66232523Sbostic unit = udaunit(dev); 66332523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0) 6648576Sroot return (ENXIO); 66532523Sbostic 66632523Sbostic /* 66732523Sbostic * Make sure the controller is running, by (re)initialising it if 66832523Sbostic * necessary. 66932523Sbostic */ 6704743Swnj sc = &uda_softc[ui->ui_ctlr]; 6715434Sroot s = spl5(); 67232523Sbostic if (sc->sc_state != ST_RUN) { 67332523Sbostic if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) { 67432523Sbostic splx(s); 6758576Sroot return (EIO); 67617553Skarels } 67732523Sbostic /* 67832523Sbostic * In case it does not come up, make sure we will be 67932523Sbostic * restarted in 10 seconds. This corresponds to the 68032523Sbostic * 10 second timeouts in udaprobe() and udaslave(). 68132523Sbostic */ 68232523Sbostic sc->sc_flags |= SC_DOWAKE; 68332523Sbostic timeout(wakeup, (caddr_t) sc, 10 * hz); 68432523Sbostic sleep((caddr_t) sc, PRIBIO); 68532523Sbostic if (sc->sc_state != ST_RUN) { 68632523Sbostic splx(s); 68732523Sbostic printf("uda%d: controller hung\n", ui->ui_ctlr); 68832523Sbostic return (EIO); 68932523Sbostic } 69032523Sbostic untimeout(wakeup, (caddr_t) sc); 6914743Swnj } 69232523Sbostic 69332523Sbostic /* 69432523Sbostic * Wait for the state to settle 69532523Sbostic */ 69632523Sbostic ra = &ra_info[unit]; 69732523Sbostic while (ra->ra_state != OPEN && ra->ra_state != OPENRAW && 69832523Sbostic ra->ra_state != CLOSED) 69932523Sbostic sleep((caddr_t)ra, PZERO + 1); 70032523Sbostic 70132523Sbostic /* 70232523Sbostic * If not on line, or we are not sure of the label, reinitialise 70332523Sbostic * the drive. 70432523Sbostic */ 70532523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0 || 70632523Sbostic (ra->ra_state != OPEN && ra->ra_state != OPENRAW)) 70732523Sbostic error = uda_rainit(ui, flag); 70830916Skarels splx(s); 70932523Sbostic if (error) 71032523Sbostic return (error); 71130536Skarels 71232523Sbostic part = udapart(dev); 71332523Sbostic lp = &udalabel[unit]; 71430536Skarels if (part >= lp->d_npartitions) 71530536Skarels return (ENXIO); 71630536Skarels /* 71732523Sbostic * Warn if a partition is opened that overlaps another 71832523Sbostic * already open, unless either is the `raw' partition 71932523Sbostic * (whole disk). 72030536Skarels */ 72132523Sbostic #define RAWPART 2 /* 'c' partition */ /* XXX */ 72232523Sbostic mask = 1 << part; 72332523Sbostic if ((ra->ra_openpart & mask) == 0 && part != RAWPART) { 72430536Skarels pp = &lp->d_partitions[part]; 72530536Skarels start = pp->p_offset; 72630536Skarels end = pp->p_offset + pp->p_size; 72732523Sbostic for (pp = lp->d_partitions, i = 0; 72832523Sbostic i < lp->d_npartitions; pp++, i++) { 72930536Skarels if (pp->p_offset + pp->p_size <= start || 73032523Sbostic pp->p_offset >= end || i == RAWPART) 73130536Skarels continue; 73232523Sbostic if (ra->ra_openpart & (1 << i)) 73330536Skarels log(LOG_WARNING, 73430536Skarels "ra%d%c: overlaps open partition (%c)\n", 73532523Sbostic unit, part + 'a', i + 'a'); 73617553Skarels } 73717553Skarels } 73830773Skarels switch (fmt) { 73930773Skarels case S_IFCHR: 74032523Sbostic ra->ra_copenpart |= mask; 74130773Skarels break; 74230773Skarels case S_IFBLK: 74332523Sbostic ra->ra_bopenpart |= mask; 74430773Skarels break; 74530773Skarels } 74632523Sbostic ra->ra_openpart |= mask; 7478576Sroot return (0); 7484743Swnj } 7494743Swnj 750*33444Sbostic /* ARGSUSED */ 75133443Skarels /*ARGSUSED*/ 75232523Sbostic udaclose(dev, flags, fmt) 75330536Skarels dev_t dev; 75430773Skarels int flags, fmt; 75530536Skarels { 75632523Sbostic register int unit = udaunit(dev); 75730773Skarels register struct ra_info *ra = &ra_info[unit]; 75832523Sbostic int s, mask = (1 << udapart(dev)); 75930536Skarels 76030773Skarels switch (fmt) { 76130773Skarels case S_IFCHR: 76232523Sbostic ra->ra_copenpart &= ~mask; 76330773Skarels break; 76430773Skarels case S_IFBLK: 76532523Sbostic ra->ra_bopenpart &= ~mask; 76630773Skarels break; 76730773Skarels } 76832523Sbostic ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; 76932523Sbostic 77030536Skarels /* 77132523Sbostic * Should wait for I/O to complete on this partition even if 77232523Sbostic * others are open, but wait for work on blkflush(). 77330536Skarels */ 77432523Sbostic if (ra->ra_openpart == 0) { 77530536Skarels s = spl5(); 77632523Sbostic while (udautab[unit].b_actf) 77732523Sbostic sleep((caddr_t)&udautab[unit], PZERO - 1); 77830536Skarels splx(s); 77932523Sbostic ra->ra_state = CLOSED; 78033443Skarels ra->ra_wlabel = 0; 78130536Skarels } 78230773Skarels return (0); 78330536Skarels } 78430536Skarels 7854743Swnj /* 78632523Sbostic * Initialise a drive. If it is not already, bring it on line, 78732523Sbostic * and set a timeout on it in case it fails to respond. 78832523Sbostic * When on line, read in the pack label. 7894743Swnj */ 79032523Sbostic uda_rainit(ui, flags) 79130536Skarels register struct uba_device *ui; 79232523Sbostic int flags; 79330536Skarels { 79432523Sbostic register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; 79530536Skarels register struct mscp *mp; 79632523Sbostic register int unit = ui->ui_unit; 79732523Sbostic register struct ra_info *ra; 79830773Skarels char *msg, *readdisklabel(); 79932523Sbostic int s, i, udastrategy(); 80030536Skarels extern int cold; 80130536Skarels 80232523Sbostic ra = &ra_info[unit]; 80332523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 80432523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); 80532523Sbostic mp->mscp_opcode = M_OP_ONLINE; 80632523Sbostic mp->mscp_unit = ui->ui_slave; 80732523Sbostic mp->mscp_cmdref = (long)&ui->ui_flags; 80832523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 80932523Sbostic ra->ra_state = WANTOPEN; 81032523Sbostic if (!cold) 81132523Sbostic s = spl5(); 81232523Sbostic i = ((struct udadevice *)ui->ui_addr)->udaip; 81330536Skarels 81430916Skarels if (cold) { 81532523Sbostic i = todr() + 1000; 81632523Sbostic while ((ui->ui_flags & UNIT_ONLINE) == 0) 81732523Sbostic if (todr() > i) 81832523Sbostic break; 81930916Skarels } else { 82032523Sbostic timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); 82132523Sbostic sleep((caddr_t)&ui->ui_flags, PSWP + 1); 82232523Sbostic splx(s); 82332523Sbostic untimeout(wakeup, (caddr_t)&ui->ui_flags); 82430916Skarels } 82532523Sbostic if (ra->ra_state != OPENRAW) { 82632523Sbostic ra->ra_state = CLOSED; 82732523Sbostic wakeup((caddr_t)ra); 82830916Skarels return (EIO); 82930916Skarels } 83030536Skarels } 83130536Skarels 83232523Sbostic lp = &udalabel[unit]; 83330916Skarels lp->d_secsize = DEV_BSIZE; 83432523Sbostic lp->d_secperunit = ra->ra_dsize; 83530916Skarels 83630536Skarels if (flags & O_NDELAY) 83730536Skarels return (0); 83832523Sbostic ra->ra_state = RDLABEL; 83930536Skarels /* 84032523Sbostic * Set up default sizes until we have the label, or longer 84132523Sbostic * if there is none. Set secpercyl, as readdisklabel wants 84232523Sbostic * to compute b_cylin (although we do not need it). 84330536Skarels */ 84430916Skarels lp->d_secpercyl = 1; 84530536Skarels lp->d_npartitions = 1; 84630536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 84730536Skarels lp->d_partitions[0].p_offset = 0; 84832523Sbostic 84930536Skarels /* 85030536Skarels * Read pack label. 85130536Skarels */ 85232523Sbostic if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp)) != NULL) { 85330916Skarels log(LOG_ERR, "ra%d: %s\n", unit, msg); 85430536Skarels #ifdef COMPAT_42 85532523Sbostic if (udamaptype(unit, lp)) 85632523Sbostic ra->ra_state = OPEN; 85730536Skarels else 85832523Sbostic ra->ra_state = OPENRAW; 85931022Skarels #else 86032523Sbostic ra->ra_state = OPENRAW; 86132523Sbostic /* uda_makefakelabel(ra, lp); */ 86230536Skarels #endif 86330773Skarels } else 86432523Sbostic ra->ra_state = OPEN; 86530916Skarels wakeup((caddr_t)ra); 86630916Skarels return (0); 86730536Skarels } 86830536Skarels 86932523Sbostic /* 87032523Sbostic * Copy the geometry information for the given ra from a 87132523Sbostic * GET UNIT STATUS response. If check, see if it changed. 87232523Sbostic */ 87332523Sbostic uda_rasave(unit, mp, check) 87432523Sbostic int unit; 87532523Sbostic register struct mscp *mp; 87632523Sbostic int check; 87732523Sbostic { 87832523Sbostic register struct ra_info *ra = &ra_info[unit]; 87932523Sbostic 880*33444Sbostic if (check && ra->ra_type != mp->mscp_guse.guse_mediaid) { 88133443Skarels printf("ra%d: changed types! was %d now %d\n", unit, 882*33444Sbostic ra->ra_type, mp->mscp_guse.guse_mediaid); 88332523Sbostic ra->ra_state = CLOSED; /* ??? */ 88432523Sbostic } 885*33444Sbostic /* ra->ra_type = mp->mscp_guse.guse_drivetype; */ 88632523Sbostic ra->ra_mediaid = mp->mscp_guse.guse_mediaid; 88732523Sbostic ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt; 88832523Sbostic ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group; 88932523Sbostic ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc; 89032523Sbostic ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc; 89132523Sbostic /* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */ 89232523Sbostic #ifdef notyet 89332523Sbostic ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize; 89432523Sbostic ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt; 89532523Sbostic ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct; 89632523Sbostic #endif 89732523Sbostic } 89832523Sbostic 89932523Sbostic /* 90032523Sbostic * Queue a transfer request, and if possible, hand it to the controller. 90132523Sbostic * 90232523Sbostic * This routine is broken into two so that the internal version 90332523Sbostic * udastrat1() can be called by the (nonexistent, as yet) bad block 90432523Sbostic * revectoring routine. 90532523Sbostic */ 90632523Sbostic udastrategy(bp) 9074743Swnj register struct buf *bp; 9084743Swnj { 90932523Sbostic register int unit; 9104743Swnj register struct uba_device *ui; 91132523Sbostic register struct ra_info *ra; 91232523Sbostic struct partition *pp; 91332523Sbostic int p; 9144743Swnj daddr_t sz, maxsz; 9154743Swnj 91632523Sbostic /* 91732523Sbostic * Make sure this is a reasonable drive to use. 91832523Sbostic */ 91932523Sbostic if ((unit = udaunit(bp->b_dev)) >= NRA || 92032523Sbostic (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || 92132523Sbostic (ra = &ra_info[unit])->ra_state == CLOSED) { 92224742Sbloom bp->b_error = ENXIO; 9234743Swnj goto bad; 92424742Sbloom } 92532523Sbostic 92632523Sbostic /* 92732523Sbostic * If drive is open `raw' or reading label, let it at it. 92832523Sbostic */ 92932523Sbostic if (ra->ra_state < OPEN) { 93032523Sbostic udastrat1(bp); 93132523Sbostic return; 93224742Sbloom } 93332523Sbostic p = udapart(bp->b_dev); 93433443Skarels if ((ra->ra_openpart & (1 << p)) == 0) { 93533443Skarels bp->b_error = ENODEV; 93633443Skarels goto bad; 93733443Skarels } 93832523Sbostic 93932523Sbostic /* 94032523Sbostic * Determine the size of the transfer, and make sure it is 94132523Sbostic * within the boundaries of the partition. 94232523Sbostic */ 94332523Sbostic pp = &udalabel[unit].d_partitions[p]; 94432523Sbostic maxsz = pp->p_size; 94532523Sbostic if (pp->p_offset + pp->p_size > ra->ra_dsize) 94632523Sbostic maxsz = ra->ra_dsize - pp->p_offset; 94730536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 94833443Skarels if (bp->b_blkno + pp->p_offset <= LABELSECTOR && 94933443Skarels #if LABELSECTOR != 0 95033443Skarels bp->b_blkno + pp->p_offset + sz > LABELSECTOR && 95133443Skarels #endif 95233443Skarels (bp->b_flags & B_READ) == 0 && ra->ra_wlabel == 0) { 95333443Skarels bp->b_error = EROFS; 95433443Skarels goto bad; 95533443Skarels } 95630536Skarels if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 95732523Sbostic /* if exactly at end of disk, return an EOF */ 95824787Skarels if (bp->b_blkno == maxsz) { 95924787Skarels bp->b_resid = bp->b_bcount; 96032523Sbostic biodone(bp); 96132523Sbostic return; 96224787Skarels } 96332523Sbostic /* or truncate if part of it fits */ 96430536Skarels sz = maxsz - bp->b_blkno; 96530536Skarels if (sz <= 0) { 96632523Sbostic bp->b_error = EINVAL; /* or hang it up */ 96730536Skarels goto bad; 96830536Skarels } 96930536Skarels bp->b_bcount = sz << DEV_BSHIFT; 97024742Sbloom } 97132523Sbostic udastrat1(bp); 97232523Sbostic return; 97332523Sbostic bad: 97432523Sbostic bp->b_flags |= B_ERROR; 97532523Sbostic biodone(bp); 97632523Sbostic } 97732523Sbostic 97832523Sbostic /* 97932523Sbostic * Work routine for udastrategy. 98032523Sbostic */ 98132523Sbostic udastrat1(bp) 98232523Sbostic register struct buf *bp; 98332523Sbostic { 98432523Sbostic register int unit = udaunit(bp->b_dev); 98532523Sbostic register struct uba_ctlr *um; 98632523Sbostic register struct buf *dp; 98732523Sbostic struct uba_device *ui; 98832523Sbostic int s = spl5(); 98932523Sbostic 9904743Swnj /* 99132523Sbostic * Append the buffer to the drive queue, and if it is not 99232523Sbostic * already there, the drive to the controller queue. (However, 99332523Sbostic * if the drive queue is marked to be requeued, we must be 99432523Sbostic * awaiting an on line or get unit status command; in this 99532523Sbostic * case, leave it off the controller queue.) 9964743Swnj */ 99732523Sbostic um = (ui = udadinfo[unit])->ui_mi; 99832523Sbostic dp = &udautab[unit]; 99932523Sbostic APPEND(bp, dp, av_forw); 100032523Sbostic if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { 100132523Sbostic APPEND(dp, &um->um_tab, b_forw); 100232523Sbostic dp->b_active++; 100332523Sbostic } 100432523Sbostic 10054743Swnj /* 100632523Sbostic * Start activity on the controller. Note that unlike other 100732523Sbostic * Unibus drivers, we must always do this, not just when the 100832523Sbostic * controller is not active. 10094743Swnj */ 101032523Sbostic udastart(um); 10115434Sroot splx(s); 10124743Swnj } 10134743Swnj 101432523Sbostic /* 101532523Sbostic * Start up whatever transfers we can find. 101632523Sbostic * Note that udastart() must be called at spl5(). 101732523Sbostic */ 101832523Sbostic udastart(um) 10194743Swnj register struct uba_ctlr *um; 10204743Swnj { 102132523Sbostic register struct uda_softc *sc = &uda_softc[um->um_ctlr]; 10224743Swnj register struct buf *bp, *dp; 10234743Swnj register struct mscp *mp; 102432523Sbostic struct uba_device *ui; 10254743Swnj struct udadevice *udaddr; 102632523Sbostic struct partition *pp; 102732523Sbostic int i, sz; 10284743Swnj 102932523Sbostic #ifdef lint 103032523Sbostic i = 0; i = i; 103132523Sbostic #endif 103232523Sbostic /* 103332523Sbostic * If it is not running, try (again and again...) to initialise 103432523Sbostic * it. If it is currently initialising just ignore it for now. 103532523Sbostic */ 103632523Sbostic if (sc->sc_state != ST_RUN) { 103732523Sbostic if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr)) 103832523Sbostic printf("uda%d: still hung\n", um->um_ctlr); 103932523Sbostic return; 104032523Sbostic } 104132523Sbostic 104232523Sbostic /* 104332523Sbostic * If um_cmd is nonzero, this controller is on the Unibus 104432523Sbostic * resource wait queue. It will not help to try more requests; 104532523Sbostic * instead, when the Unibus unblocks and calls udadgo(), we 104632523Sbostic * will call udastart() again. 104732523Sbostic */ 104832523Sbostic if (um->um_cmd) 104932523Sbostic return; 105032523Sbostic 105132523Sbostic sc->sc_flags |= SC_INSTART; 105232523Sbostic udaddr = (struct udadevice *) um->um_addr; 105332523Sbostic 10544743Swnj loop: 105532523Sbostic /* 105632523Sbostic * Service the drive at the head of the queue. It may not 105732523Sbostic * need anything, in which case it might be shutting down 105832523Sbostic * in udaclose(). 105932523Sbostic */ 106032523Sbostic if ((dp = um->um_tab.b_actf) == NULL) 106132523Sbostic goto out; 10624743Swnj if ((bp = dp->b_actf) == NULL) { 10634743Swnj dp->b_active = 0; 10644743Swnj um->um_tab.b_actf = dp->b_forw; 106532523Sbostic if (ra_info[dp - udautab].ra_openpart == 0) 106632523Sbostic wakeup((caddr_t)dp); /* finish close protocol */ 106732523Sbostic goto loop; 10684743Swnj } 106932523Sbostic 107032523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 1071*33444Sbostic udasaerror(um, 1); 107232523Sbostic goto out; 10734743Swnj } 107432523Sbostic 107532523Sbostic /* 107632523Sbostic * Get an MSCP packet, then figure out what to do. If 107732523Sbostic * we cannot get a command packet, the command ring may 107832523Sbostic * be too small: We should have at least as many command 107932523Sbostic * packets as credits, for best performance. 108032523Sbostic */ 108132523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) { 108232523Sbostic if (sc->sc_mi.mi_credits > MSCP_MINCREDITS && 108332523Sbostic (sc->sc_flags & SC_GRIPED) == 0) { 108432523Sbostic log(LOG_NOTICE, "uda%d: command ring too small\n", 108532523Sbostic um->um_ctlr); 108632523Sbostic sc->sc_flags |= SC_GRIPED;/* complain only once */ 108717553Skarels } 108832523Sbostic goto out; 10894743Swnj } 10904743Swnj 109132523Sbostic /* 109232523Sbostic * Bring the drive on line if it is not already. Get its status 109332523Sbostic * if we do not already have it. Otherwise just start the transfer. 109432523Sbostic */ 109532523Sbostic ui = udadinfo[udaunit(bp->b_dev)]; 109632523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 109732523Sbostic mp->mscp_opcode = M_OP_ONLINE; 109832523Sbostic goto common; 10994743Swnj } 110032523Sbostic if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) { 110132523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 110232523Sbostic common: 110332523Sbostic if (ui->ui_flags & UNIT_REQUEUE) panic("udastart"); 110432523Sbostic /* 110532523Sbostic * Take the drive off the controller queue. When the 110632523Sbostic * command finishes, make sure the drive is requeued. 110732523Sbostic */ 110832523Sbostic um->um_tab.b_actf = dp->b_forw; 110932523Sbostic dp->b_active = 0; 111032523Sbostic ui->ui_flags |= UNIT_REQUEUE; 111132523Sbostic mp->mscp_unit = ui->ui_slave; 111232523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 111332523Sbostic sc->sc_flags |= SC_STARTPOLL; 111432523Sbostic #ifdef POLLSTATS 111532523Sbostic sc->sc_ncmd++; 111625653Skarels #endif 111732523Sbostic goto loop; 111817553Skarels } 111932523Sbostic 112032523Sbostic pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)]; 112132523Sbostic mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; 11224743Swnj mp->mscp_unit = ui->ui_slave; 112332523Sbostic mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset; 112430536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 112532523Sbostic mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ? 112632523Sbostic (pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount; 112732523Sbostic /* mscp_cmdref is filled in by mscp_go() */ 11284743Swnj 11294743Swnj /* 113032523Sbostic * Drop the packet pointer into the `command' field so udadgo() 113132523Sbostic * can tell what to start. If ubago returns 1, we can do another 113232523Sbostic * transfer. If not, um_cmd will still point at mp, so we will 113332523Sbostic * know that we are waiting for resources. 11344743Swnj */ 113532523Sbostic um->um_cmd = (int)mp; 113632523Sbostic if (ubago(ui)) 113732523Sbostic goto loop; 113832523Sbostic 113932523Sbostic /* 114032523Sbostic * All done, or blocked in ubago(). If we managed to 114132523Sbostic * issue some commands, start up the beast. 114232523Sbostic */ 114332523Sbostic out: 114432523Sbostic if (sc->sc_flags & SC_STARTPOLL) { 114532523Sbostic #ifdef POLLSTATS 114632523Sbostic udastats.cmd[sc->sc_ncmd]++; 114732523Sbostic sc->sc_ncmd = 0; 114832523Sbostic #endif 1149*33444Sbostic i = ((struct udadevice *)um->um_addr)->udaip; 11504743Swnj } 115132523Sbostic sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL); 115232523Sbostic } 115332523Sbostic 115432523Sbostic /* 115532523Sbostic * Start a transfer. 115632523Sbostic * 115732523Sbostic * If we are not called from within udastart(), we must have been 115832523Sbostic * blocked, so call udastart to do more requests (if any). If 115932523Sbostic * this calls us again immediately we will not recurse, because 116032523Sbostic * that time we will be in udastart(). Clever.... 116132523Sbostic */ 116232523Sbostic udadgo(um) 116332523Sbostic register struct uba_ctlr *um; 116432523Sbostic { 116532523Sbostic struct uda_softc *sc = &uda_softc[um->um_ctlr]; 116632523Sbostic struct mscp *mp = (struct mscp *)um->um_cmd; 116732523Sbostic 116832523Sbostic um->um_tab.b_active++; /* another transfer going */ 116932523Sbostic 11704743Swnj /* 117132523Sbostic * Fill in the MSCP packet and move the buffer to the 117232523Sbostic * I/O wait queue. Mark the controller as no longer on 117332523Sbostic * the resource queue, and remember to initiate polling. 11744743Swnj */ 117532523Sbostic mp->mscp_seq.seq_buffer = (um->um_ubinfo & 0x3ffff) | 117632523Sbostic (UBAI_BDP(um->um_ubinfo) << 24); 117732523Sbostic mscp_go(&sc->sc_mi, mp, um->um_ubinfo); 117832523Sbostic um->um_cmd = 0; 117932523Sbostic um->um_ubinfo = 0; /* tyke it awye */ 118032523Sbostic sc->sc_flags |= SC_STARTPOLL; 118132523Sbostic #ifdef POLLSTATS 118232523Sbostic sc->sc_ncmd++; 118332523Sbostic #endif 118432523Sbostic if ((sc->sc_flags & SC_INSTART) == 0) 118532523Sbostic udastart(um); 11864743Swnj } 11874743Swnj 118832523Sbostic udaiodone(mi, bp, info) 118932523Sbostic register struct mscp_info *mi; 119032523Sbostic struct buf *bp; 119132523Sbostic int info; 119232523Sbostic { 119332523Sbostic register struct uba_ctlr *um = udaminfo[mi->mi_ctlr]; 119432523Sbostic 119532523Sbostic um->um_ubinfo = info; 119632523Sbostic ubadone(um); 119732523Sbostic biodone(bp); 119832523Sbostic if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab) 119932523Sbostic ubarelse(um->um_ubanum, &um->um_bdp); 120032523Sbostic um->um_tab.b_active--; /* another transfer done */ 120132523Sbostic } 120232523Sbostic 1203*33444Sbostic static struct saerr { 1204*33444Sbostic int code; /* error code (including UDA_ERR) */ 1205*33444Sbostic char *desc; /* what it means: Efoo => foo error */ 1206*33444Sbostic } saerr[] = { 1207*33444Sbostic { 0100001, "Eunibus packet read" }, 1208*33444Sbostic { 0100002, "Eunibus packet write" }, 1209*33444Sbostic { 0100003, "EUDA ROM and RAM parity" }, 1210*33444Sbostic { 0100004, "EUDA RAM parity" }, 1211*33444Sbostic { 0100005, "EUDA ROM parity" }, 1212*33444Sbostic { 0100006, "Eunibus ring read" }, 1213*33444Sbostic { 0100007, "Eunibus ring write" }, 1214*33444Sbostic { 0100010, " unibus interrupt master failure" }, 1215*33444Sbostic { 0100011, "Ehost access timeout" }, 1216*33444Sbostic { 0100012, " host exceeded command limit" }, 1217*33444Sbostic { 0100013, " unibus bus master failure" }, 1218*33444Sbostic { 0100014, " DM XFC fatal error" }, 1219*33444Sbostic { 0100015, " hardware timeout of instruction loop" }, 1220*33444Sbostic { 0100016, " invalid virtual circuit id" }, 1221*33444Sbostic { 0100017, "Eunibus interrupt write" }, 1222*33444Sbostic { 0104000, "Efatal sequence" }, 1223*33444Sbostic { 0104040, " D proc ALU" }, 1224*33444Sbostic { 0104041, "ED proc control ROM parity" }, 1225*33444Sbostic { 0105102, "ED proc w/no BD#2 or RAM parity" }, 1226*33444Sbostic { 0105105, "ED proc RAM buffer" }, 1227*33444Sbostic { 0105152, "ED proc SDI" }, 1228*33444Sbostic { 0105153, "ED proc write mode wrap serdes" }, 1229*33444Sbostic { 0105154, "ED proc read mode serdes, RSGEN & ECC" }, 1230*33444Sbostic { 0106040, "EU proc ALU" }, 1231*33444Sbostic { 0106041, "EU proc control reg" }, 1232*33444Sbostic { 0106042, " U proc DFAIL/cntl ROM parity/BD #1 test CNT" }, 1233*33444Sbostic { 0106047, " U proc const PROM err w/D proc running SDI test" }, 1234*33444Sbostic { 0106055, " unexpected trap" }, 1235*33444Sbostic { 0106071, "EU proc const PROM" }, 1236*33444Sbostic { 0106072, "EU proc control ROM parity" }, 1237*33444Sbostic { 0106200, "Estep 1 data" }, 1238*33444Sbostic { 0107103, "EU proc RAM parity" }, 1239*33444Sbostic { 0107107, "EU proc RAM buffer" }, 1240*33444Sbostic { 0107115, " test count wrong (BD 12)" }, 1241*33444Sbostic { 0112300, "Estep 2" }, 1242*33444Sbostic { 0122240, "ENPR" }, 1243*33444Sbostic { 0122300, "Estep 3" }, 1244*33444Sbostic { 0142300, "Estep 4" }, 1245*33444Sbostic { 0, " unknown error code" } 1246*33444Sbostic }; 1247*33444Sbostic 12484743Swnj /* 1249*33444Sbostic * If the error bit was set in the controller status register, gripe, 1250*33444Sbostic * then (optionally) reset the controller and requeue pending transfers. 12514743Swnj */ 1252*33444Sbostic udasaerror(um, doreset) 125332523Sbostic register struct uba_ctlr *um; 1254*33444Sbostic int doreset; 12554743Swnj { 1256*33444Sbostic register int code = ((struct udadevice *)um->um_addr)->udasa; 1257*33444Sbostic register struct saerr *e; 125832523Sbostic 1259*33444Sbostic if ((code & UDA_ERR) == 0) 1260*33444Sbostic return; 1261*33444Sbostic for (e = saerr; e->code; e++) 1262*33444Sbostic if (e->code == code) 1263*33444Sbostic break; 1264*33444Sbostic printf("uda%d: controller error, sa=0%o (%s%s)\n", 1265*33444Sbostic um->um_ctlr, code, e->desc + 1, 1266*33444Sbostic *e->desc == 'E' ? " error" : ""); 1267*33444Sbostic if (doreset) { 1268*33444Sbostic mscp_requeue(&uda_softc[um->um_ctlr].sc_mi); 1269*33444Sbostic (void) udainit(um->um_ctlr); 1270*33444Sbostic } 127132523Sbostic } 127232523Sbostic 127332523Sbostic /* 127432523Sbostic * Interrupt routine. Depending on the state of the controller, 127532523Sbostic * continue initialisation, or acknowledge command and response 127632523Sbostic * interrupts, and process responses. 127732523Sbostic */ 127832523Sbostic udaintr(ctlr) 127932523Sbostic int ctlr; 128032523Sbostic { 128132523Sbostic register struct uba_ctlr *um = udaminfo[ctlr]; 128232523Sbostic register struct uda_softc *sc = &uda_softc[ctlr]; 1283*33444Sbostic register struct udadevice *udaddr = (struct udadevice *)um->um_addr; 128432523Sbostic register struct uda *ud; 128532523Sbostic register struct mscp *mp; 12864743Swnj register int i; 12874743Swnj 128827254Skridle #ifdef VAX630 128932523Sbostic (void) spl5(); /* Qbus interrupt protocol is odd */ 129027254Skridle #endif 129132523Sbostic sc->sc_wticks = 0; /* reset interrupt watchdog */ 129232523Sbostic 129332523Sbostic /* 129432523Sbostic * Combinations during steps 1, 2, and 3: STEPnMASK 129532523Sbostic * corresponds to which bits should be tested; 129632523Sbostic * STEPnGOOD corresponds to the pattern that should 129732523Sbostic * appear after the interrupt from STEPn initialisation. 129832523Sbostic * All steps test the bits in ALLSTEPS. 129932523Sbostic */ 130032523Sbostic #define ALLSTEPS (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1) 130132523Sbostic 130232523Sbostic #define STEP1MASK (ALLSTEPS | UDA_IE | UDA_NCNRMASK) 130332523Sbostic #define STEP1GOOD (UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2) 130432523Sbostic 130532523Sbostic #define STEP2MASK (ALLSTEPS | UDA_IE | UDA_IVECMASK) 130632523Sbostic #define STEP2GOOD (UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2)) 130732523Sbostic 130832523Sbostic #define STEP3MASK ALLSTEPS 130932523Sbostic #define STEP3GOOD UDA_STEP4 131032523Sbostic 13114743Swnj switch (sc->sc_state) { 131232523Sbostic 131332523Sbostic case ST_IDLE: 131432523Sbostic /* 131532523Sbostic * Ignore unsolicited interrupts. 131632523Sbostic */ 131732523Sbostic log(LOG_WARNING, "uda%d: stray intr\n", ctlr); 13184743Swnj return; 13194743Swnj 132032523Sbostic case ST_STEP1: 132132523Sbostic /* 132232523Sbostic * Begin step two initialisation. 132332523Sbostic */ 132432523Sbostic if ((udaddr->udasa & STEP1MASK) != STEP1GOOD) { 132532523Sbostic i = 1; 132632523Sbostic initfailed: 132732523Sbostic printf("uda%d: init step %d failed, sa=%b\n", 132832523Sbostic ctlr, i, udaddr->udasa, udasr_bits); 1329*33444Sbostic udasaerror(um, 0); 133032523Sbostic sc->sc_state = ST_IDLE; 133132523Sbostic if (sc->sc_flags & SC_DOWAKE) { 133232523Sbostic sc->sc_flags &= ~SC_DOWAKE; 1333*33444Sbostic wakeup((caddr_t)sc); 133432523Sbostic } 13354743Swnj return; 13364743Swnj } 1337*33444Sbostic udaddr->udasa = (int)&sc->sc_uda->uda_ca.ca_rspdsc[0] | 133832523Sbostic (cpu == VAX_780 || cpu == VAX_8600 ? UDA_PI : 0); 133932523Sbostic sc->sc_state = ST_STEP2; 13404743Swnj return; 13414743Swnj 134232523Sbostic case ST_STEP2: 134332523Sbostic /* 134432523Sbostic * Begin step 3 initialisation. 134532523Sbostic */ 134632523Sbostic if ((udaddr->udasa & STEP2MASK) != STEP2GOOD) { 134732523Sbostic i = 2; 134832523Sbostic goto initfailed; 13494743Swnj } 1350*33444Sbostic udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_rspdsc[0]) >> 16; 135132523Sbostic sc->sc_state = ST_STEP3; 13524743Swnj return; 13534743Swnj 135432523Sbostic case ST_STEP3: 135532523Sbostic /* 135632523Sbostic * Set controller characteristics (finish initialisation). 135732523Sbostic */ 135832523Sbostic if ((udaddr->udasa & STEP3MASK) != STEP3GOOD) { 135932523Sbostic i = 3; 136032523Sbostic goto initfailed; 13614743Swnj } 136232523Sbostic i = udaddr->udasa & 0xff; 136332523Sbostic if (i != sc->sc_micro) { 136432523Sbostic sc->sc_micro = i; 136532523Sbostic printf("uda%d: version %d model %d\n", 136632523Sbostic ctlr, i & 0xf, i >> 4); 136732523Sbostic } 136832523Sbostic 136917553Skarels /* 137032523Sbostic * Present the burst size, then remove it. Why this 137132523Sbostic * should be done this way, I have no idea. 137232523Sbostic * 137332523Sbostic * Note that this assumes udaburst[ctlr] > 0. 137417553Skarels */ 137532523Sbostic udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2; 13764743Swnj udaddr->udasa = UDA_GO; 137732523Sbostic printf("uda%d: DMA burst size set to %d\n", 137832523Sbostic ctlr, udaburst[ctlr]); 13794743Swnj 138032523Sbostic udainitds(ctlr); /* initialise data structures */ 138132523Sbostic 13824743Swnj /* 138332523Sbostic * Before we can get a command packet, we need some 138432523Sbostic * credits. Fake some up to keep mscp_getcp() happy, 138532523Sbostic * get a packet, and cancel all credits (the right 138632523Sbostic * number should come back in the response to the 138732523Sbostic * SCC packet). 13884743Swnj */ 138932523Sbostic sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1; 139032523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT); 139132523Sbostic if (mp == NULL) /* `cannot happen' */ 139232523Sbostic panic("udaintr"); 139332523Sbostic sc->sc_mi.mi_credits = 0; 139432523Sbostic mp->mscp_opcode = M_OP_SETCTLRC; 139532523Sbostic mp->mscp_unit = 0; 139632523Sbostic mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | 139732523Sbostic M_CF_THIS; 139832523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 139932523Sbostic i = udaddr->udaip; 140032523Sbostic sc->sc_state = ST_SETCHAR; 14014743Swnj return; 14024743Swnj 140332523Sbostic case ST_SETCHAR: 140432523Sbostic case ST_RUN: 140532523Sbostic /* 140632523Sbostic * Handle Set Ctlr Characteristics responses and operational 140732523Sbostic * responses (via mscp_dorsp). 140832523Sbostic */ 14094743Swnj break; 14104743Swnj 14114743Swnj default: 141232523Sbostic printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state); 141332523Sbostic panic("udastate"); 14144743Swnj } 14154743Swnj 141632523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 1417*33444Sbostic udasaerror(um, 1); 141832523Sbostic return; 14194743Swnj } 14204743Swnj 142132523Sbostic ud = &uda[ctlr]; 142232523Sbostic 14234743Swnj /* 142432523Sbostic * Handle buffer purge requests. 142532523Sbostic * I have never seen these to work usefully, thus the log(). 14264743Swnj */ 14274743Swnj if (ud->uda_ca.ca_bdp) { 142832523Sbostic log(LOG_DEBUG, "uda%d: purge bdp %d\n", 142932523Sbostic ctlr, ud->uda_ca.ca_bdp); 143026372Skarels UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); 14314743Swnj ud->uda_ca.ca_bdp = 0; 143232523Sbostic udaddr->udasa = 0; /* signal purge complete */ 14334743Swnj } 14344743Swnj 14354743Swnj /* 143632523Sbostic * Check for response and command ring transitions. 14374743Swnj */ 14384743Swnj if (ud->uda_ca.ca_rspint) { 14394743Swnj ud->uda_ca.ca_rspint = 0; 144032523Sbostic mscp_dorsp(&sc->sc_mi); 14414743Swnj } 14424743Swnj if (ud->uda_ca.ca_cmdint) { 14434743Swnj ud->uda_ca.ca_cmdint = 0; 144432523Sbostic MSCP_DOCMD(&sc->sc_mi); 14454743Swnj } 144632523Sbostic udastart(um); 14474743Swnj } 14484743Swnj 14494743Swnj /* 145032523Sbostic * Initialise the various data structures that control the UDA50. 145117553Skarels */ 145232523Sbostic udainitds(ctlr) 145332523Sbostic int ctlr; 145432523Sbostic { 145532523Sbostic register struct uda *ud = &uda[ctlr]; 145632523Sbostic register struct uda *uud = uda_softc[ctlr].sc_uda; 145732523Sbostic register struct mscp *mp; 145832523Sbostic register int i; 14594743Swnj 146032523Sbostic for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) { 146132523Sbostic ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | 146232523Sbostic (long)&uud->uda_rsp[i].mscp_cmdref; 146332523Sbostic mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i]; 146432523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 14654743Swnj } 146632523Sbostic for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) { 146732523Sbostic ud->uda_ca.ca_cmddsc[i] = MSCP_INT | 146832523Sbostic (long)&uud->uda_cmd[i].mscp_cmdref; 146932523Sbostic mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i]; 147032523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 147132523Sbostic } 14724743Swnj } 14734743Swnj 14744743Swnj /* 1475*33444Sbostic * Handle an error datagram. 14764743Swnj */ 147732523Sbostic udadgram(mi, mp) 147832523Sbostic struct mscp_info *mi; 147932523Sbostic struct mscp *mp; 14804743Swnj { 148117553Skarels 148232523Sbostic mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); 1483*33444Sbostic /* 1484*33444Sbostic * SDI status information bytes 10 and 11 are the microprocessor 1485*33444Sbostic * error code and front panel code respectively. These vary per 1486*33444Sbostic * drive type and are printed purely for field service information. 1487*33444Sbostic */ 1488*33444Sbostic if (mp->mscp_format == M_FM_SDI) 1489*33444Sbostic printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", 1490*33444Sbostic mp->mscp_erd.erd_sdistat[10], 1491*33444Sbostic mp->mscp_erd.erd_sdistat[11]); 149232523Sbostic } 149317553Skarels 149432523Sbostic /* 149532523Sbostic * The Set Controller Characteristics command finished. 149632523Sbostic * Record the new state of the controller. 149732523Sbostic */ 149832523Sbostic udactlrdone(mi, mp) 149932523Sbostic register struct mscp_info *mi; 150032523Sbostic struct mscp *mp; 150132523Sbostic { 150232523Sbostic register struct uda_softc *sc = &uda_softc[mi->mi_ctlr]; 150317553Skarels 150432523Sbostic if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) 150532523Sbostic sc->sc_state = ST_RUN; 150632523Sbostic else { 150732523Sbostic printf("uda%d: SETCTLRC failed: ", 150832523Sbostic mi->mi_ctlr, mp->mscp_status); 150932523Sbostic mscp_printevent(mp); 151032523Sbostic sc->sc_state = ST_IDLE; 15114743Swnj } 151232523Sbostic if (sc->sc_flags & SC_DOWAKE) { 151332523Sbostic sc->sc_flags &= ~SC_DOWAKE; 151432523Sbostic wakeup((caddr_t)sc); 15156964Ssam } 15164743Swnj } 15174743Swnj 15184743Swnj /* 151932523Sbostic * Received a response from an as-yet unconfigured drive. Configure it 152032523Sbostic * in, if possible. 15214743Swnj */ 152232523Sbostic udaunconf(mi, mp) 152332523Sbostic struct mscp_info *mi; 152432523Sbostic register struct mscp *mp; 15254743Swnj { 15264743Swnj 152717553Skarels /* 152832523Sbostic * If it is a slave response, copy it to udaslavereply for 152932523Sbostic * udaslave() to look at. 153017553Skarels */ 153132523Sbostic if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && 153232523Sbostic (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) { 153332523Sbostic udaslavereply = *mp; 153432523Sbostic return (MSCP_DONE); 15354743Swnj } 153632523Sbostic 153732523Sbostic /* 153832523Sbostic * Otherwise, it had better be an available attention response. 153932523Sbostic */ 154032523Sbostic if (mp->mscp_opcode != M_OP_AVAILATTN) 154132523Sbostic return (MSCP_FAILED); 154232523Sbostic 154332523Sbostic /* do what autoconf does */ 154432523Sbostic return (MSCP_FAILED); /* not yet, arwhite, not yet */ 15454743Swnj } 15464743Swnj 154732523Sbostic /* 154832523Sbostic * A drive came on line. Check its type and size. Return DONE if 154932523Sbostic * we think the drive is truly on line. In any case, awaken anyone 155032523Sbostic * sleeping on the drive on-line-ness. 155132523Sbostic */ 155232523Sbostic udaonline(ui, mp) 155332523Sbostic register struct uba_device *ui; 155432523Sbostic struct mscp *mp; 15554743Swnj { 155632523Sbostic register struct ra_info *ra = &ra_info[ui->ui_unit]; 15574743Swnj 155832523Sbostic wakeup((caddr_t)&ui->ui_flags); 155932523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 156032523Sbostic printf("uda%d: attempt to bring ra%d on line failed: ", 156132523Sbostic ui->ui_ctlr, ui->ui_unit); 156232523Sbostic mscp_printevent(mp); 156332523Sbostic ra->ra_state = CLOSED; 156432523Sbostic return (MSCP_FAILED); 156532523Sbostic } 156632523Sbostic 156732523Sbostic ra->ra_state = OPENRAW; 156832523Sbostic ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize; 156932523Sbostic printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit, 157032523Sbostic ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize); 157132523Sbostic /* can now compute ncyl */ 157232523Sbostic ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks / 157332523Sbostic ra->ra_geom.rg_nsectors; 157432523Sbostic return (MSCP_DONE); 15754743Swnj } 15764743Swnj 157732523Sbostic /* 157832523Sbostic * We got some (configured) unit's status. Return DONE if it succeeded. 157932523Sbostic */ 158032523Sbostic udagotstatus(ui, mp) 158132523Sbostic register struct uba_device *ui; 158232523Sbostic register struct mscp *mp; 15834743Swnj { 15844743Swnj 158532523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 158632523Sbostic printf("uda%d: attempt to get status for ra%d failed: ", 158732523Sbostic ui->ui_ctlr, ui->ui_unit); 158832523Sbostic mscp_printevent(mp); 158932523Sbostic return (MSCP_FAILED); 159032523Sbostic } 159132523Sbostic /* record for (future) bad block forwarding and whatever else */ 159232523Sbostic uda_rasave(ui->ui_unit, mp, 1); 159332523Sbostic return (MSCP_DONE); 15944743Swnj } 15954743Swnj 159632523Sbostic /* 159732523Sbostic * A transfer failed. We get a chance to fix or restart it. 159832523Sbostic * Need to write the bad block forwaring code first.... 159932523Sbostic */ 160032523Sbostic /*ARGSUSED*/ 160132523Sbostic udaioerror(ui, mp, bp) 160232523Sbostic register struct uba_device *ui; 160332523Sbostic register struct mscp *mp; 160432523Sbostic struct buf *bp; 16054743Swnj { 16064743Swnj 160732523Sbostic if (mp->mscp_flags & M_EF_BBLKR) { 160832523Sbostic /* 160932523Sbostic * A bad block report. Eventually we will 161032523Sbostic * restart this transfer, but for now, just 161132523Sbostic * log it and give up. 161232523Sbostic */ 161332523Sbostic log(LOG_ERR, "ra%d: bad block report: %d%s\n", 161432523Sbostic ui->ui_unit, mp->mscp_seq.seq_lbn, 161532523Sbostic mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); 161632523Sbostic } else { 161732523Sbostic /* 161832523Sbostic * What the heck IS a `serious exception' anyway? 161932523Sbostic * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION 162032523Sbostic * FOR THEIR OWN CONTROLLERS. 162132523Sbostic */ 162232523Sbostic if (mp->mscp_flags & M_EF_SEREX) 162332523Sbostic log(LOG_ERR, "ra%d: serious exception reported\n", 162432523Sbostic ui->ui_unit); 16254743Swnj } 162632523Sbostic return (MSCP_FAILED); 16274743Swnj } 16284743Swnj 162932523Sbostic /* 163032523Sbostic * A replace operation finished. 163132523Sbostic */ 163232523Sbostic /*ARGSUSED*/ 163332523Sbostic udareplace(ui, mp) 163432523Sbostic struct uba_device *ui; 163532523Sbostic struct mscp *mp; 16364743Swnj { 163717553Skarels 163832523Sbostic panic("udareplace"); 16394743Swnj } 164017553Skarels 164132523Sbostic /* 164232523Sbostic * A bad block related operation finished. 164332523Sbostic */ 164432523Sbostic /*ARGSUSED*/ 164532523Sbostic udabb(ui, mp, bp) 164632523Sbostic struct uba_device *ui; 164732523Sbostic struct mscp *mp; 164832523Sbostic struct buf *bp; 164917553Skarels { 165017553Skarels 165132523Sbostic panic("udabb"); 165217553Skarels } 165317553Skarels 165432523Sbostic 165532523Sbostic /* 165632523Sbostic * I/O controls. 165732523Sbostic */ 165832523Sbostic udaioctl(dev, cmd, data, flag) 165912511Ssam dev_t dev; 166030536Skarels int cmd; 166130536Skarels caddr_t data; 166230536Skarels int flag; 166312511Ssam { 166432523Sbostic register int unit = udaunit(dev); 166530536Skarels register struct disklabel *lp; 166633443Skarels register struct ra_info *ra = &ra_info[unit]; 166733443Skarels int error = 0, wlab; 166812511Ssam 166932523Sbostic lp = &udalabel[unit]; 167030536Skarels 167130536Skarels switch (cmd) { 167230536Skarels 167330536Skarels case DIOCGDINFO: 167430536Skarels *(struct disklabel *)data = *lp; 167530536Skarels break; 167630536Skarels 167730773Skarels case DIOCGPART: 167830773Skarels ((struct partinfo *)data)->disklab = lp; 167930773Skarels ((struct partinfo *)data)->part = 168032523Sbostic &lp->d_partitions[udapart(dev)]; 168130536Skarels break; 168230536Skarels 168330536Skarels case DIOCSDINFO: 168430536Skarels if ((flag & FWRITE) == 0) 168530536Skarels error = EBADF; 168630536Skarels else 168732574Skarels error = setdisklabel(lp, (struct disklabel *)data, 168833443Skarels ra->ra_openpart); 168930536Skarels break; 169030536Skarels 169133443Skarels case DIOCWLABEL: 169233443Skarels if ((flag & FWRITE) == 0) 169333443Skarels error = EBADF; 169433443Skarels else 169533443Skarels ra->ra_wlabel = *(int *)data; 169633443Skarels break; 169733443Skarels 169832574Skarels case DIOCWDINFO: 169933443Skarels /* simulate opening partition 0 so write succeeds */ 170033443Skarels ra->ra_openpart |= (1 << 0); /* XXX */ 170133443Skarels wlab = ra->ra_wlabel; 170233443Skarels ra->ra_wlabel = 1; 170332574Skarels if ((flag & FWRITE) == 0) 170432523Sbostic error = EBADF; 170532574Skarels else if ((error = setdisklabel(lp, (struct disklabel *)data, 170633443Skarels ra->ra_openpart)) == 0) 170732574Skarels error = writedisklabel(dev, udastrategy, lp); 170833443Skarels ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; 170933443Skarels if (error == 0) 171033443Skarels ra->ra_state = OPEN; 171133443Skarels ra->ra_wlabel = wlab; 171230536Skarels break; 171330536Skarels 171432523Sbostic #ifdef notyet 171532523Sbostic case UDAIOCREPLACE: 171632523Sbostic /* 171732523Sbostic * Initiate bad block replacement for the given LBN. 171832523Sbostic * (Should we allow modifiers?) 171932523Sbostic */ 172032523Sbostic error = EOPNOTSUPP; 172132523Sbostic break; 172232523Sbostic 172332523Sbostic case UDAIOCGMICRO: 172432523Sbostic /* 172532523Sbostic * Return the microcode revision for the UDA50 running 172632523Sbostic * this drive. 172732523Sbostic */ 1728*33444Sbostic *(int *)data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro; 172932523Sbostic break; 173032523Sbostic #endif 173132523Sbostic 173230536Skarels default: 173330536Skarels error = ENOTTY; 173430536Skarels break; 173530536Skarels } 173632523Sbostic return (error); 173732523Sbostic } 173832523Sbostic 173932523Sbostic /* 174032523Sbostic * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) 174132523Sbostic * on that Unibus, and requeue outstanding I/O. 174232523Sbostic */ 174332523Sbostic udareset(uban) 174432523Sbostic int uban; 174532523Sbostic { 174632523Sbostic register struct uba_ctlr *um; 174732523Sbostic register struct uda_softc *sc; 174832523Sbostic register int ctlr; 174932523Sbostic 175032523Sbostic for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) { 175132523Sbostic if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban || 175232523Sbostic um->um_alive == 0) 175332523Sbostic continue; 175432523Sbostic printf(" uda%d", ctlr); 175532523Sbostic 175632523Sbostic /* 175732523Sbostic * Our BDP (if any) is gone; our command (if any) is 175832523Sbostic * flushed; the device is no longer mapped; and the 175932523Sbostic * UDA50 is not yet initialised. 176032523Sbostic */ 176132523Sbostic if (um->um_bdp) { 176232523Sbostic printf("<%d>", UBAI_BDP(um->um_bdp)); 176332523Sbostic um->um_bdp = 0; 176432523Sbostic } 176532523Sbostic um->um_ubinfo = 0; 176632523Sbostic um->um_cmd = 0; 176732523Sbostic sc->sc_flags &= ~SC_MAPPED; 176832523Sbostic sc->sc_state = ST_IDLE; 176932523Sbostic 177032523Sbostic /* reset queues and requeue pending transfers */ 177132523Sbostic mscp_requeue(&sc->sc_mi); 177232523Sbostic 177332523Sbostic /* 177432523Sbostic * If it fails to initialise we will notice later and 177532523Sbostic * try again (and again...). Do not call udastart() 177632523Sbostic * here; it will be done after the controller finishes 177732523Sbostic * initialisation. 177832523Sbostic */ 177932523Sbostic if (udainit(ctlr)) 178032523Sbostic printf(" (hung)"); 178132523Sbostic } 178232523Sbostic } 178332523Sbostic 178432523Sbostic /* 178532523Sbostic * Watchdog timer: If the controller is active, and no interrupts 178632523Sbostic * have occurred for 30 seconds, assume it has gone away. 178732523Sbostic */ 178832523Sbostic udawatch() 178932523Sbostic { 179032523Sbostic register int i; 179132523Sbostic register struct uba_ctlr *um; 179232523Sbostic register struct uda_softc *sc; 179332523Sbostic 179432523Sbostic timeout(udawatch, (caddr_t) 0, hz); /* every second */ 179532523Sbostic for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) { 179632523Sbostic if ((um = udaminfo[i]) == 0 || !um->um_alive) 179732523Sbostic continue; 179832523Sbostic if (sc->sc_state == ST_IDLE) 179932523Sbostic continue; 180032523Sbostic if (sc->sc_state == ST_RUN && !um->um_tab.b_active) 180132523Sbostic sc->sc_wticks = 0; 180232523Sbostic else if (++sc->sc_wticks >= 30) { 180332523Sbostic sc->sc_wticks = 0; 180432523Sbostic printf("uda%d: lost interrupt\n", i); 180532523Sbostic ubareset(um->um_ubanum); 180632523Sbostic } 180732523Sbostic } 180832523Sbostic } 180932523Sbostic 181032523Sbostic /* 181132523Sbostic * Do a panic dump. We set up the controller for one command packet 181232523Sbostic * and one response packet, for which we use `struct uda1'. 181332523Sbostic */ 181432523Sbostic struct uda1 { 181532523Sbostic struct uda1ca uda1_ca; /* communications area */ 181632523Sbostic struct mscp uda1_rsp; /* response packet */ 181732523Sbostic struct mscp uda1_cmd; /* command packet */ 181832523Sbostic } uda1; 181932523Sbostic 182032523Sbostic #define DBSIZE 32 /* dump 16K at a time */ 182132523Sbostic 182232523Sbostic udadump(dev) 182332523Sbostic dev_t dev; 182432523Sbostic { 182532523Sbostic struct udadevice *udaddr; 182632523Sbostic struct uda1 *ud_ubaddr; 182732523Sbostic char *start; 182832523Sbostic int num, blk, unit, maxsz, blkoff, reg; 182932523Sbostic struct partition *pp; 183032523Sbostic register struct uba_regs *uba; 183132523Sbostic register struct uba_device *ui; 183232523Sbostic register struct uda1 *ud; 183332523Sbostic register struct pte *io; 183432523Sbostic register int i; 183532523Sbostic 183632523Sbostic /* 183732523Sbostic * Make sure the device is a reasonable place on which to dump. 183832523Sbostic */ 183932523Sbostic unit = udaunit(dev); 184032523Sbostic if (unit >= NRA) 184132523Sbostic return (ENXIO); 1842*33444Sbostic #define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff)) 184332523Sbostic ui = phys(struct uba_device *, udadinfo[unit]); 184432523Sbostic if (ui == NULL || ui->ui_alive == 0) 184532523Sbostic return (ENXIO); 184632523Sbostic 184732523Sbostic /* 184832523Sbostic * Find and initialise the UBA; get the physical address of the 184932523Sbostic * device registers, and of communications area and command and 185032523Sbostic * response packet. 185132523Sbostic */ 185232523Sbostic uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 185332523Sbostic ubainit(uba); 185432523Sbostic udaddr = (struct udadevice *)ui->ui_physaddr; 185532523Sbostic ud = phys(struct uda1 *, &uda1); 185632523Sbostic 185732523Sbostic /* 185832523Sbostic * Map the ca+packets into Unibus I/O space so the UDA50 can get 185932523Sbostic * at them. Use the registers at the end of the Unibus map (since 186032523Sbostic * we will use the registers at the beginning to map the memory 186132523Sbostic * we are dumping). 186232523Sbostic */ 186332523Sbostic num = btoc(sizeof(struct uda1)) + 1; 186432523Sbostic reg = NUBMREG - num; 186532523Sbostic io = &uba->uba_map[reg]; 186632523Sbostic for (i = 0; i < num; i++) 186732523Sbostic *(int *)io++ = UBAMR_MRV | (btop(ud) + i); 186832523Sbostic ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); 186932523Sbostic 187032523Sbostic /* 187132523Sbostic * Initialise the controller, with one command and one response 187232523Sbostic * packet. 187332523Sbostic */ 187432523Sbostic udaddr->udaip = 0; 187532523Sbostic if (udadumpwait(udaddr, UDA_STEP1)) 187632523Sbostic return (EFAULT); 187732523Sbostic udaddr->udasa = UDA_ERR; 187832523Sbostic if (udadumpwait(udaddr, UDA_STEP2)) 187932523Sbostic return (EFAULT); 188032523Sbostic udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; 188132523Sbostic if (udadumpwait(udaddr, UDA_STEP3)) 188232523Sbostic return (EFAULT); 188332523Sbostic udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; 188432523Sbostic if (udadumpwait(udaddr, UDA_STEP4)) 188532523Sbostic return (EFAULT); 188632523Sbostic uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff; 188732523Sbostic udaddr->udasa = UDA_GO; 188832523Sbostic 188932523Sbostic /* 189032523Sbostic * Set up the command and response descriptor, then set the 189132523Sbostic * controller characteristics and bring the drive on line. 189232523Sbostic * Note that all uninitialised locations in uda1_cmd are zero. 189332523Sbostic */ 189432523Sbostic ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; 189532523Sbostic ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; 189632523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ 189732523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ 189832523Sbostic if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) 189932523Sbostic return (EFAULT); 190032523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 190132523Sbostic if (udadumpcmd(M_OP_ONLINE, ud, ui)) 190232523Sbostic return (EFAULT); 190332523Sbostic 190432523Sbostic pp = phys(struct partition *, 190532523Sbostic &udalabel[unit].d_partitions[udapart(dev)]); 190632523Sbostic maxsz = pp->p_size; 190732523Sbostic blkoff = pp->p_offset; 190832523Sbostic 190932523Sbostic /* 191032523Sbostic * Dump all of physical memory, or as much as will fit in the 191132523Sbostic * space provided. 191232523Sbostic */ 191332523Sbostic start = 0; 191432523Sbostic num = maxfree; 191532523Sbostic if (dumplo < 0) 191632523Sbostic return (EINVAL); 191732523Sbostic if (dumplo + num >= maxsz) 191832523Sbostic num = maxsz - dumplo; 191932523Sbostic blkoff += dumplo; 192032523Sbostic 192132523Sbostic /* 192232523Sbostic * Write out memory, DBSIZE pages at a time. 192332523Sbostic * N.B.: this code depends on the fact that the sector 192432523Sbostic * size == the page size. 192532523Sbostic */ 192632523Sbostic while (num > 0) { 192732523Sbostic blk = num > DBSIZE ? DBSIZE : num; 192832523Sbostic io = uba->uba_map; 192932523Sbostic /* 193032523Sbostic * Map in the pages to write, leaving an invalid entry 193132523Sbostic * at the end to guard against wild Unibus transfers. 193232523Sbostic * Then do the write. 193332523Sbostic */ 193432523Sbostic for (i = 0; i < blk; i++) 1935*33444Sbostic *(int *)io++ = UBAMR_MRV | (btop(start) + i); 1936*33444Sbostic *(int *)io = 0; 193732523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 193832523Sbostic ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; 193932523Sbostic ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; 194032523Sbostic if (udadumpcmd(M_OP_WRITE, ud, ui)) 194132523Sbostic return (EIO); 194232523Sbostic start += blk << PGSHIFT; 194332523Sbostic num -= blk; 194432523Sbostic } 194532523Sbostic return (0); /* made it! */ 194632523Sbostic } 194732523Sbostic 194832523Sbostic /* 194932523Sbostic * Wait for some of the bits in `bits' to come on. If the error bit 195032523Sbostic * comes on, or ten seconds pass without response, return true (error). 195132523Sbostic */ 195232523Sbostic udadumpwait(udaddr, bits) 195332523Sbostic register struct udadevice *udaddr; 195432523Sbostic register int bits; 195532523Sbostic { 195632523Sbostic register int timo = todr() + 1000; 195732523Sbostic 195832523Sbostic while ((udaddr->udasa & bits) == 0) { 195932523Sbostic if (udaddr->udasa & UDA_ERR) { 196032523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 196132523Sbostic return (1); 196232523Sbostic } 196332523Sbostic if (todr() >= timo) { 196432523Sbostic printf("timeout\ndump "); 196532523Sbostic return (1); 196632523Sbostic } 196732523Sbostic } 196830536Skarels return (0); 196930536Skarels } 197030536Skarels 197132523Sbostic /* 197232523Sbostic * Feed a command to the UDA50, wait for its response, and return 197332523Sbostic * true iff something went wrong. 197432523Sbostic */ 197532523Sbostic udadumpcmd(op, ud, ui) 197632523Sbostic int op; 197732523Sbostic register struct uda1 *ud; 197832523Sbostic struct uba_device *ui; 197932523Sbostic { 198032523Sbostic register struct udadevice *udaddr; 198132523Sbostic register int n; 198232523Sbostic #define mp (&ud->uda1_rsp) 198332523Sbostic 1984*33444Sbostic udaddr = (struct udadevice *)ui->ui_physaddr; 198532523Sbostic ud->uda1_cmd.mscp_opcode = op; 198632523Sbostic ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; 198732523Sbostic ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; 198832523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 198932523Sbostic ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; 199032523Sbostic if (udaddr->udasa & UDA_ERR) { 199132523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 199232523Sbostic return (1); 199332523Sbostic } 199432523Sbostic n = udaddr->udaip; 199532523Sbostic n = todr() + 1000; 199632523Sbostic for (;;) { 199732523Sbostic if (todr() > n) { 199832523Sbostic printf("timeout\ndump "); 199932523Sbostic return (1); 200032523Sbostic } 200132523Sbostic if (ud->uda1_ca.ca_cmdint) 200232523Sbostic ud->uda1_ca.ca_cmdint = 0; 200332523Sbostic if (ud->uda1_ca.ca_rspint == 0) 200432523Sbostic continue; 200532523Sbostic ud->uda1_ca.ca_rspint = 0; 200632523Sbostic if (mp->mscp_opcode == (op | M_OP_END)) 200732523Sbostic break; 200832523Sbostic printf("\n"); 200932523Sbostic switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { 201032523Sbostic 201132523Sbostic case MSCPT_SEQ: 201232523Sbostic printf("sequential"); 201332523Sbostic break; 201432523Sbostic 201532523Sbostic case MSCPT_DATAGRAM: 201632523Sbostic mscp_decodeerror("uda", ui->ui_ctlr, mp); 201732523Sbostic printf("datagram"); 201832523Sbostic break; 201932523Sbostic 202032523Sbostic case MSCPT_CREDITS: 202132523Sbostic printf("credits"); 202232523Sbostic break; 202332523Sbostic 202432523Sbostic case MSCPT_MAINTENANCE: 202532523Sbostic printf("maintenance"); 202632523Sbostic break; 202732523Sbostic 202832523Sbostic default: 202932523Sbostic printf("unknown (type 0x%x)", 203032523Sbostic MSCP_MSGTYPE(mp->mscp_msgtc)); 203132523Sbostic break; 203232523Sbostic } 203332523Sbostic printf(" ignored\ndump "); 203432523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 203532523Sbostic } 203632523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 203732523Sbostic printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, 203832523Sbostic mp->mscp_opcode, mp->mscp_status); 203932523Sbostic return (1); 204032523Sbostic } 204132523Sbostic return (0); 204232523Sbostic #undef mp 204332523Sbostic } 204432523Sbostic 204532523Sbostic /* 204632523Sbostic * Return the size of a partition, if known, or -1 if not. 204732523Sbostic */ 204832523Sbostic udasize(dev) 204930536Skarels dev_t dev; 205030536Skarels { 205132523Sbostic register int unit = udaunit(dev); 205230536Skarels register struct uba_device *ui; 205330536Skarels 205432523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == NULL || 205532523Sbostic ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 || 205632523Sbostic ra_info[unit].ra_state != OPEN) 205712511Ssam return (-1); 205832523Sbostic return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size); 205912511Ssam } 206017553Skarels 206130536Skarels #ifdef COMPAT_42 206232523Sbostic /* 206332523Sbostic * Tables mapping unlabelled drives. 206432523Sbostic */ 206530536Skarels struct size { 206630536Skarels daddr_t nblocks; 206730536Skarels daddr_t blkoff; 2068*33444Sbostic } ra60_sizes[8] = { 206930536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 207030536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 207130536Skarels 400176, 0, /* C=sectors 0 thru 400175 */ 207230536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 207330536Skarels 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ 207430536Skarels 350852, 49324, /* F=sectors 49324 thru 400175 */ 207530536Skarels 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ 207630536Skarels 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */ 2077*33444Sbostic }, ra70_sizes[8] = { 2078*33444Sbostic 15884, 0, /* A=blk 0 thru 15883 */ 2079*33444Sbostic 33440, 15972, /* B=blk 15972 thru 49323 */ 2080*33444Sbostic -1, 0, /* C=blk 0 thru end */ 2081*33444Sbostic 15884, 341220, /* D=blk 341220 thru 357103 */ 2082*33444Sbostic 55936, 357192, /* E=blk 357192 thru 413127 */ 2083*33444Sbostic -1, 413457, /* F=blk 413457 thru end */ 2084*33444Sbostic -1, 341220, /* G=blk 341220 thru end */ 2085*33444Sbostic 291346, 49731, /* H=blk 49731 thru 341076 */ 208630536Skarels }, ra80_sizes[8] = { 208730536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 208830536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 208930536Skarels 242606, 0, /* C=sectors 0 thru 242605 */ 209030536Skarels 0, 0, /* D=unused */ 209130536Skarels 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ 209230536Skarels 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ 209330536Skarels 192696, 49910, /* G=sectors 49910 thru 242605 */ 209430536Skarels 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */ 209530536Skarels }, ra81_sizes[8] ={ 2096*33444Sbostic #ifdef MARYLAND 2097*33444Sbostic #ifdef ENEEVAX 2098*33444Sbostic 30706, 0, /* A=cyl 0 thru 42 + 2 sectors */ 2099*33444Sbostic 40696, 30706, /* B=cyl 43 thru 99 - 2 sectors */ 2100*33444Sbostic -1, 0, /* C=cyl 0 thru 1247 */ 2101*33444Sbostic -1, 71400, /* D=cyl 100 thru 1247 */ 2102*33444Sbostic 2103*33444Sbostic 15884, 0, /* E=blk 0 thru 15883 */ 2104*33444Sbostic 33440, 15884, /* F=blk 15884 thru 49323 */ 2105*33444Sbostic 82080, 49324, /* G=blk 49324 thru 131403 */ 2106*33444Sbostic -1, 131404, /* H=blk 131404 thru end */ 2107*33444Sbostic #else 2108*33444Sbostic 67832, 0, /* A=cyl 0 thru 94 + 2 sectors */ 2109*33444Sbostic 67828, 67832, /* B=cyl 95 thru 189 - 2 sectors */ 2110*33444Sbostic -1, 0, /* C=cyl 0 thru 1247 */ 2111*33444Sbostic -1, 135660, /* D=cyl 190 thru 1247 */ 2112*33444Sbostic 0, 0, 2113*33444Sbostic 0, 0, 2114*33444Sbostic 0, 0, 2115*33444Sbostic 0, 0, 2116*33444Sbostic #endif ENEEVAX 2117*33444Sbostic #else 211830536Skarels /* 211930536Skarels * These are the new standard partition sizes for ra81's. 212030536Skarels * An RA_COMPAT system is compiled with D, E, and F corresponding 212130536Skarels * to the 4.2 partitions for G, H, and F respectively. 212230536Skarels */ 212330536Skarels #ifndef UCBRA 212430536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 212530536Skarels 66880, 16422, /* B=sectors 16422 thru 83301 */ 212630536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 212730536Skarels #ifdef RA_COMPAT 212830536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 212930536Skarels 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ 213030536Skarels 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */ 213130536Skarels #else 213230536Skarels 15884, 375564, /* D=sectors 375564 thru 391447 */ 213330536Skarels 307200, 391986, /* E=sectors 391986 thru 699185 */ 213430536Skarels 191352, 699720, /* F=sectors 699720 thru 891071 */ 213530536Skarels #endif RA_COMPAT 213630536Skarels 515508, 375564, /* G=sectors 375564 thru 891071 */ 213730536Skarels 291346, 83538, /* H=sectors 83538 thru 374883 */ 213830536Skarels 213930536Skarels /* 214030536Skarels * These partitions correspond to the sizes used by sites at Berkeley, 214130536Skarels * and by those sites that have received copies of the Berkeley driver 214230536Skarels * with deltas 6.2 or greater (11/15/83). 214330536Skarels */ 214430536Skarels #else UCBRA 214530536Skarels 214630536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 214730536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 214830536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 214930536Skarels 15884, 242606, /* D=sectors 242606 thru 258489 */ 215030536Skarels 307200, 258490, /* E=sectors 258490 thru 565689 */ 215130536Skarels 325382, 565690, /* F=sectors 565690 thru 891071 */ 215230536Skarels 648466, 242606, /* G=sectors 242606 thru 891071 */ 215330536Skarels 193282, 49324, /* H=sectors 49324 thru 242605 */ 215430536Skarels 215530536Skarels #endif UCBRA 2156*33444Sbostic #endif MARYLAND 2157*33444Sbostic }, ra82_sizes[8] = { 2158*33444Sbostic 15884, 0, /* A=blk 0 thru 15883 */ 2159*33444Sbostic 66880, 16245, /* B=blk 16245 thru 83124 */ 2160*33444Sbostic -1, 0, /* C=blk 0 thru end */ 2161*33444Sbostic 15884, 375345, /* D=blk 375345 thru 391228 */ 2162*33444Sbostic 307200, 391590, /* E=blk 391590 thru 698789 */ 2163*33444Sbostic -1, 699390, /* F=blk 699390 thru end */ 2164*33444Sbostic -1, 375345, /* G=blk 375345 thru end */ 2165*33444Sbostic 291346, 83790, /* H=blk 83790 thru 375135 */ 2166*33444Sbostic }, rc25_sizes[8] = { 2167*33444Sbostic 15884, 0, /* A=blk 0 thru 15883 */ 2168*33444Sbostic 10032, 15884, /* B=blk 15884 thru 49323 */ 2169*33444Sbostic -1, 0, /* C=blk 0 thru end */ 2170*33444Sbostic 0, 0, /* D=blk 340670 thru 356553 */ 2171*33444Sbostic 0, 0, /* E=blk 356554 thru 412489 */ 2172*33444Sbostic 0, 0, /* F=blk 412490 thru end */ 2173*33444Sbostic -1, 25916, /* G=blk 49324 thru 131403 */ 2174*33444Sbostic 0, 0, /* H=blk 131404 thru end */ 2175*33444Sbostic }, rd52_sizes[8] = { 2176*33444Sbostic 15884, 0, /* A=blk 0 thru 15883 */ 2177*33444Sbostic 9766, 15884, /* B=blk 15884 thru 25649 */ 2178*33444Sbostic -1, 0, /* C=blk 0 thru end */ 2179*33444Sbostic 0, 0, /* D=unused */ 2180*33444Sbostic 0, 0, /* E=unused */ 2181*33444Sbostic 0, 0, /* F=unused */ 2182*33444Sbostic -1, 25650, /* G=blk 25650 thru end */ 2183*33444Sbostic 0, 0, /* H=unused */ 2184*33444Sbostic }, rd53_sizes[8] = { 2185*33444Sbostic 15884, 0, /* A=blk 0 thru 15883 */ 2186*33444Sbostic 33440, 15884, /* B=blk 15884 thru 49323 */ 2187*33444Sbostic -1, 0, /* C=blk 0 thru end */ 2188*33444Sbostic 0, 0, /* D=unused */ 2189*33444Sbostic 33440, 0, /* E=blk 0 thru 33439 */ 2190*33444Sbostic -1, 33440, /* F=blk 33440 thru end */ 2191*33444Sbostic -1, 49324, /* G=blk 49324 thru end */ 2192*33444Sbostic -1, 15884, /* H=blk 15884 thru end */ 2193*33444Sbostic }, rx50_sizes[8] = { 2194*33444Sbostic 800, 0, /* A=blk 0 thru 799 */ 2195*33444Sbostic 0, 0, 2196*33444Sbostic -1, 0, /* C=blk 0 thru end */ 2197*33444Sbostic 0, 0, 2198*33444Sbostic 0, 0, 2199*33444Sbostic 0, 0, 2200*33444Sbostic 0, 0, 2201*33444Sbostic 0, 0, 220230536Skarels }; 220330536Skarels 220432523Sbostic /* 2205*33444Sbostic * Media ID decoding table. 220632523Sbostic */ 220732523Sbostic struct udatypes { 2208*33444Sbostic u_long ut_id; /* media drive ID */ 220932523Sbostic char *ut_name; /* drive type name */ 221032523Sbostic struct size *ut_sizes; /* partition tables */ 221132523Sbostic int ut_nsectors, ut_ntracks, ut_ncylinders; 221232523Sbostic } udatypes[] = { 2213*33444Sbostic { MSCP_MKDRIVE2('R', 'A', 60), "ra60", ra60_sizes, 42, 4, 2382 }, 2214*33444Sbostic { MSCP_MKDRIVE2('R', 'A', 70), "ra70", ra70_sizes, 33, 11, 1507 }, 2215*33444Sbostic { MSCP_MKDRIVE2('R', 'A', 80), "ra80", ra80_sizes, 31, 14, 559 }, 2216*33444Sbostic { MSCP_MKDRIVE2('R', 'A', 81), "ra81", ra81_sizes, 51, 14, 1248 }, 2217*33444Sbostic { MSCP_MKDRIVE2('R', 'A', 82), "ra82", ra82_sizes, 57, 14, 1423 }, 2218*33444Sbostic { MSCP_MKDRIVE2('R', 'C', 25), "rc25-removable", 2219*33444Sbostic rc25_sizes, 42, 4, 302 }, 2220*33444Sbostic { MSCP_MKDRIVE3('R', 'C', 'F', 25), "rc25-fixed", 2221*33444Sbostic rc25_sizes, 42, 4, 302 }, 2222*33444Sbostic { MSCP_MKDRIVE2('R', 'D', 52), "rd52", rd52_sizes, 18, 7, 480 }, 2223*33444Sbostic { MSCP_MKDRIVE2('R', 'D', 53), "rd53", rd53_sizes, 18, 8, 963 }, 2224*33444Sbostic { MSCP_MKDRIVE2('R', 'X', 50), "rx50", rx50_sizes, 10, 1, 80 }, 2225*33444Sbostic 0 222632523Sbostic }; 222732523Sbostic 222832523Sbostic #define NTYPES (sizeof(udatypes) / sizeof(*udatypes)) 222932523Sbostic 223032523Sbostic udamaptype(unit, lp) 223132523Sbostic int unit; 223230536Skarels register struct disklabel *lp; 223330536Skarels { 223432523Sbostic register struct udatypes *ut; 223532523Sbostic register struct size *sz; 223630536Skarels register struct partition *pp; 223732523Sbostic register char *p; 223832523Sbostic register int i; 223932523Sbostic register struct ra_info *ra = &ra_info[unit]; 224030536Skarels 224132523Sbostic lp->d_secsize = 512; 224232523Sbostic lp->d_secperunit = ra->ra_dsize; 2243*33444Sbostic i = MSCP_MEDIA_DRIVE(ra->ra_mediaid); 2244*33444Sbostic for (ut = udatypes; ut->ut_id; ut++) 2245*33444Sbostic if (ut->ut_id == i) 2246*33444Sbostic goto found; 2247*33444Sbostic 2248*33444Sbostic /* not one we know; fake up a label for the whole drive */ 2249*33444Sbostic lp->d_nsectors = ra->ra_geom.rg_nsectors; 2250*33444Sbostic lp->d_ntracks = ra->ra_geom.rg_ntracks; 2251*33444Sbostic lp->d_ncylinders = ra->ra_geom.rg_ncyl; 2252*33444Sbostic i = ra->ra_mediaid; /* print the port type too */ 2253*33444Sbostic printf("ra%d: don't have a partition table for %c%c %c%c%c%d;\n\ 2254*33444Sbostic using (s,t,c)=(%d,%d,%d)\n", 2255*33444Sbostic unit, MSCP_MID_CHAR(4, i), MSCP_MID_CHAR(3, i), 2256*33444Sbostic MSCP_MID_CHAR(2, i), MSCP_MID_CHAR(1, i), 2257*33444Sbostic MSCP_MID_CHAR(0, i), MSCP_MID_CHAR(0, i), 2258*33444Sbostic MSCP_MID_NUM(i), lp->d_nsectors, 2259*33444Sbostic lp->d_ntracks, lp->d_ncylinders); 2260*33444Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 2261*33444Sbostic lp->d_typename[0] = 'r'; 2262*33444Sbostic lp->d_typename[1] = 'a'; 2263*33444Sbostic lp->d_typename[2] = '?'; 2264*33444Sbostic lp->d_typename[3] = '?'; 2265*33444Sbostic lp->d_typename[4] = 0; 2266*33444Sbostic lp->d_npartitions = 1; 2267*33444Sbostic lp->d_partitions[0].p_offset = 0; 2268*33444Sbostic lp->d_partitions[0].p_size = lp->d_secperunit; 2269*33444Sbostic return (0); 2270*33444Sbostic found: 227132523Sbostic p = ut->ut_name; 227232523Sbostic for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++) 227332523Sbostic lp->d_typename[i] = *p++; 227432523Sbostic lp->d_typename[i] = 0; 227532523Sbostic sz = ut->ut_sizes; 227632523Sbostic /* GET nsectors, ntracks, ncylinders FROM SAVED GEOMETRY? */ 227732523Sbostic lp->d_nsectors = ut->ut_nsectors; 227832523Sbostic lp->d_ntracks = ut->ut_ntracks; 227932523Sbostic lp->d_ncylinders = ut->ut_ncylinders; 228030536Skarels lp->d_npartitions = 8; 228130536Skarels lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 228232523Sbostic for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) { 228332523Sbostic pp->p_offset = sz->blkoff; 228432523Sbostic if ((pp->p_size = sz->nblocks) == (u_long)-1) 228532523Sbostic pp->p_size = ra->ra_dsize - sz->blkoff; 228630536Skarels } 228730536Skarels return (1); 228830536Skarels } 228932523Sbostic #endif /* COMPAT_42 */ 229032523Sbostic #endif /* NUDA > 0 */ 2291