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*33443Skarels * @(#)uda.c 7.12 (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 */ 16332523Sbostic 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; 179*33443Skarels 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; 369*33443Skarels 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) 53632523Sbostic dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ 53732523Sbostic udaip[ui->ui_ctlr][ui->ui_slave] = ui; 53833195Sbostic 53933195Sbostic /* 54033195Sbostic * RX50s cannot be brought on line unless there is 54133195Sbostic * a floppy in the drive. Since an ONLINE while cold 54233195Sbostic * takes ten seconds to fail, and (when notyet becomes now) 54333195Sbostic * no sensible person will swap to an RX50, we just 54433195Sbostic * defer the ONLINE until someone tries to use the drive. 54533195Sbostic */ 54633195Sbostic if (ra_info[unit].ra_type == RA_TYPE_RX50) { 54733195Sbostic printf("ra%d: rx50\n", unit); 54833195Sbostic return; 54933195Sbostic } 55032523Sbostic if (uda_rainit(ui, 0)) 55132574Skarels printf("ra%d: offline\n", unit); 55232523Sbostic else { 55332523Sbostic printf("ra%d: %s\n", unit, udalabel[unit].d_typename); 55432523Sbostic #ifdef notyet 55532523Sbostic addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]); 55626295Skarels #endif 55730536Skarels } 55832523Sbostic } 55932523Sbostic 56032523Sbostic /* 56132523Sbostic * Initialise a UDA50. Return true iff something goes wrong. 56232523Sbostic */ 56332523Sbostic udainit(ctlr) 56432523Sbostic int ctlr; 56532523Sbostic { 56632523Sbostic register struct uda_softc *sc; 56732523Sbostic register struct udadevice *udaddr; 56832523Sbostic struct uba_ctlr *um; 56932523Sbostic int timo, ubinfo; 57032523Sbostic 57132523Sbostic sc = &uda_softc[ctlr]; 57232523Sbostic um = udaminfo[ctlr]; 57332523Sbostic if ((sc->sc_flags & SC_MAPPED) == 0) { 57432523Sbostic /* 57532523Sbostic * Map the communication area and command and 57632523Sbostic * response packets into Unibus space. 57732523Sbostic */ 57832523Sbostic ubinfo = uballoc(um->um_ubanum, (caddr_t) &uda[ctlr], 57932523Sbostic sizeof (struct uda), UBA_CANTWAIT); 58032523Sbostic if (ubinfo == 0) { 58132523Sbostic printf("uda%d: uballoc map failed\n", ctlr); 58232523Sbostic return (-1); 58332523Sbostic } 58432523Sbostic sc->sc_uda = (struct uda *) (ubinfo & 0x3ffff); 58532523Sbostic sc->sc_flags |= SC_MAPPED; 58632523Sbostic } 58732523Sbostic 58830536Skarels /* 58932523Sbostic * While we are thinking about it, reset the next command 59032523Sbostic * and response indicies. 59130536Skarels */ 59232523Sbostic sc->sc_mi.mi_cmd.mri_next = 0; 59332523Sbostic sc->sc_mi.mi_rsp.mri_next = 0; 59432523Sbostic 59532523Sbostic /* 59632523Sbostic * Start up the hardware initialisation sequence. 59732523Sbostic */ 59832523Sbostic #define STEP0MASK (UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \ 59932523Sbostic UDA_STEP1 | UDA_NV) 60032523Sbostic 60132523Sbostic sc->sc_state = ST_IDLE; /* in case init fails */ 60232523Sbostic udaddr = (struct udadevice *) um->um_addr; 60332523Sbostic udaddr->udaip = 0; 60432523Sbostic timo = todr() + 1000; 60532523Sbostic while ((udaddr->udasa & STEP0MASK) == 0) { 60632523Sbostic if (todr() > timo) { 60732523Sbostic printf("uda%d: timeout during init\n", ctlr); 60832523Sbostic return (-1); 60932523Sbostic } 61032523Sbostic } 61132523Sbostic if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) { 61232523Sbostic printf("uda%d: init failed, sa=%b\n", ctlr, 61332523Sbostic udaddr->udasa, udasr_bits); 61432523Sbostic return (-1); 61532523Sbostic } 61632523Sbostic 61732523Sbostic /* 61832523Sbostic * Success! Record new state, and start step 1 initialisation. 61932523Sbostic * The rest is done in the interrupt handler. 62032523Sbostic */ 62132523Sbostic sc->sc_state = ST_STEP1; 62232523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 62332523Sbostic (sc->sc_ivec >> 2); 62432523Sbostic return (0); 6254743Swnj } 6264743Swnj 6274743Swnj /* 62832523Sbostic * Open a drive. 6294743Swnj */ 63032523Sbostic /*ARGSUSED*/ 63132523Sbostic udaopen(dev, flag, fmt) 6324743Swnj dev_t dev; 63330773Skarels int flag, fmt; 6344743Swnj { 63532523Sbostic register int unit; 6364743Swnj register struct uba_device *ui; 6374743Swnj register struct uda_softc *sc; 63830536Skarels register struct disklabel *lp; 63930536Skarels register struct partition *pp; 64030916Skarels register struct ra_info *ra; 64132523Sbostic int s, i, part, mask, error = 0; 64230536Skarels daddr_t start, end; 64330536Skarels 64432523Sbostic /* 64532523Sbostic * Make sure this is a reasonable open request. 64632523Sbostic */ 64732523Sbostic unit = udaunit(dev); 64832523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0) 6498576Sroot return (ENXIO); 65032523Sbostic 65132523Sbostic /* 65232523Sbostic * Make sure the controller is running, by (re)initialising it if 65332523Sbostic * necessary. 65432523Sbostic */ 6554743Swnj sc = &uda_softc[ui->ui_ctlr]; 6565434Sroot s = spl5(); 65732523Sbostic if (sc->sc_state != ST_RUN) { 65832523Sbostic if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) { 65932523Sbostic splx(s); 6608576Sroot return (EIO); 66117553Skarels } 66232523Sbostic /* 66332523Sbostic * In case it does not come up, make sure we will be 66432523Sbostic * restarted in 10 seconds. This corresponds to the 66532523Sbostic * 10 second timeouts in udaprobe() and udaslave(). 66632523Sbostic */ 66732523Sbostic sc->sc_flags |= SC_DOWAKE; 66832523Sbostic timeout(wakeup, (caddr_t) sc, 10 * hz); 66932523Sbostic sleep((caddr_t) sc, PRIBIO); 67032523Sbostic if (sc->sc_state != ST_RUN) { 67132523Sbostic splx(s); 67232523Sbostic printf("uda%d: controller hung\n", ui->ui_ctlr); 67332523Sbostic return (EIO); 67432523Sbostic } 67532523Sbostic untimeout(wakeup, (caddr_t) sc); 6764743Swnj } 67732523Sbostic 67832523Sbostic /* 67932523Sbostic * Wait for the state to settle 68032523Sbostic */ 68132523Sbostic ra = &ra_info[unit]; 68232523Sbostic while (ra->ra_state != OPEN && ra->ra_state != OPENRAW && 68332523Sbostic ra->ra_state != CLOSED) 68432523Sbostic sleep((caddr_t)ra, PZERO + 1); 68532523Sbostic 68632523Sbostic /* 68732523Sbostic * If not on line, or we are not sure of the label, reinitialise 68832523Sbostic * the drive. 68932523Sbostic */ 69032523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0 || 69132523Sbostic (ra->ra_state != OPEN && ra->ra_state != OPENRAW)) 69232523Sbostic error = uda_rainit(ui, flag); 69330916Skarels splx(s); 69432523Sbostic if (error) 69532523Sbostic return (error); 69630536Skarels 69732523Sbostic part = udapart(dev); 69832523Sbostic lp = &udalabel[unit]; 69930536Skarels if (part >= lp->d_npartitions) 70030536Skarels return (ENXIO); 70130536Skarels /* 70232523Sbostic * Warn if a partition is opened that overlaps another 70332523Sbostic * already open, unless either is the `raw' partition 70432523Sbostic * (whole disk). 70530536Skarels */ 70632523Sbostic #define RAWPART 2 /* 'c' partition */ /* XXX */ 70732523Sbostic mask = 1 << part; 70832523Sbostic if ((ra->ra_openpart & mask) == 0 && part != RAWPART) { 70930536Skarels pp = &lp->d_partitions[part]; 71030536Skarels start = pp->p_offset; 71130536Skarels end = pp->p_offset + pp->p_size; 71232523Sbostic for (pp = lp->d_partitions, i = 0; 71332523Sbostic i < lp->d_npartitions; pp++, i++) { 71430536Skarels if (pp->p_offset + pp->p_size <= start || 71532523Sbostic pp->p_offset >= end || i == RAWPART) 71630536Skarels continue; 71732523Sbostic if (ra->ra_openpart & (1 << i)) 71830536Skarels log(LOG_WARNING, 71930536Skarels "ra%d%c: overlaps open partition (%c)\n", 72032523Sbostic unit, part + 'a', i + 'a'); 72117553Skarels } 72217553Skarels } 72330773Skarels switch (fmt) { 72430773Skarels case S_IFCHR: 72532523Sbostic ra->ra_copenpart |= mask; 72630773Skarels break; 72730773Skarels case S_IFBLK: 72832523Sbostic ra->ra_bopenpart |= mask; 72930773Skarels break; 73030773Skarels } 73132523Sbostic ra->ra_openpart |= mask; 7328576Sroot return (0); 7334743Swnj } 7344743Swnj 735*33443Skarels /*ARGSUSED*/ 73632523Sbostic udaclose(dev, flags, fmt) 73730536Skarels dev_t dev; 73830773Skarels int flags, fmt; 73930536Skarels { 74032523Sbostic register int unit = udaunit(dev); 74130773Skarels register struct ra_info *ra = &ra_info[unit]; 74232523Sbostic int s, mask = (1 << udapart(dev)); 74330536Skarels 74430773Skarels switch (fmt) { 74530773Skarels case S_IFCHR: 74632523Sbostic ra->ra_copenpart &= ~mask; 74730773Skarels break; 74830773Skarels case S_IFBLK: 74932523Sbostic ra->ra_bopenpart &= ~mask; 75030773Skarels break; 75130773Skarels } 75232523Sbostic ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; 75332523Sbostic 75430536Skarels /* 75532523Sbostic * Should wait for I/O to complete on this partition even if 75632523Sbostic * others are open, but wait for work on blkflush(). 75730536Skarels */ 75832523Sbostic if (ra->ra_openpart == 0) { 75930536Skarels s = spl5(); 76032523Sbostic while (udautab[unit].b_actf) 76132523Sbostic sleep((caddr_t)&udautab[unit], PZERO - 1); 76230536Skarels splx(s); 76332523Sbostic ra->ra_state = CLOSED; 764*33443Skarels ra->ra_wlabel = 0; 76530536Skarels } 76630773Skarels return (0); 76730536Skarels } 76830536Skarels 7694743Swnj /* 77032523Sbostic * Initialise a drive. If it is not already, bring it on line, 77132523Sbostic * and set a timeout on it in case it fails to respond. 77232523Sbostic * When on line, read in the pack label. 7734743Swnj */ 77432523Sbostic uda_rainit(ui, flags) 77530536Skarels register struct uba_device *ui; 77632523Sbostic int flags; 77730536Skarels { 77832523Sbostic register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; 77932523Sbostic register struct disklabel *lp; 78030536Skarels register struct mscp *mp; 78132523Sbostic register int unit = ui->ui_unit; 78232523Sbostic register struct ra_info *ra; 78330773Skarels char *msg, *readdisklabel(); 78432523Sbostic int s, i, udastrategy(); 78530536Skarels extern int cold; 78630536Skarels 78732523Sbostic ra = &ra_info[unit]; 78832523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 78932523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); 79032523Sbostic mp->mscp_opcode = M_OP_ONLINE; 79132523Sbostic mp->mscp_unit = ui->ui_slave; 79232523Sbostic mp->mscp_cmdref = (long)&ui->ui_flags; 79332523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 79432523Sbostic ra->ra_state = WANTOPEN; 79532523Sbostic if (!cold) 79632523Sbostic s = spl5(); 79732523Sbostic i = ((struct udadevice *)ui->ui_addr)->udaip; 79830536Skarels 79930916Skarels if (cold) { 80032523Sbostic i = todr() + 1000; 80132523Sbostic while ((ui->ui_flags & UNIT_ONLINE) == 0) 80232523Sbostic if (todr() > i) 80332523Sbostic break; 80430916Skarels } else { 80532523Sbostic timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); 80632523Sbostic sleep((caddr_t)&ui->ui_flags, PSWP + 1); 80732523Sbostic splx(s); 80832523Sbostic untimeout(wakeup, (caddr_t)&ui->ui_flags); 80930916Skarels } 81032523Sbostic if (ra->ra_state != OPENRAW) { 81132523Sbostic ra->ra_state = CLOSED; 81232523Sbostic wakeup((caddr_t)ra); 81330916Skarels return (EIO); 81430916Skarels } 81530536Skarels } 81630536Skarels 81732523Sbostic lp = &udalabel[unit]; 81830916Skarels lp->d_secsize = DEV_BSIZE; 81932523Sbostic lp->d_secperunit = ra->ra_dsize; 82030916Skarels 82130536Skarels if (flags & O_NDELAY) 82230536Skarels return (0); 82332523Sbostic ra->ra_state = RDLABEL; 82430536Skarels /* 82532523Sbostic * Set up default sizes until we have the label, or longer 82632523Sbostic * if there is none. Set secpercyl, as readdisklabel wants 82732523Sbostic * to compute b_cylin (although we do not need it). 82830536Skarels */ 82930916Skarels lp->d_secpercyl = 1; 83030536Skarels lp->d_npartitions = 1; 83130536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 83230536Skarels lp->d_partitions[0].p_offset = 0; 83332523Sbostic 83430536Skarels /* 83530536Skarels * Read pack label. 83630536Skarels */ 83732523Sbostic if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp)) != NULL) { 83830916Skarels log(LOG_ERR, "ra%d: %s\n", unit, msg); 83930536Skarels #ifdef COMPAT_42 84032523Sbostic if (udamaptype(unit, lp)) 84132523Sbostic ra->ra_state = OPEN; 84230536Skarels else 84332523Sbostic ra->ra_state = OPENRAW; 84431022Skarels #else 84532523Sbostic ra->ra_state = OPENRAW; 84632523Sbostic /* uda_makefakelabel(ra, lp); */ 84730536Skarels #endif 84830773Skarels } else 84932523Sbostic ra->ra_state = OPEN; 85030916Skarels wakeup((caddr_t)ra); 85130916Skarels return (0); 85230536Skarels } 85330536Skarels 85432523Sbostic /* 85532523Sbostic * Copy the geometry information for the given ra from a 85632523Sbostic * GET UNIT STATUS response. If check, see if it changed. 85732523Sbostic */ 85832523Sbostic uda_rasave(unit, mp, check) 85932523Sbostic int unit; 86032523Sbostic register struct mscp *mp; 86132523Sbostic int check; 86232523Sbostic { 86332523Sbostic register struct ra_info *ra = &ra_info[unit]; 86432523Sbostic 86532523Sbostic if (check && ra->ra_type != mp->mscp_guse.guse_drivetype) { 866*33443Skarels printf("ra%d: changed types! was %d now %d\n", unit, 86732523Sbostic ra->ra_type, mp->mscp_guse.guse_drivetype); 86832523Sbostic ra->ra_state = CLOSED; /* ??? */ 86932523Sbostic } 87032523Sbostic ra->ra_type = mp->mscp_guse.guse_drivetype; 87132523Sbostic ra->ra_mediaid = mp->mscp_guse.guse_mediaid; 87232523Sbostic ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt; 87332523Sbostic ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group; 87432523Sbostic ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc; 87532523Sbostic ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc; 87632523Sbostic /* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */ 87732523Sbostic #ifdef notyet 87832523Sbostic ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize; 87932523Sbostic ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt; 88032523Sbostic ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct; 88132523Sbostic #endif 88232523Sbostic } 88332523Sbostic 88432523Sbostic /* 88532523Sbostic * Queue a transfer request, and if possible, hand it to the controller. 88632523Sbostic * 88732523Sbostic * This routine is broken into two so that the internal version 88832523Sbostic * udastrat1() can be called by the (nonexistent, as yet) bad block 88932523Sbostic * revectoring routine. 89032523Sbostic */ 89132523Sbostic udastrategy(bp) 8924743Swnj register struct buf *bp; 8934743Swnj { 89432523Sbostic register int unit; 8954743Swnj register struct uba_device *ui; 89632523Sbostic register struct ra_info *ra; 89732523Sbostic struct partition *pp; 89832523Sbostic int p; 8994743Swnj daddr_t sz, maxsz; 9004743Swnj 90132523Sbostic /* 90232523Sbostic * Make sure this is a reasonable drive to use. 90332523Sbostic */ 90432523Sbostic if ((unit = udaunit(bp->b_dev)) >= NRA || 90532523Sbostic (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || 90632523Sbostic (ra = &ra_info[unit])->ra_state == CLOSED) { 90724742Sbloom bp->b_error = ENXIO; 9084743Swnj goto bad; 90924742Sbloom } 91032523Sbostic 91132523Sbostic /* 91232523Sbostic * If drive is open `raw' or reading label, let it at it. 91332523Sbostic */ 91432523Sbostic if (ra->ra_state < OPEN) { 91532523Sbostic udastrat1(bp); 91632523Sbostic return; 91724742Sbloom } 91832523Sbostic p = udapart(bp->b_dev); 919*33443Skarels if ((ra->ra_openpart & (1 << p)) == 0) { 920*33443Skarels bp->b_error = ENODEV; 921*33443Skarels goto bad; 922*33443Skarels } 92332523Sbostic 92432523Sbostic /* 92532523Sbostic * Determine the size of the transfer, and make sure it is 92632523Sbostic * within the boundaries of the partition. 92732523Sbostic */ 92832523Sbostic pp = &udalabel[unit].d_partitions[p]; 92932523Sbostic maxsz = pp->p_size; 93032523Sbostic if (pp->p_offset + pp->p_size > ra->ra_dsize) 93132523Sbostic maxsz = ra->ra_dsize - pp->p_offset; 93230536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 933*33443Skarels if (bp->b_blkno + pp->p_offset <= LABELSECTOR && 934*33443Skarels #if LABELSECTOR != 0 935*33443Skarels bp->b_blkno + pp->p_offset + sz > LABELSECTOR && 936*33443Skarels #endif 937*33443Skarels (bp->b_flags & B_READ) == 0 && ra->ra_wlabel == 0) { 938*33443Skarels bp->b_error = EROFS; 939*33443Skarels goto bad; 940*33443Skarels } 94130536Skarels if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 94232523Sbostic /* if exactly at end of disk, return an EOF */ 94324787Skarels if (bp->b_blkno == maxsz) { 94424787Skarels bp->b_resid = bp->b_bcount; 94532523Sbostic biodone(bp); 94632523Sbostic return; 94724787Skarels } 94832523Sbostic /* or truncate if part of it fits */ 94930536Skarels sz = maxsz - bp->b_blkno; 95030536Skarels if (sz <= 0) { 95132523Sbostic bp->b_error = EINVAL; /* or hang it up */ 95230536Skarels goto bad; 95330536Skarels } 95430536Skarels bp->b_bcount = sz << DEV_BSHIFT; 95524742Sbloom } 95632523Sbostic udastrat1(bp); 95732523Sbostic return; 95832523Sbostic bad: 95932523Sbostic bp->b_flags |= B_ERROR; 96032523Sbostic biodone(bp); 96132523Sbostic } 96232523Sbostic 96332523Sbostic /* 96432523Sbostic * Work routine for udastrategy. 96532523Sbostic */ 96632523Sbostic udastrat1(bp) 96732523Sbostic register struct buf *bp; 96832523Sbostic { 96932523Sbostic register int unit = udaunit(bp->b_dev); 97032523Sbostic register struct uba_ctlr *um; 97132523Sbostic register struct buf *dp; 97232523Sbostic struct uba_device *ui; 97332523Sbostic int s = spl5(); 97432523Sbostic 9754743Swnj /* 97632523Sbostic * Append the buffer to the drive queue, and if it is not 97732523Sbostic * already there, the drive to the controller queue. (However, 97832523Sbostic * if the drive queue is marked to be requeued, we must be 97932523Sbostic * awaiting an on line or get unit status command; in this 98032523Sbostic * case, leave it off the controller queue.) 9814743Swnj */ 98232523Sbostic um = (ui = udadinfo[unit])->ui_mi; 98332523Sbostic dp = &udautab[unit]; 98432523Sbostic APPEND(bp, dp, av_forw); 98532523Sbostic if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { 98632523Sbostic APPEND(dp, &um->um_tab, b_forw); 98732523Sbostic dp->b_active++; 98832523Sbostic } 98932523Sbostic 9904743Swnj /* 99132523Sbostic * Start activity on the controller. Note that unlike other 99232523Sbostic * Unibus drivers, we must always do this, not just when the 99332523Sbostic * controller is not active. 9944743Swnj */ 99532523Sbostic udastart(um); 9965434Sroot splx(s); 9974743Swnj } 9984743Swnj 99932523Sbostic /* 100032523Sbostic * Start up whatever transfers we can find. 100132523Sbostic * Note that udastart() must be called at spl5(). 100232523Sbostic */ 100332523Sbostic udastart(um) 10044743Swnj register struct uba_ctlr *um; 10054743Swnj { 100632523Sbostic register struct uda_softc *sc = &uda_softc[um->um_ctlr]; 10074743Swnj register struct buf *bp, *dp; 10084743Swnj register struct mscp *mp; 100932523Sbostic struct uba_device *ui; 10104743Swnj struct udadevice *udaddr; 101132523Sbostic struct partition *pp; 101232523Sbostic int i, sz; 10134743Swnj 101432523Sbostic #ifdef lint 101532523Sbostic i = 0; i = i; 101632523Sbostic #endif 101732523Sbostic /* 101832523Sbostic * If it is not running, try (again and again...) to initialise 101932523Sbostic * it. If it is currently initialising just ignore it for now. 102032523Sbostic */ 102132523Sbostic if (sc->sc_state != ST_RUN) { 102232523Sbostic if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr)) 102332523Sbostic printf("uda%d: still hung\n", um->um_ctlr); 102432523Sbostic return; 102532523Sbostic } 102632523Sbostic 102732523Sbostic /* 102832523Sbostic * If um_cmd is nonzero, this controller is on the Unibus 102932523Sbostic * resource wait queue. It will not help to try more requests; 103032523Sbostic * instead, when the Unibus unblocks and calls udadgo(), we 103132523Sbostic * will call udastart() again. 103232523Sbostic */ 103332523Sbostic if (um->um_cmd) 103432523Sbostic return; 103532523Sbostic 103632523Sbostic sc->sc_flags |= SC_INSTART; 103732523Sbostic udaddr = (struct udadevice *) um->um_addr; 103832523Sbostic 10394743Swnj loop: 104032523Sbostic /* 104132523Sbostic * Service the drive at the head of the queue. It may not 104232523Sbostic * need anything, in which case it might be shutting down 104332523Sbostic * in udaclose(). 104432523Sbostic */ 104532523Sbostic if ((dp = um->um_tab.b_actf) == NULL) 104632523Sbostic goto out; 10474743Swnj if ((bp = dp->b_actf) == NULL) { 10484743Swnj dp->b_active = 0; 10494743Swnj um->um_tab.b_actf = dp->b_forw; 105032523Sbostic if (ra_info[dp - udautab].ra_openpart == 0) 105132523Sbostic wakeup((caddr_t)dp); /* finish close protocol */ 105232523Sbostic goto loop; 10534743Swnj } 105432523Sbostic 105532523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 105632523Sbostic udasaerror(um); 105732523Sbostic goto out; 10584743Swnj } 105932523Sbostic 106032523Sbostic /* 106132523Sbostic * Get an MSCP packet, then figure out what to do. If 106232523Sbostic * we cannot get a command packet, the command ring may 106332523Sbostic * be too small: We should have at least as many command 106432523Sbostic * packets as credits, for best performance. 106532523Sbostic */ 106632523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) { 106732523Sbostic if (sc->sc_mi.mi_credits > MSCP_MINCREDITS && 106832523Sbostic (sc->sc_flags & SC_GRIPED) == 0) { 106932523Sbostic log(LOG_NOTICE, "uda%d: command ring too small\n", 107032523Sbostic um->um_ctlr); 107132523Sbostic sc->sc_flags |= SC_GRIPED;/* complain only once */ 107217553Skarels } 107332523Sbostic goto out; 10744743Swnj } 10754743Swnj 107632523Sbostic /* 107732523Sbostic * Bring the drive on line if it is not already. Get its status 107832523Sbostic * if we do not already have it. Otherwise just start the transfer. 107932523Sbostic */ 108032523Sbostic ui = udadinfo[udaunit(bp->b_dev)]; 108132523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 108232523Sbostic mp->mscp_opcode = M_OP_ONLINE; 108332523Sbostic goto common; 10844743Swnj } 108532523Sbostic if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) { 108632523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 108732523Sbostic common: 108832523Sbostic if (ui->ui_flags & UNIT_REQUEUE) panic("udastart"); 108932523Sbostic /* 109032523Sbostic * Take the drive off the controller queue. When the 109132523Sbostic * command finishes, make sure the drive is requeued. 109232523Sbostic */ 109332523Sbostic um->um_tab.b_actf = dp->b_forw; 109432523Sbostic dp->b_active = 0; 109532523Sbostic ui->ui_flags |= UNIT_REQUEUE; 109632523Sbostic mp->mscp_unit = ui->ui_slave; 109732523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 109832523Sbostic sc->sc_flags |= SC_STARTPOLL; 109932523Sbostic #ifdef POLLSTATS 110032523Sbostic sc->sc_ncmd++; 110125653Skarels #endif 110232523Sbostic goto loop; 110317553Skarels } 110432523Sbostic 110532523Sbostic pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)]; 110632523Sbostic mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; 11074743Swnj mp->mscp_unit = ui->ui_slave; 110832523Sbostic mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset; 110930536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 111032523Sbostic mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ? 111132523Sbostic (pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount; 111232523Sbostic /* mscp_cmdref is filled in by mscp_go() */ 11134743Swnj 11144743Swnj /* 111532523Sbostic * Drop the packet pointer into the `command' field so udadgo() 111632523Sbostic * can tell what to start. If ubago returns 1, we can do another 111732523Sbostic * transfer. If not, um_cmd will still point at mp, so we will 111832523Sbostic * know that we are waiting for resources. 11194743Swnj */ 112032523Sbostic um->um_cmd = (int)mp; 112132523Sbostic if (ubago(ui)) 112232523Sbostic goto loop; 112332523Sbostic 112432523Sbostic /* 112532523Sbostic * All done, or blocked in ubago(). If we managed to 112632523Sbostic * issue some commands, start up the beast. 112732523Sbostic */ 112832523Sbostic out: 112932523Sbostic if (sc->sc_flags & SC_STARTPOLL) { 113032523Sbostic #ifdef POLLSTATS 113132523Sbostic udastats.cmd[sc->sc_ncmd]++; 113232523Sbostic sc->sc_ncmd = 0; 113332523Sbostic #endif 113432523Sbostic i = ((struct udadevice *) um->um_addr)->udaip; 11354743Swnj } 113632523Sbostic sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL); 113732523Sbostic } 113832523Sbostic 113932523Sbostic /* 114032523Sbostic * Start a transfer. 114132523Sbostic * 114232523Sbostic * If we are not called from within udastart(), we must have been 114332523Sbostic * blocked, so call udastart to do more requests (if any). If 114432523Sbostic * this calls us again immediately we will not recurse, because 114532523Sbostic * that time we will be in udastart(). Clever.... 114632523Sbostic */ 114732523Sbostic udadgo(um) 114832523Sbostic register struct uba_ctlr *um; 114932523Sbostic { 115032523Sbostic struct uda_softc *sc = &uda_softc[um->um_ctlr]; 115132523Sbostic struct mscp *mp = (struct mscp *)um->um_cmd; 115232523Sbostic 115332523Sbostic um->um_tab.b_active++; /* another transfer going */ 115432523Sbostic 11554743Swnj /* 115632523Sbostic * Fill in the MSCP packet and move the buffer to the 115732523Sbostic * I/O wait queue. Mark the controller as no longer on 115832523Sbostic * the resource queue, and remember to initiate polling. 11594743Swnj */ 116032523Sbostic mp->mscp_seq.seq_buffer = (um->um_ubinfo & 0x3ffff) | 116132523Sbostic (UBAI_BDP(um->um_ubinfo) << 24); 116232523Sbostic mscp_go(&sc->sc_mi, mp, um->um_ubinfo); 116332523Sbostic um->um_cmd = 0; 116432523Sbostic um->um_ubinfo = 0; /* tyke it awye */ 116532523Sbostic sc->sc_flags |= SC_STARTPOLL; 116632523Sbostic #ifdef POLLSTATS 116732523Sbostic sc->sc_ncmd++; 116832523Sbostic #endif 116932523Sbostic if ((sc->sc_flags & SC_INSTART) == 0) 117032523Sbostic udastart(um); 11714743Swnj } 11724743Swnj 117332523Sbostic udaiodone(mi, bp, info) 117432523Sbostic register struct mscp_info *mi; 117532523Sbostic struct buf *bp; 117632523Sbostic int info; 117732523Sbostic { 117832523Sbostic register struct uba_ctlr *um = udaminfo[mi->mi_ctlr]; 117932523Sbostic 118032523Sbostic um->um_ubinfo = info; 118132523Sbostic ubadone(um); 118232523Sbostic biodone(bp); 118332523Sbostic if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab) 118432523Sbostic ubarelse(um->um_ubanum, &um->um_bdp); 118532523Sbostic um->um_tab.b_active--; /* another transfer done */ 118632523Sbostic } 118732523Sbostic 11884743Swnj /* 118932523Sbostic * The error bit was set in the controller status register. Gripe, 119032523Sbostic * reset the controller, requeue pending transfers. 11914743Swnj */ 119232523Sbostic udasaerror(um) 119332523Sbostic register struct uba_ctlr *um; 11944743Swnj { 119532523Sbostic 119632523Sbostic printf("uda%d: controller error, sa=%b\n", um->um_ctlr, 119732523Sbostic ((struct udadevice *) um->um_addr)->udasa, udasr_bits); 119832523Sbostic mscp_requeue(&uda_softc[um->um_ctlr].sc_mi); 119932523Sbostic (void) udainit(um->um_ctlr); 120032523Sbostic } 120132523Sbostic 120232523Sbostic /* 120332523Sbostic * Interrupt routine. Depending on the state of the controller, 120432523Sbostic * continue initialisation, or acknowledge command and response 120532523Sbostic * interrupts, and process responses. 120632523Sbostic */ 120732523Sbostic udaintr(ctlr) 120832523Sbostic int ctlr; 120932523Sbostic { 121032523Sbostic register struct uba_ctlr *um = udaminfo[ctlr]; 121132523Sbostic register struct uda_softc *sc = &uda_softc[ctlr]; 121232523Sbostic register struct udadevice *udaddr = (struct udadevice *) um->um_addr; 121332523Sbostic register struct uda *ud; 121432523Sbostic register struct mscp *mp; 12154743Swnj register int i; 12164743Swnj 121727254Skridle #ifdef VAX630 121832523Sbostic (void) spl5(); /* Qbus interrupt protocol is odd */ 121927254Skridle #endif 122032523Sbostic sc->sc_wticks = 0; /* reset interrupt watchdog */ 122132523Sbostic 122232523Sbostic /* 122332523Sbostic * Combinations during steps 1, 2, and 3: STEPnMASK 122432523Sbostic * corresponds to which bits should be tested; 122532523Sbostic * STEPnGOOD corresponds to the pattern that should 122632523Sbostic * appear after the interrupt from STEPn initialisation. 122732523Sbostic * All steps test the bits in ALLSTEPS. 122832523Sbostic */ 122932523Sbostic #define ALLSTEPS (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1) 123032523Sbostic 123132523Sbostic #define STEP1MASK (ALLSTEPS | UDA_IE | UDA_NCNRMASK) 123232523Sbostic #define STEP1GOOD (UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2) 123332523Sbostic 123432523Sbostic #define STEP2MASK (ALLSTEPS | UDA_IE | UDA_IVECMASK) 123532523Sbostic #define STEP2GOOD (UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2)) 123632523Sbostic 123732523Sbostic #define STEP3MASK ALLSTEPS 123832523Sbostic #define STEP3GOOD UDA_STEP4 123932523Sbostic 12404743Swnj switch (sc->sc_state) { 124132523Sbostic 124232523Sbostic case ST_IDLE: 124332523Sbostic /* 124432523Sbostic * Ignore unsolicited interrupts. 124532523Sbostic */ 124632523Sbostic log(LOG_WARNING, "uda%d: stray intr\n", ctlr); 12474743Swnj return; 12484743Swnj 124932523Sbostic case ST_STEP1: 125032523Sbostic /* 125132523Sbostic * Begin step two initialisation. 125232523Sbostic */ 125332523Sbostic if ((udaddr->udasa & STEP1MASK) != STEP1GOOD) { 125432523Sbostic i = 1; 125532523Sbostic initfailed: 125632523Sbostic printf("uda%d: init step %d failed, sa=%b\n", 125732523Sbostic ctlr, i, udaddr->udasa, udasr_bits); 125832523Sbostic sc->sc_state = ST_IDLE; 125932523Sbostic if (sc->sc_flags & SC_DOWAKE) { 126032523Sbostic sc->sc_flags &= ~SC_DOWAKE; 126132523Sbostic wakeup((caddr_t) sc); 126232523Sbostic } 12634743Swnj return; 12644743Swnj } 126532523Sbostic udaddr->udasa = (int) &sc->sc_uda->uda_ca.ca_rspdsc[0] | 126632523Sbostic (cpu == VAX_780 || cpu == VAX_8600 ? UDA_PI : 0); 126732523Sbostic sc->sc_state = ST_STEP2; 12684743Swnj return; 12694743Swnj 127032523Sbostic case ST_STEP2: 127132523Sbostic /* 127232523Sbostic * Begin step 3 initialisation. 127332523Sbostic */ 127432523Sbostic if ((udaddr->udasa & STEP2MASK) != STEP2GOOD) { 127532523Sbostic i = 2; 127632523Sbostic goto initfailed; 12774743Swnj } 127832523Sbostic udaddr->udasa = ((int) &sc->sc_uda->uda_ca.ca_rspdsc[0]) >> 16; 127932523Sbostic sc->sc_state = ST_STEP3; 12804743Swnj return; 12814743Swnj 128232523Sbostic case ST_STEP3: 128332523Sbostic /* 128432523Sbostic * Set controller characteristics (finish initialisation). 128532523Sbostic */ 128632523Sbostic if ((udaddr->udasa & STEP3MASK) != STEP3GOOD) { 128732523Sbostic i = 3; 128832523Sbostic goto initfailed; 12894743Swnj } 129032523Sbostic i = udaddr->udasa & 0xff; 129132523Sbostic if (i != sc->sc_micro) { 129232523Sbostic sc->sc_micro = i; 129332523Sbostic printf("uda%d: version %d model %d\n", 129432523Sbostic ctlr, i & 0xf, i >> 4); 129532523Sbostic } 129632523Sbostic 129717553Skarels /* 129832523Sbostic * Present the burst size, then remove it. Why this 129932523Sbostic * should be done this way, I have no idea. 130032523Sbostic * 130132523Sbostic * Note that this assumes udaburst[ctlr] > 0. 130217553Skarels */ 130332523Sbostic udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2; 13044743Swnj udaddr->udasa = UDA_GO; 130532523Sbostic printf("uda%d: DMA burst size set to %d\n", 130632523Sbostic ctlr, udaburst[ctlr]); 13074743Swnj 130832523Sbostic udainitds(ctlr); /* initialise data structures */ 130932523Sbostic 13104743Swnj /* 131132523Sbostic * Before we can get a command packet, we need some 131232523Sbostic * credits. Fake some up to keep mscp_getcp() happy, 131332523Sbostic * get a packet, and cancel all credits (the right 131432523Sbostic * number should come back in the response to the 131532523Sbostic * SCC packet). 13164743Swnj */ 131732523Sbostic sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1; 131832523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT); 131932523Sbostic if (mp == NULL) /* `cannot happen' */ 132032523Sbostic panic("udaintr"); 132132523Sbostic sc->sc_mi.mi_credits = 0; 132232523Sbostic mp->mscp_opcode = M_OP_SETCTLRC; 132332523Sbostic mp->mscp_unit = 0; 132432523Sbostic mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | 132532523Sbostic M_CF_THIS; 132632523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 132732523Sbostic i = udaddr->udaip; 132832523Sbostic sc->sc_state = ST_SETCHAR; 13294743Swnj return; 13304743Swnj 133132523Sbostic case ST_SETCHAR: 133232523Sbostic case ST_RUN: 133332523Sbostic /* 133432523Sbostic * Handle Set Ctlr Characteristics responses and operational 133532523Sbostic * responses (via mscp_dorsp). 133632523Sbostic */ 13374743Swnj break; 13384743Swnj 13394743Swnj default: 134032523Sbostic printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state); 134132523Sbostic panic("udastate"); 13424743Swnj } 13434743Swnj 134432523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 134532523Sbostic udasaerror(um); 134632523Sbostic return; 13474743Swnj } 13484743Swnj 134932523Sbostic ud = &uda[ctlr]; 135032523Sbostic 13514743Swnj /* 135232523Sbostic * Handle buffer purge requests. 135332523Sbostic * I have never seen these to work usefully, thus the log(). 13544743Swnj */ 13554743Swnj if (ud->uda_ca.ca_bdp) { 135632523Sbostic log(LOG_DEBUG, "uda%d: purge bdp %d\n", 135732523Sbostic ctlr, ud->uda_ca.ca_bdp); 135826372Skarels UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); 13594743Swnj ud->uda_ca.ca_bdp = 0; 136032523Sbostic udaddr->udasa = 0; /* signal purge complete */ 13614743Swnj } 13624743Swnj 13634743Swnj /* 136432523Sbostic * Check for response and command ring transitions. 13654743Swnj */ 13664743Swnj if (ud->uda_ca.ca_rspint) { 13674743Swnj ud->uda_ca.ca_rspint = 0; 136832523Sbostic mscp_dorsp(&sc->sc_mi); 13694743Swnj } 13704743Swnj if (ud->uda_ca.ca_cmdint) { 13714743Swnj ud->uda_ca.ca_cmdint = 0; 137232523Sbostic MSCP_DOCMD(&sc->sc_mi); 13734743Swnj } 137432523Sbostic udastart(um); 13754743Swnj } 13764743Swnj 137732523Sbostic #ifndef GENERIC_RAW 137832523Sbostic struct buf rudabuf[NRA]; 137932523Sbostic 13804743Swnj /* 138132523Sbostic * Read and write. 13824743Swnj */ 138332523Sbostic udaread(dev, uio) 138432523Sbostic dev_t dev; 138532523Sbostic struct uio *uio; 13864743Swnj { 13874743Swnj 138832523Sbostic return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_READ, 138932523Sbostic minphys, uio)); 139032523Sbostic } 13914743Swnj 139232523Sbostic udawrite(dev, uio) 139332523Sbostic dev_t dev; 139432523Sbostic struct uio *uio; 139532523Sbostic { 13964743Swnj 139732523Sbostic return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_WRITE, 139832523Sbostic minphys, uio)); 139932523Sbostic } 140032523Sbostic #endif /* GENERIC_RAW */ 14014743Swnj 140217553Skarels /* 140332523Sbostic * Initialise the various data structures that control the UDA50. 140417553Skarels */ 140532523Sbostic udainitds(ctlr) 140632523Sbostic int ctlr; 140732523Sbostic { 140832523Sbostic register struct uda *ud = &uda[ctlr]; 140932523Sbostic register struct uda *uud = uda_softc[ctlr].sc_uda; 141032523Sbostic register struct mscp *mp; 141132523Sbostic register int i; 14124743Swnj 141332523Sbostic for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) { 141432523Sbostic ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | 141532523Sbostic (long)&uud->uda_rsp[i].mscp_cmdref; 141632523Sbostic mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i]; 141732523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 14184743Swnj } 141932523Sbostic for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) { 142032523Sbostic ud->uda_ca.ca_cmddsc[i] = MSCP_INT | 142132523Sbostic (long)&uud->uda_cmd[i].mscp_cmdref; 142232523Sbostic mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i]; 142332523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 142432523Sbostic } 14254743Swnj } 14264743Swnj 14274743Swnj /* 142832523Sbostic * Handle an error datagram. All we do now is decode it. 14294743Swnj */ 143032523Sbostic udadgram(mi, mp) 143132523Sbostic struct mscp_info *mi; 143232523Sbostic struct mscp *mp; 14334743Swnj { 143417553Skarels 143532523Sbostic mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); 143632523Sbostic } 143717553Skarels 143832523Sbostic /* 143932523Sbostic * The Set Controller Characteristics command finished. 144032523Sbostic * Record the new state of the controller. 144132523Sbostic */ 144232523Sbostic udactlrdone(mi, mp) 144332523Sbostic register struct mscp_info *mi; 144432523Sbostic struct mscp *mp; 144532523Sbostic { 144632523Sbostic register struct uda_softc *sc = &uda_softc[mi->mi_ctlr]; 144717553Skarels 144832523Sbostic if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) 144932523Sbostic sc->sc_state = ST_RUN; 145032523Sbostic else { 145132523Sbostic printf("uda%d: SETCTLRC failed: ", 145232523Sbostic mi->mi_ctlr, mp->mscp_status); 145332523Sbostic mscp_printevent(mp); 145432523Sbostic sc->sc_state = ST_IDLE; 14554743Swnj } 145632523Sbostic if (sc->sc_flags & SC_DOWAKE) { 145732523Sbostic sc->sc_flags &= ~SC_DOWAKE; 145832523Sbostic wakeup((caddr_t)sc); 14596964Ssam } 14604743Swnj } 14614743Swnj 14624743Swnj /* 146332523Sbostic * Received a response from an as-yet unconfigured drive. Configure it 146432523Sbostic * in, if possible. 14654743Swnj */ 146632523Sbostic udaunconf(mi, mp) 146732523Sbostic struct mscp_info *mi; 146832523Sbostic register struct mscp *mp; 14694743Swnj { 14704743Swnj 147117553Skarels /* 147232523Sbostic * If it is a slave response, copy it to udaslavereply for 147332523Sbostic * udaslave() to look at. 147417553Skarels */ 147532523Sbostic if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && 147632523Sbostic (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) { 147732523Sbostic udaslavereply = *mp; 147832523Sbostic return (MSCP_DONE); 14794743Swnj } 148032523Sbostic 148132523Sbostic /* 148232523Sbostic * Otherwise, it had better be an available attention response. 148332523Sbostic */ 148432523Sbostic if (mp->mscp_opcode != M_OP_AVAILATTN) 148532523Sbostic return (MSCP_FAILED); 148632523Sbostic 148732523Sbostic /* do what autoconf does */ 148832523Sbostic return (MSCP_FAILED); /* not yet, arwhite, not yet */ 14894743Swnj } 14904743Swnj 149132523Sbostic /* 149232523Sbostic * A drive came on line. Check its type and size. Return DONE if 149332523Sbostic * we think the drive is truly on line. In any case, awaken anyone 149432523Sbostic * sleeping on the drive on-line-ness. 149532523Sbostic */ 149632523Sbostic udaonline(ui, mp) 149732523Sbostic register struct uba_device *ui; 149832523Sbostic struct mscp *mp; 14994743Swnj { 150032523Sbostic register struct ra_info *ra = &ra_info[ui->ui_unit]; 15014743Swnj 150232523Sbostic wakeup((caddr_t)&ui->ui_flags); 150332523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 150432523Sbostic printf("uda%d: attempt to bring ra%d on line failed: ", 150532523Sbostic ui->ui_ctlr, ui->ui_unit); 150632523Sbostic mscp_printevent(mp); 150732523Sbostic ra->ra_state = CLOSED; 150832523Sbostic return (MSCP_FAILED); 150932523Sbostic } 151032523Sbostic 151132523Sbostic ra->ra_state = OPENRAW; 151232523Sbostic ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize; 151332523Sbostic printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit, 151432523Sbostic ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize); 151532523Sbostic /* can now compute ncyl */ 151632523Sbostic ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks / 151732523Sbostic ra->ra_geom.rg_nsectors; 151832523Sbostic return (MSCP_DONE); 15194743Swnj } 15204743Swnj 152132523Sbostic /* 152232523Sbostic * We got some (configured) unit's status. Return DONE if it succeeded. 152332523Sbostic */ 152432523Sbostic udagotstatus(ui, mp) 152532523Sbostic register struct uba_device *ui; 152632523Sbostic register struct mscp *mp; 15274743Swnj { 15284743Swnj 152932523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 153032523Sbostic printf("uda%d: attempt to get status for ra%d failed: ", 153132523Sbostic ui->ui_ctlr, ui->ui_unit); 153232523Sbostic mscp_printevent(mp); 153332523Sbostic return (MSCP_FAILED); 153432523Sbostic } 153532523Sbostic /* record for (future) bad block forwarding and whatever else */ 153632523Sbostic uda_rasave(ui->ui_unit, mp, 1); 153732523Sbostic return (MSCP_DONE); 15384743Swnj } 15394743Swnj 154032523Sbostic /* 154132523Sbostic * A transfer failed. We get a chance to fix or restart it. 154232523Sbostic * Need to write the bad block forwaring code first.... 154332523Sbostic */ 154432523Sbostic /*ARGSUSED*/ 154532523Sbostic udaioerror(ui, mp, bp) 154632523Sbostic register struct uba_device *ui; 154732523Sbostic register struct mscp *mp; 154832523Sbostic struct buf *bp; 15494743Swnj { 15504743Swnj 155132523Sbostic if (mp->mscp_flags & M_EF_BBLKR) { 155232523Sbostic /* 155332523Sbostic * A bad block report. Eventually we will 155432523Sbostic * restart this transfer, but for now, just 155532523Sbostic * log it and give up. 155632523Sbostic */ 155732523Sbostic log(LOG_ERR, "ra%d: bad block report: %d%s\n", 155832523Sbostic ui->ui_unit, mp->mscp_seq.seq_lbn, 155932523Sbostic mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); 156032523Sbostic } else { 156132523Sbostic /* 156232523Sbostic * What the heck IS a `serious exception' anyway? 156332523Sbostic * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION 156432523Sbostic * FOR THEIR OWN CONTROLLERS. 156532523Sbostic */ 156632523Sbostic if (mp->mscp_flags & M_EF_SEREX) 156732523Sbostic log(LOG_ERR, "ra%d: serious exception reported\n", 156832523Sbostic ui->ui_unit); 15694743Swnj } 157032523Sbostic return (MSCP_FAILED); 15714743Swnj } 15724743Swnj 157332523Sbostic /* 157432523Sbostic * A replace operation finished. 157532523Sbostic */ 157632523Sbostic /*ARGSUSED*/ 157732523Sbostic udareplace(ui, mp) 157832523Sbostic struct uba_device *ui; 157932523Sbostic struct mscp *mp; 15804743Swnj { 158117553Skarels 158232523Sbostic panic("udareplace"); 15834743Swnj } 158417553Skarels 158532523Sbostic /* 158632523Sbostic * A bad block related operation finished. 158732523Sbostic */ 158832523Sbostic /*ARGSUSED*/ 158932523Sbostic udabb(ui, mp, bp) 159032523Sbostic struct uba_device *ui; 159132523Sbostic struct mscp *mp; 159232523Sbostic struct buf *bp; 159317553Skarels { 159417553Skarels 159532523Sbostic panic("udabb"); 159617553Skarels } 159717553Skarels 159832523Sbostic 159932523Sbostic /* 160032523Sbostic * I/O controls. 160132523Sbostic */ 160232523Sbostic udaioctl(dev, cmd, data, flag) 160312511Ssam dev_t dev; 160430536Skarels int cmd; 160530536Skarels caddr_t data; 160630536Skarels int flag; 160712511Ssam { 160832523Sbostic register int unit = udaunit(dev); 160930536Skarels register struct disklabel *lp; 1610*33443Skarels register struct ra_info *ra = &ra_info[unit]; 1611*33443Skarels int error = 0, wlab; 161212511Ssam 161332523Sbostic lp = &udalabel[unit]; 161430536Skarels 161530536Skarels switch (cmd) { 161630536Skarels 161730536Skarels case DIOCGDINFO: 161830536Skarels *(struct disklabel *)data = *lp; 161930536Skarels break; 162030536Skarels 162130773Skarels case DIOCGPART: 162230773Skarels ((struct partinfo *)data)->disklab = lp; 162330773Skarels ((struct partinfo *)data)->part = 162432523Sbostic &lp->d_partitions[udapart(dev)]; 162530536Skarels break; 162630536Skarels 162730536Skarels case DIOCSDINFO: 162830536Skarels if ((flag & FWRITE) == 0) 162930536Skarels error = EBADF; 163030536Skarels else 163132574Skarels error = setdisklabel(lp, (struct disklabel *)data, 1632*33443Skarels ra->ra_openpart); 163330536Skarels break; 163430536Skarels 1635*33443Skarels case DIOCWLABEL: 1636*33443Skarels if ((flag & FWRITE) == 0) 1637*33443Skarels error = EBADF; 1638*33443Skarels else 1639*33443Skarels ra->ra_wlabel = *(int *)data; 1640*33443Skarels break; 1641*33443Skarels 164232574Skarels case DIOCWDINFO: 1643*33443Skarels /* simulate opening partition 0 so write succeeds */ 1644*33443Skarels ra->ra_openpart |= (1 << 0); /* XXX */ 1645*33443Skarels wlab = ra->ra_wlabel; 1646*33443Skarels ra->ra_wlabel = 1; 164732574Skarels if ((flag & FWRITE) == 0) 164832523Sbostic error = EBADF; 164932574Skarels else if ((error = setdisklabel(lp, (struct disklabel *)data, 1650*33443Skarels ra->ra_openpart)) == 0) 165132574Skarels error = writedisklabel(dev, udastrategy, lp); 1652*33443Skarels ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; 1653*33443Skarels if (error == 0) 1654*33443Skarels ra->ra_state = OPEN; 1655*33443Skarels ra->ra_wlabel = wlab; 165630536Skarels break; 165730536Skarels 165832523Sbostic #ifdef notyet 165932523Sbostic case UDAIOCREPLACE: 166032523Sbostic /* 166132523Sbostic * Initiate bad block replacement for the given LBN. 166232523Sbostic * (Should we allow modifiers?) 166332523Sbostic */ 166432523Sbostic error = EOPNOTSUPP; 166532523Sbostic break; 166632523Sbostic 166732523Sbostic case UDAIOCGMICRO: 166832523Sbostic /* 166932523Sbostic * Return the microcode revision for the UDA50 running 167032523Sbostic * this drive. 167132523Sbostic */ 167232523Sbostic *(int *) data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro; 167332523Sbostic break; 167432523Sbostic #endif 167532523Sbostic 167630536Skarels default: 167730536Skarels error = ENOTTY; 167830536Skarels break; 167930536Skarels } 168032523Sbostic return (error); 168132523Sbostic } 168232523Sbostic 168332523Sbostic /* 168432523Sbostic * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) 168532523Sbostic * on that Unibus, and requeue outstanding I/O. 168632523Sbostic */ 168732523Sbostic udareset(uban) 168832523Sbostic int uban; 168932523Sbostic { 169032523Sbostic register struct uba_ctlr *um; 169132523Sbostic register struct uda_softc *sc; 169232523Sbostic register int ctlr; 169332523Sbostic 169432523Sbostic for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) { 169532523Sbostic if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban || 169632523Sbostic um->um_alive == 0) 169732523Sbostic continue; 169832523Sbostic printf(" uda%d", ctlr); 169932523Sbostic 170032523Sbostic /* 170132523Sbostic * Our BDP (if any) is gone; our command (if any) is 170232523Sbostic * flushed; the device is no longer mapped; and the 170332523Sbostic * UDA50 is not yet initialised. 170432523Sbostic */ 170532523Sbostic if (um->um_bdp) { 170632523Sbostic printf("<%d>", UBAI_BDP(um->um_bdp)); 170732523Sbostic um->um_bdp = 0; 170832523Sbostic } 170932523Sbostic um->um_ubinfo = 0; 171032523Sbostic um->um_cmd = 0; 171132523Sbostic sc->sc_flags &= ~SC_MAPPED; 171232523Sbostic sc->sc_state = ST_IDLE; 171332523Sbostic 171432523Sbostic /* reset queues and requeue pending transfers */ 171532523Sbostic mscp_requeue(&sc->sc_mi); 171632523Sbostic 171732523Sbostic /* 171832523Sbostic * If it fails to initialise we will notice later and 171932523Sbostic * try again (and again...). Do not call udastart() 172032523Sbostic * here; it will be done after the controller finishes 172132523Sbostic * initialisation. 172232523Sbostic */ 172332523Sbostic if (udainit(ctlr)) 172432523Sbostic printf(" (hung)"); 172532523Sbostic } 172632523Sbostic } 172732523Sbostic 172832523Sbostic /* 172932523Sbostic * Watchdog timer: If the controller is active, and no interrupts 173032523Sbostic * have occurred for 30 seconds, assume it has gone away. 173132523Sbostic */ 173232523Sbostic udawatch() 173332523Sbostic { 173432523Sbostic register int i; 173532523Sbostic register struct uba_ctlr *um; 173632523Sbostic register struct uda_softc *sc; 173732523Sbostic 173832523Sbostic timeout(udawatch, (caddr_t) 0, hz); /* every second */ 173932523Sbostic for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) { 174032523Sbostic if ((um = udaminfo[i]) == 0 || !um->um_alive) 174132523Sbostic continue; 174232523Sbostic if (sc->sc_state == ST_IDLE) 174332523Sbostic continue; 174432523Sbostic if (sc->sc_state == ST_RUN && !um->um_tab.b_active) 174532523Sbostic sc->sc_wticks = 0; 174632523Sbostic else if (++sc->sc_wticks >= 30) { 174732523Sbostic sc->sc_wticks = 0; 174832523Sbostic printf("uda%d: lost interrupt\n", i); 174932523Sbostic ubareset(um->um_ubanum); 175032523Sbostic } 175132523Sbostic } 175232523Sbostic } 175332523Sbostic 175432523Sbostic /* 175532523Sbostic * Do a panic dump. We set up the controller for one command packet 175632523Sbostic * and one response packet, for which we use `struct uda1'. 175732523Sbostic */ 175832523Sbostic struct uda1 { 175932523Sbostic struct uda1ca uda1_ca; /* communications area */ 176032523Sbostic struct mscp uda1_rsp; /* response packet */ 176132523Sbostic struct mscp uda1_cmd; /* command packet */ 176232523Sbostic } uda1; 176332523Sbostic 176432523Sbostic #define DBSIZE 32 /* dump 16K at a time */ 176532523Sbostic 176632523Sbostic udadump(dev) 176732523Sbostic dev_t dev; 176832523Sbostic { 176932523Sbostic struct udadevice *udaddr; 177032523Sbostic struct uda1 *ud_ubaddr; 177132523Sbostic char *start; 177232523Sbostic int num, blk, unit, maxsz, blkoff, reg; 177332523Sbostic struct partition *pp; 177432523Sbostic register struct uba_regs *uba; 177532523Sbostic register struct uba_device *ui; 177632523Sbostic register struct uda1 *ud; 177732523Sbostic register struct pte *io; 177832523Sbostic register int i; 177932523Sbostic 178032523Sbostic /* 178132523Sbostic * Make sure the device is a reasonable place on which to dump. 178232523Sbostic */ 178332523Sbostic unit = udaunit(dev); 178432523Sbostic if (unit >= NRA) 178532523Sbostic return (ENXIO); 178632523Sbostic #define phys(cast, addr) ((cast) ((int) addr & 0x7fffffff)) 178732523Sbostic ui = phys(struct uba_device *, udadinfo[unit]); 178832523Sbostic if (ui == NULL || ui->ui_alive == 0) 178932523Sbostic return (ENXIO); 179032523Sbostic 179132523Sbostic /* 179232523Sbostic * Find and initialise the UBA; get the physical address of the 179332523Sbostic * device registers, and of communications area and command and 179432523Sbostic * response packet. 179532523Sbostic */ 179632523Sbostic uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 179732523Sbostic ubainit(uba); 179832523Sbostic udaddr = (struct udadevice *)ui->ui_physaddr; 179932523Sbostic ud = phys(struct uda1 *, &uda1); 180032523Sbostic 180132523Sbostic /* 180232523Sbostic * Map the ca+packets into Unibus I/O space so the UDA50 can get 180332523Sbostic * at them. Use the registers at the end of the Unibus map (since 180432523Sbostic * we will use the registers at the beginning to map the memory 180532523Sbostic * we are dumping). 180632523Sbostic */ 180732523Sbostic num = btoc(sizeof(struct uda1)) + 1; 180832523Sbostic reg = NUBMREG - num; 180932523Sbostic io = &uba->uba_map[reg]; 181032523Sbostic for (i = 0; i < num; i++) 181132523Sbostic *(int *)io++ = UBAMR_MRV | (btop(ud) + i); 181232523Sbostic ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); 181332523Sbostic 181432523Sbostic /* 181532523Sbostic * Initialise the controller, with one command and one response 181632523Sbostic * packet. 181732523Sbostic */ 181832523Sbostic udaddr->udaip = 0; 181932523Sbostic if (udadumpwait(udaddr, UDA_STEP1)) 182032523Sbostic return (EFAULT); 182132523Sbostic udaddr->udasa = UDA_ERR; 182232523Sbostic if (udadumpwait(udaddr, UDA_STEP2)) 182332523Sbostic return (EFAULT); 182432523Sbostic udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; 182532523Sbostic if (udadumpwait(udaddr, UDA_STEP3)) 182632523Sbostic return (EFAULT); 182732523Sbostic udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; 182832523Sbostic if (udadumpwait(udaddr, UDA_STEP4)) 182932523Sbostic return (EFAULT); 183032523Sbostic uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff; 183132523Sbostic udaddr->udasa = UDA_GO; 183232523Sbostic 183332523Sbostic /* 183432523Sbostic * Set up the command and response descriptor, then set the 183532523Sbostic * controller characteristics and bring the drive on line. 183632523Sbostic * Note that all uninitialised locations in uda1_cmd are zero. 183732523Sbostic */ 183832523Sbostic ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; 183932523Sbostic ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; 184032523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ 184132523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ 184232523Sbostic if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) 184332523Sbostic return (EFAULT); 184432523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 184532523Sbostic if (udadumpcmd(M_OP_ONLINE, ud, ui)) 184632523Sbostic return (EFAULT); 184732523Sbostic 184832523Sbostic pp = phys(struct partition *, 184932523Sbostic &udalabel[unit].d_partitions[udapart(dev)]); 185032523Sbostic maxsz = pp->p_size; 185132523Sbostic blkoff = pp->p_offset; 185232523Sbostic 185332523Sbostic /* 185432523Sbostic * Dump all of physical memory, or as much as will fit in the 185532523Sbostic * space provided. 185632523Sbostic */ 185732523Sbostic start = 0; 185832523Sbostic num = maxfree; 185932523Sbostic if (dumplo < 0) 186032523Sbostic return (EINVAL); 186132523Sbostic if (dumplo + num >= maxsz) 186232523Sbostic num = maxsz - dumplo; 186332523Sbostic blkoff += dumplo; 186432523Sbostic 186532523Sbostic /* 186632523Sbostic * Write out memory, DBSIZE pages at a time. 186732523Sbostic * N.B.: this code depends on the fact that the sector 186832523Sbostic * size == the page size. 186932523Sbostic */ 187032523Sbostic while (num > 0) { 187132523Sbostic blk = num > DBSIZE ? DBSIZE : num; 187232523Sbostic io = uba->uba_map; 187332523Sbostic /* 187432523Sbostic * Map in the pages to write, leaving an invalid entry 187532523Sbostic * at the end to guard against wild Unibus transfers. 187632523Sbostic * Then do the write. 187732523Sbostic */ 187832523Sbostic for (i = 0; i < blk; i++) 187932523Sbostic *(int *) io++ = UBAMR_MRV | (btop(start) + i); 188032523Sbostic *(int *) io = 0; 188132523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 188232523Sbostic ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; 188332523Sbostic ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; 188432523Sbostic if (udadumpcmd(M_OP_WRITE, ud, ui)) 188532523Sbostic return (EIO); 188632523Sbostic start += blk << PGSHIFT; 188732523Sbostic num -= blk; 188832523Sbostic } 188932523Sbostic return (0); /* made it! */ 189032523Sbostic } 189132523Sbostic 189232523Sbostic /* 189332523Sbostic * Wait for some of the bits in `bits' to come on. If the error bit 189432523Sbostic * comes on, or ten seconds pass without response, return true (error). 189532523Sbostic */ 189632523Sbostic udadumpwait(udaddr, bits) 189732523Sbostic register struct udadevice *udaddr; 189832523Sbostic register int bits; 189932523Sbostic { 190032523Sbostic register int timo = todr() + 1000; 190132523Sbostic 190232523Sbostic while ((udaddr->udasa & bits) == 0) { 190332523Sbostic if (udaddr->udasa & UDA_ERR) { 190432523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 190532523Sbostic return (1); 190632523Sbostic } 190732523Sbostic if (todr() >= timo) { 190832523Sbostic printf("timeout\ndump "); 190932523Sbostic return (1); 191032523Sbostic } 191132523Sbostic } 191230536Skarels return (0); 191330536Skarels } 191430536Skarels 191532523Sbostic /* 191632523Sbostic * Feed a command to the UDA50, wait for its response, and return 191732523Sbostic * true iff something went wrong. 191832523Sbostic */ 191932523Sbostic udadumpcmd(op, ud, ui) 192032523Sbostic int op; 192132523Sbostic register struct uda1 *ud; 192232523Sbostic struct uba_device *ui; 192332523Sbostic { 192432523Sbostic register struct udadevice *udaddr; 192532523Sbostic register int n; 192632523Sbostic #define mp (&ud->uda1_rsp) 192732523Sbostic 192832523Sbostic udaddr = (struct udadevice *) ui->ui_physaddr; 192932523Sbostic ud->uda1_cmd.mscp_opcode = op; 193032523Sbostic ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; 193132523Sbostic ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; 193232523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 193332523Sbostic ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; 193432523Sbostic if (udaddr->udasa & UDA_ERR) { 193532523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 193632523Sbostic return (1); 193732523Sbostic } 193832523Sbostic n = udaddr->udaip; 193932523Sbostic n = todr() + 1000; 194032523Sbostic for (;;) { 194132523Sbostic if (todr() > n) { 194232523Sbostic printf("timeout\ndump "); 194332523Sbostic return (1); 194432523Sbostic } 194532523Sbostic if (ud->uda1_ca.ca_cmdint) 194632523Sbostic ud->uda1_ca.ca_cmdint = 0; 194732523Sbostic if (ud->uda1_ca.ca_rspint == 0) 194832523Sbostic continue; 194932523Sbostic ud->uda1_ca.ca_rspint = 0; 195032523Sbostic if (mp->mscp_opcode == (op | M_OP_END)) 195132523Sbostic break; 195232523Sbostic printf("\n"); 195332523Sbostic switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { 195432523Sbostic 195532523Sbostic case MSCPT_SEQ: 195632523Sbostic printf("sequential"); 195732523Sbostic break; 195832523Sbostic 195932523Sbostic case MSCPT_DATAGRAM: 196032523Sbostic mscp_decodeerror("uda", ui->ui_ctlr, mp); 196132523Sbostic printf("datagram"); 196232523Sbostic break; 196332523Sbostic 196432523Sbostic case MSCPT_CREDITS: 196532523Sbostic printf("credits"); 196632523Sbostic break; 196732523Sbostic 196832523Sbostic case MSCPT_MAINTENANCE: 196932523Sbostic printf("maintenance"); 197032523Sbostic break; 197132523Sbostic 197232523Sbostic default: 197332523Sbostic printf("unknown (type 0x%x)", 197432523Sbostic MSCP_MSGTYPE(mp->mscp_msgtc)); 197532523Sbostic break; 197632523Sbostic } 197732523Sbostic printf(" ignored\ndump "); 197832523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 197932523Sbostic } 198032523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 198132523Sbostic printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, 198232523Sbostic mp->mscp_opcode, mp->mscp_status); 198332523Sbostic return (1); 198432523Sbostic } 198532523Sbostic return (0); 198632523Sbostic #undef mp 198732523Sbostic } 198832523Sbostic 198932523Sbostic /* 199032523Sbostic * Return the size of a partition, if known, or -1 if not. 199132523Sbostic */ 199232523Sbostic udasize(dev) 199330536Skarels dev_t dev; 199430536Skarels { 199532523Sbostic register int unit = udaunit(dev); 199630536Skarels register struct uba_device *ui; 199730536Skarels 199832523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == NULL || 199932523Sbostic ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 || 200032523Sbostic ra_info[unit].ra_state != OPEN) 200112511Ssam return (-1); 200232523Sbostic return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size); 200312511Ssam } 200417553Skarels 200530536Skarels #ifdef COMPAT_42 200632523Sbostic /* 200732523Sbostic * Tables mapping unlabelled drives. 200832523Sbostic */ 200930536Skarels struct size { 201030536Skarels daddr_t nblocks; 201130536Skarels daddr_t blkoff; 201232523Sbostic } ra25_sizes[8] = { 201330536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 201430536Skarels 10032, 15884, /* B=blk 15884 thru 49323 */ 201530536Skarels -1, 0, /* C=blk 0 thru end */ 201630536Skarels 0, 0, /* D=blk 340670 thru 356553 */ 201730536Skarels 0, 0, /* E=blk 356554 thru 412489 */ 201830536Skarels 0, 0, /* F=blk 412490 thru end */ 201930536Skarels -1, 25916, /* G=blk 49324 thru 131403 */ 202030536Skarels 0, 0, /* H=blk 131404 thru end */ 202132523Sbostic }, rx50_sizes[8] = { 202232523Sbostic 800, 0, /* A=blk 0 thru 799 */ 202332523Sbostic 0, 0, 202432523Sbostic -1, 0, /* C=blk 0 thru end */ 202532523Sbostic 0, 0, 202632523Sbostic 0, 0, 202732523Sbostic 0, 0, 202832523Sbostic 0, 0, 202932523Sbostic 0, 0, 203030536Skarels }, rd52_sizes[8] = { 203130536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 203230536Skarels 9766, 15884, /* B=blk 15884 thru 25649 */ 203330536Skarels -1, 0, /* C=blk 0 thru end */ 203430536Skarels 0, 0, /* D=unused */ 203530536Skarels 0, 0, /* E=unused */ 203630536Skarels 0, 0, /* F=unused */ 203730536Skarels -1, 25650, /* G=blk 25650 thru end */ 203830536Skarels 0, 0, /* H=unused */ 203930536Skarels }, rd53_sizes[8] = { 204030536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 204130536Skarels 33440, 15884, /* B=blk 15884 thru 49323 */ 204230536Skarels -1, 0, /* C=blk 0 thru end */ 204330536Skarels 0, 0, /* D=unused */ 204430536Skarels 33440, 0, /* E=blk 0 thru 33439 */ 204530536Skarels -1, 33440, /* F=blk 33440 thru end */ 204630536Skarels -1, 49324, /* G=blk 49324 thru end */ 204730536Skarels -1, 15884, /* H=blk 15884 thru end */ 204830536Skarels }, ra60_sizes[8] = { 204930536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 205030536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 205130536Skarels 400176, 0, /* C=sectors 0 thru 400175 */ 205230536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 205330536Skarels 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ 205430536Skarels 350852, 49324, /* F=sectors 49324 thru 400175 */ 205530536Skarels 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ 205630536Skarels 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */ 205730536Skarels }, ra80_sizes[8] = { 205830536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 205930536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 206030536Skarels 242606, 0, /* C=sectors 0 thru 242605 */ 206130536Skarels 0, 0, /* D=unused */ 206230536Skarels 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ 206330536Skarels 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ 206430536Skarels 192696, 49910, /* G=sectors 49910 thru 242605 */ 206530536Skarels 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */ 206630536Skarels }, ra81_sizes[8] ={ 206730536Skarels /* 206830536Skarels * These are the new standard partition sizes for ra81's. 206930536Skarels * An RA_COMPAT system is compiled with D, E, and F corresponding 207030536Skarels * to the 4.2 partitions for G, H, and F respectively. 207130536Skarels */ 207230536Skarels #ifndef UCBRA 207330536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 207430536Skarels 66880, 16422, /* B=sectors 16422 thru 83301 */ 207530536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 207630536Skarels #ifdef RA_COMPAT 207730536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 207830536Skarels 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ 207930536Skarels 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */ 208030536Skarels #else 208130536Skarels 15884, 375564, /* D=sectors 375564 thru 391447 */ 208230536Skarels 307200, 391986, /* E=sectors 391986 thru 699185 */ 208330536Skarels 191352, 699720, /* F=sectors 699720 thru 891071 */ 208430536Skarels #endif RA_COMPAT 208530536Skarels 515508, 375564, /* G=sectors 375564 thru 891071 */ 208630536Skarels 291346, 83538, /* H=sectors 83538 thru 374883 */ 208730536Skarels 208830536Skarels /* 208930536Skarels * These partitions correspond to the sizes used by sites at Berkeley, 209030536Skarels * and by those sites that have received copies of the Berkeley driver 209130536Skarels * with deltas 6.2 or greater (11/15/83). 209230536Skarels */ 209330536Skarels #else UCBRA 209430536Skarels 209530536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 209630536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 209730536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 209830536Skarels 15884, 242606, /* D=sectors 242606 thru 258489 */ 209930536Skarels 307200, 258490, /* E=sectors 258490 thru 565689 */ 210030536Skarels 325382, 565690, /* F=sectors 565690 thru 891071 */ 210130536Skarels 648466, 242606, /* G=sectors 242606 thru 891071 */ 210230536Skarels 193282, 49324, /* H=sectors 49324 thru 242605 */ 210330536Skarels 210430536Skarels #endif UCBRA 210530536Skarels }; 210630536Skarels 210732523Sbostic /* 210832523Sbostic * Drive type index decoding table. `ut_name' is null iff the 210932523Sbostic * type is not known. 211032523Sbostic */ 211132523Sbostic struct udatypes { 211232523Sbostic char *ut_name; /* drive type name */ 211332523Sbostic struct size *ut_sizes; /* partition tables */ 211432523Sbostic int ut_nsectors, ut_ntracks, ut_ncylinders; 211532523Sbostic } udatypes[] = { 211632523Sbostic NULL, NULL, 211732523Sbostic 0, 0, 0, 211832523Sbostic "ra80", ra80_sizes, /* 1 = ra80 */ 211932523Sbostic 31, 14, 559, 212032523Sbostic "rc25-removable", ra25_sizes, /* 2 = rc25-r */ 212132523Sbostic 42, 4, 302, 212232523Sbostic "rc25-fixed", ra25_sizes, /* 3 = rc25-f */ 212332523Sbostic 42, 4, 302, 212432523Sbostic "ra60", ra60_sizes, /* 4 = ra60 */ 212532523Sbostic 42, 4, 2382, 212632523Sbostic "ra81", ra81_sizes, /* 5 = ra81 */ 212732523Sbostic 51, 14, 1248, 212832523Sbostic NULL, NULL, /* 6 = ? */ 212932523Sbostic 0, 0, 0, 213032523Sbostic "rx50", rx50_sizes, /* 7 = rx50 */ 213132523Sbostic 10, 1, 80, 213232523Sbostic "rd52", rd52_sizes, /* 8 = rd52 */ 213332523Sbostic 18, 7, 480, 213432523Sbostic "rd53", rd53_sizes, /* 9 = rd53 */ 213532523Sbostic 18, 8, 963, 213632523Sbostic }; 213732523Sbostic 213832523Sbostic #define NTYPES (sizeof(udatypes) / sizeof(*udatypes)) 213932523Sbostic 214032523Sbostic udamaptype(unit, lp) 214132523Sbostic int unit; 214230536Skarels register struct disklabel *lp; 214330536Skarels { 214432523Sbostic register struct udatypes *ut; 214532523Sbostic register struct size *sz; 214630536Skarels register struct partition *pp; 214732523Sbostic register char *p; 214832523Sbostic register int i; 214932523Sbostic register struct ra_info *ra = &ra_info[unit]; 215030536Skarels 215132523Sbostic lp->d_secsize = 512; 215232523Sbostic lp->d_secperunit = ra->ra_dsize; 215332523Sbostic if ((u_long)ra->ra_type >= NTYPES) { 215432523Sbostic printf("ra%d: don't have a partition table for", unit); 215532523Sbostic mscp_printmedia(ra->ra_mediaid); 215632523Sbostic lp->d_nsectors = ra->ra_geom.rg_nsectors; 215732523Sbostic lp->d_ntracks = ra->ra_geom.rg_ntracks; 215832523Sbostic lp->d_ncylinders = ra->ra_geom.rg_ncyl; 215932523Sbostic printf(";\nusing (t,s,c)=(%d,%d,%d)\n", lp->d_nsectors, 216032523Sbostic lp->d_ntracks, lp->d_ncylinders); 216132523Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 216232523Sbostic lp->d_typename[0] = 'r'; 216332523Sbostic lp->d_typename[1] = 'a'; 216432523Sbostic lp->d_typename[2] = '?'; 216532523Sbostic lp->d_typename[3] = '?'; 216632523Sbostic lp->d_typename[4] = 0; 216730536Skarels lp->d_npartitions = 1; 216830536Skarels lp->d_partitions[0].p_offset = 0; 216930536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 217030536Skarels return (0); 217130536Skarels } 217232523Sbostic ut = &udatypes[ra->ra_type]; 217332523Sbostic p = ut->ut_name; 217432523Sbostic for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++) 217532523Sbostic lp->d_typename[i] = *p++; 217632523Sbostic lp->d_typename[i] = 0; 217732523Sbostic sz = ut->ut_sizes; 217832523Sbostic /* GET nsectors, ntracks, ncylinders FROM SAVED GEOMETRY? */ 217932523Sbostic lp->d_nsectors = ut->ut_nsectors; 218032523Sbostic lp->d_ntracks = ut->ut_ntracks; 218132523Sbostic lp->d_ncylinders = ut->ut_ncylinders; 218230536Skarels lp->d_npartitions = 8; 218330536Skarels lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 218432523Sbostic for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) { 218532523Sbostic pp->p_offset = sz->blkoff; 218632523Sbostic if ((pp->p_size = sz->nblocks) == (u_long)-1) 218732523Sbostic pp->p_size = ra->ra_dsize - sz->blkoff; 218830536Skarels } 218930536Skarels return (1); 219030536Skarels } 219132523Sbostic #endif /* COMPAT_42 */ 219232523Sbostic #endif /* NUDA > 0 */ 2193