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*32574Skarels * @(#)uda.c 7.9 (Berkeley) 11/01/87 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 */ 16432523Sbostic u_long ra_mediaid; /* media id */ 16532523Sbostic int ra_state; /* open/closed state */ 16632523Sbostic struct ra_geom { /* geometry information */ 16732523Sbostic u_short rg_nsectors; /* sectors/track */ 16832523Sbostic u_short rg_ngroups; /* track groups */ 16932523Sbostic u_short rg_ngpc; /* groups/cylinder */ 17032523Sbostic u_short rg_ntracks; /* ngroups*ngpc */ 17132523Sbostic u_short rg_ncyl; /* ra_dsize/ntracks/nsectors */ 17232523Sbostic #ifdef notyet 17332523Sbostic u_short rg_rctsize; /* size of rct */ 17432523Sbostic u_short rg_rbns; /* replacement blocks per track */ 17532523Sbostic u_short rg_nrct; /* number of rct copies */ 17632523Sbostic #endif 17732523Sbostic } ra_geom; 17832523Sbostic u_long ra_openpart; /* partitions open */ 17932523Sbostic u_long ra_bopenpart; /* block partitions open */ 18032523Sbostic u_long ra_copenpart; /* character partitions open */ 18132523Sbostic } ra_info[NRA]; 18217553Skarels 18330536Skarels /* 18430536Skarels * Software state, per drive 18530536Skarels */ 18630536Skarels #define CLOSED 0 18730536Skarels #define WANTOPEN 1 18830536Skarels #define RDLABEL 2 18930536Skarels #define OPEN 3 19030536Skarels #define OPENRAW 4 19117553Skarels 19232523Sbostic /* 19332523Sbostic * Definition of the driver for autoconf. 19432523Sbostic */ 19532523Sbostic int udaprobe(), udaslave(), udaattach(), udadgo(), udaintr(); 19632523Sbostic struct uba_ctlr *udaminfo[NUDA]; 19732523Sbostic struct uba_device *udadinfo[NRA]; 19832523Sbostic struct disklabel udalabel[NRA]; 19917553Skarels 20032523Sbostic u_short udastd[] = { 0772150, 0772550, 0777550, 0 }; 20132523Sbostic struct uba_driver udadriver = 20232523Sbostic { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda", 20332523Sbostic udaminfo }; 20417553Skarels 20532523Sbostic /* 20632523Sbostic * More driver definitions, for generic MSCP code. 20732523Sbostic */ 20832523Sbostic int udadgram(), udactlrdone(), udaunconf(), udaiodone(); 20932523Sbostic int udaonline(), udagotstatus(), udaioerror(), udareplace(), udabb(); 2104743Swnj 21132523Sbostic struct buf udautab[NRA]; /* per drive transfer queue */ 2124743Swnj 21332523Sbostic struct mscp_driver udamscpdriver = 21432523Sbostic { MAXUNIT, NRA, UNITSHIFT, udautab, udadinfo, 21532523Sbostic udadgram, udactlrdone, udaunconf, udaiodone, 21632523Sbostic udaonline, udagotstatus, udareplace, udaioerror, udabb, 21732523Sbostic "uda", "ra" }; 21832523Sbostic 21932523Sbostic /* 22032523Sbostic * Miscellaneous private variables. 22132523Sbostic */ 22232523Sbostic char udasr_bits[] = UDASR_BITS; 22332523Sbostic 22432523Sbostic struct uba_device *udaip[NUDA][MAXUNIT]; 22532523Sbostic /* inverting pointers: ctlr & unit => Unibus 22632523Sbostic device pointer */ 22732523Sbostic 22832523Sbostic int udaburst[NUDA] = { 0 }; /* burst size, per UDA50, zero => default; 22932523Sbostic in data space so patchable via adb */ 23032523Sbostic 23132523Sbostic struct mscp udaslavereply; /* get unit status response packet, set 23232523Sbostic for udaslave by udaunconf, via udaintr */ 23332523Sbostic 23432523Sbostic static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr 23532523Sbostic info to slave routine; instead, we remember 23632523Sbostic the last ctlr argument to probe */ 23732523Sbostic 23832523Sbostic int udawstart, udawatch(); /* watchdog timer */ 23932523Sbostic 24032523Sbostic /* 24132523Sbostic * Externals 24232523Sbostic */ 24332523Sbostic int wakeup(); 24432523Sbostic int hz; 24532523Sbostic 24632523Sbostic /* 24732523Sbostic * Poke at a supposed UDA50 to see if it is there. 24832523Sbostic * This routine duplicates some of the code in udainit() only 24932523Sbostic * because autoconf has not set up the right information yet. 25032523Sbostic * We have to do everything `by hand'. 25132523Sbostic */ 25232523Sbostic udaprobe(reg, ctlr, um) 2534743Swnj caddr_t reg; 2544743Swnj int ctlr; 25532523Sbostic struct uba_ctlr *um; 2564743Swnj { 2574743Swnj register int br, cvec; 25832523Sbostic register struct uda_softc *sc; 25932523Sbostic register struct udadevice *udaddr; 26032523Sbostic register struct mscp_info *mi; 26132523Sbostic int timeout, tries; 2624743Swnj 26332523Sbostic #ifdef VAX750 26432523Sbostic /* 26532523Sbostic * The UDA50 wants to share BDPs on 750s, but not on 780s or 26632523Sbostic * 8600s. (730s have no BDPs anyway.) Toward this end, we 26732523Sbostic * here set the `keep bdp' flag in the per-driver information 26832523Sbostic * if this is a 750. (We just need to do it once, but it is 26932523Sbostic * easiest to do it now, for each UDA50.) 27032523Sbostic */ 27132523Sbostic if (cpu == VAX_750) 27232523Sbostic udadriver.ud_keepbdp = 1; 27332523Sbostic #endif 27417553Skarels 27532523Sbostic probeum = um; /* remember for udaslave() */ 2764743Swnj #ifdef lint 27732523Sbostic br = 0; cvec = br; br = cvec; udaintr(0); 2784743Swnj #endif 27932523Sbostic /* 28032523Sbostic * Set up the controller-specific generic MSCP driver info. 28132523Sbostic * Note that this should really be done in the (nonexistent) 28232523Sbostic * controller attach routine. 28332523Sbostic */ 28432523Sbostic sc = &uda_softc[ctlr]; 28532523Sbostic mi = &sc->sc_mi; 28632523Sbostic mi->mi_md = &udamscpdriver; 28732523Sbostic mi->mi_ctlr = um->um_ctlr; 28832523Sbostic mi->mi_tab = &um->um_tab; 28932523Sbostic mi->mi_ip = udaip[ctlr]; 29032523Sbostic mi->mi_cmd.mri_size = NCMD; 29132523Sbostic mi->mi_cmd.mri_desc = uda[ctlr].uda_ca.ca_cmddsc; 29232523Sbostic mi->mi_cmd.mri_ring = uda[ctlr].uda_cmd; 29332523Sbostic mi->mi_rsp.mri_size = NRSP; 29432523Sbostic mi->mi_rsp.mri_desc = uda[ctlr].uda_ca.ca_rspdsc; 29532523Sbostic mi->mi_rsp.mri_ring = uda[ctlr].uda_rsp; 29632523Sbostic mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; 29732523Sbostic 29832523Sbostic /* 29932523Sbostic * More controller specific variables. Again, this should 30032523Sbostic * be in the controller attach routine. 30132523Sbostic */ 30232523Sbostic if (udaburst[ctlr] == 0) 30332523Sbostic udaburst[ctlr] = DEFAULT_BURST; 30432523Sbostic 30532523Sbostic /* 30632523Sbostic * Get an interrupt vector. Note that even if the controller 30732523Sbostic * does not respond, we keep the vector. This is not a serious 30832523Sbostic * problem; but it would be easily fixed if we had a controller 30932523Sbostic * attach routine. Sigh. 31032523Sbostic */ 31132523Sbostic sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 31217553Skarels udaddr = (struct udadevice *) reg; 31317553Skarels 31432523Sbostic /* 31532523Sbostic * Initialise the controller (partially). The UDA50 programmer's 31632523Sbostic * manual states that if initialisation fails, it should be retried 31732523Sbostic * at least once, but after a second failure the port should be 31832523Sbostic * considered `down'; it also mentions that the controller should 31932523Sbostic * initialise within ten seconds. Or so I hear; I have not seen 32032523Sbostic * this manual myself. 32132523Sbostic */ 32232523Sbostic tries = 0; 32332523Sbostic again: 32432523Sbostic udaddr->udaip = 0; /* start initialisation */ 32532523Sbostic timeout = todr() + 1000; /* timeout in 10 seconds */ 32632523Sbostic while ((udaddr->udasa & UDA_STEP1) == 0) 32732523Sbostic if (todr() > timeout) 32832523Sbostic goto bad; 32932523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 33032523Sbostic (sc->sc_ivec >> 2); 33132523Sbostic while ((udaddr->udasa & UDA_STEP2) == 0) 33232523Sbostic if (todr() > timeout) 33332523Sbostic goto bad; 33432523Sbostic 33532523Sbostic /* should have interrupted by now */ 33632523Sbostic #ifdef VAX630 33732523Sbostic if (cpu == VAX_630) 33832523Sbostic br = 0x15; /* screwy interrupt structure */ 33927254Skridle #endif 34032523Sbostic return (sizeof (struct udadevice)); 34132523Sbostic bad: 34232523Sbostic if (++tries < 2) 34332523Sbostic goto again; 34432523Sbostic return (0); 3454743Swnj } 3464743Swnj 34732523Sbostic /* 34832523Sbostic * Find a slave. We allow wildcard slave numbers (something autoconf 34932523Sbostic * is not really prepared to deal with); and we need to know the 35032523Sbostic * controller number to talk to the UDA. For the latter, we keep 35132523Sbostic * track of the last controller probed, since a controller probe 35232523Sbostic * immediately precedes all slave probes for that controller. For the 35332523Sbostic * former, we simply put the unit number into ui->ui_slave after we 35432523Sbostic * have found one. 35532523Sbostic * 35632523Sbostic * Note that by the time udaslave is called, the interrupt vector 35732523Sbostic * for the UDA50 has been set up (so that udaunconf() will be called). 35832523Sbostic */ 35932523Sbostic udaslave(ui, reg) 36032523Sbostic register struct uba_device *ui; 3614743Swnj caddr_t reg; 3624743Swnj { 36332523Sbostic register struct uba_ctlr *um = probeum; 36432523Sbostic register struct mscp *mp; 36532523Sbostic register struct uda_softc *sc; 36632523Sbostic register struct ra_info *ra; 36732523Sbostic int next = 0, type, timeout, tries, i; 36817553Skarels 36932523Sbostic #ifdef lint 37032523Sbostic i = 0; i = i; 37132523Sbostic #endif 37232523Sbostic /* 37332523Sbostic * Make sure the controller is fully initialised, by waiting 37432523Sbostic * for it if necessary. 37532523Sbostic */ 37632523Sbostic sc = &uda_softc[um->um_ctlr]; 37732523Sbostic if (sc->sc_state == ST_RUN) 37832523Sbostic goto findunit; 37932523Sbostic tries = 0; 38032523Sbostic again: 38132523Sbostic if (udainit(ui->ui_ctlr)) 38232523Sbostic return (0); 38332523Sbostic timeout = todr() + 1000; /* 10 seconds */ 38432523Sbostic while (todr() < timeout) 38532523Sbostic if (sc->sc_state == ST_RUN) /* made it */ 38632523Sbostic goto findunit; 38732523Sbostic if (++tries < 2) 38832523Sbostic goto again; 38932523Sbostic printf("uda%d: controller hung\n", um->um_ctlr); 39032523Sbostic return (0); 39117553Skarels 39232523Sbostic /* 39332523Sbostic * The controller is all set; go find the unit. Grab an 39432523Sbostic * MSCP packet and send out a Get Unit Status command, with 39532523Sbostic * the `next unit' modifier if we are looking for a generic 39632523Sbostic * unit. We set the `in slave' flag so that udaunconf() 39732523Sbostic * knows to copy the response to `udaslavereply'. 39832523Sbostic */ 39932523Sbostic findunit: 40032523Sbostic udaslavereply.mscp_opcode = 0; 40132523Sbostic sc->sc_flags |= SC_INSLAVE; 40232523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) 40332523Sbostic panic("udaslave"); /* `cannot happen' */ 40432523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 40532523Sbostic if (ui->ui_slave == '?') { 40632523Sbostic mp->mscp_unit = next; 40732523Sbostic mp->mscp_modifier = M_GUM_NEXTUNIT; 40832523Sbostic } else { 40932523Sbostic mp->mscp_unit = ui->ui_slave; 41032523Sbostic mp->mscp_modifier = 0; 41117553Skarels } 41232523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 41332523Sbostic i = ((struct udadevice *) reg)->udaip; /* initiate polling */ 41432523Sbostic mp = &udaslavereply; 41532523Sbostic timeout = todr() + 1000; 41632523Sbostic while (todr() < timeout) 41732523Sbostic if (mp->mscp_opcode) 41832523Sbostic goto gotit; 41932523Sbostic printf("uda%d: no response to Get Unit Status request\n", 42032523Sbostic um->um_ctlr); 42132523Sbostic sc->sc_flags &= ~SC_INSLAVE; 42232523Sbostic return (0); 42332523Sbostic 42432523Sbostic gotit: 42532523Sbostic sc->sc_flags &= ~SC_INSLAVE; 42632523Sbostic 42732523Sbostic /* 42832523Sbostic * Got a slave response. If the unit is there, use it. 42932523Sbostic */ 43032523Sbostic switch (mp->mscp_status & M_ST_MASK) { 43132523Sbostic 43232523Sbostic case M_ST_SUCCESS: /* worked */ 43332523Sbostic case M_ST_AVAILABLE: /* found another drive */ 43432523Sbostic break; /* use it */ 43532523Sbostic 43632523Sbostic case M_ST_OFFLINE: 43732523Sbostic /* 43832523Sbostic * Figure out why it is off line. It may be because 43932523Sbostic * it is nonexistent, or because it is spun down, or 44032523Sbostic * for some other reason. 44132523Sbostic */ 44232523Sbostic switch (mp->mscp_status & ~M_ST_MASK) { 44332523Sbostic 44432523Sbostic case M_OFFLINE_UNKNOWN: 44532523Sbostic /* 44632523Sbostic * No such drive, and there are none with 44732523Sbostic * higher unit numbers either, if we are 44832523Sbostic * using M_GUM_NEXTUNIT. 44932523Sbostic */ 45032523Sbostic return (0); 45132523Sbostic 45232523Sbostic case M_OFFLINE_UNMOUNTED: 45332523Sbostic /* 45432523Sbostic * The drive is not spun up. Use it anyway. 45532523Sbostic * 45632523Sbostic * N.B.: this seems to be a common occurrance 45732523Sbostic * after a power failure. The first attempt 45832523Sbostic * to bring it on line seems to spin it up 45932523Sbostic * (and thus takes several minutes). Perhaps 46032523Sbostic * we should note here that the on-line may 46132523Sbostic * take longer than usual. 46232523Sbostic */ 46332523Sbostic break; 46432523Sbostic 46532523Sbostic default: 46632523Sbostic /* 46732523Sbostic * In service, or something else equally unusable. 46832523Sbostic */ 46932523Sbostic printf("uda%d: unit %d off line: ", um->um_ctlr, 47032523Sbostic mp->mscp_unit); 47132523Sbostic mscp_printevent(mp); 47232523Sbostic goto try_another; 47332523Sbostic } 47432523Sbostic break; 47532523Sbostic 47632523Sbostic default: 47732523Sbostic printf("uda%d: unable to get unit status: ", um->um_ctlr); 47832523Sbostic mscp_printevent(mp); 47932523Sbostic return (0); 48017553Skarels } 48132523Sbostic 48232523Sbostic /* 48332523Sbostic * Does this ever happen? What (if anything) does it mean? 48432523Sbostic */ 48532523Sbostic if (mp->mscp_unit < next) { 48632523Sbostic printf("uda%d: unit %d, next %d\n", 48732523Sbostic um->um_ctlr, mp->mscp_unit, next); 48832523Sbostic return (0); 48917553Skarels } 49032523Sbostic 49132523Sbostic if (mp->mscp_unit >= MAXUNIT) { 49232523Sbostic printf("uda%d: cannot handle unit number %d (max is %d)\n", 49332523Sbostic um->um_ctlr, mp->mscp_unit, MAXUNIT - 1); 49432523Sbostic return (0); 49532523Sbostic } 49632523Sbostic 49732523Sbostic /* 49832523Sbostic * See if we already handle this drive. 49932523Sbostic * (Only likely if ui->ui_slave=='?'.) 50032523Sbostic */ 50132523Sbostic if (udaip[um->um_ctlr][mp->mscp_unit] != NULL) { 50232523Sbostic try_another: 50332523Sbostic if (ui->ui_slave != '?') 50432523Sbostic return (0); 50532523Sbostic next = mp->mscp_unit + 1; 50632523Sbostic goto findunit; 50732523Sbostic } 50832523Sbostic 50932523Sbostic /* 51032523Sbostic * Voila! 51132523Sbostic */ 51232523Sbostic uda_rasave(ui->ui_unit, mp, 0); 51332523Sbostic ui->ui_flags = 0; /* not on line, nor anything else */ 51432523Sbostic ui->ui_slave = mp->mscp_unit; 51532523Sbostic return (1); 5164743Swnj } 5174743Swnj 51832523Sbostic /* 51932523Sbostic * Attach a found slave. Make sure the watchdog timer is running. 52032523Sbostic * If this disk is being profiled, fill in the `mspw' value (used by 52132523Sbostic * what?). Set up the inverting pointer, and attempt to bring the 52232523Sbostic * drive on line and read its label. 52332523Sbostic */ 52432523Sbostic udaattach(ui) 5254743Swnj register struct uba_device *ui; 5264743Swnj { 52732523Sbostic register int unit = ui->ui_unit; 52832523Sbostic 52932523Sbostic if (udawstart == 0) { 53032523Sbostic timeout(udawatch, (caddr_t) 0, hz); 53132523Sbostic udawstart++; 53232523Sbostic } 53312443Ssam if (ui->ui_dk >= 0) 53432523Sbostic dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ 53532523Sbostic udaip[ui->ui_ctlr][ui->ui_slave] = ui; 53632523Sbostic if (uda_rainit(ui, 0)) 537*32574Skarels printf("ra%d: offline\n", unit); 53832523Sbostic else { 53932523Sbostic printf("ra%d: %s\n", unit, udalabel[unit].d_typename); 54032523Sbostic #ifdef notyet 54132523Sbostic addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]); 54226295Skarels #endif 54330536Skarels } 54432523Sbostic } 54532523Sbostic 54632523Sbostic /* 54732523Sbostic * Initialise a UDA50. Return true iff something goes wrong. 54832523Sbostic */ 54932523Sbostic udainit(ctlr) 55032523Sbostic int ctlr; 55132523Sbostic { 55232523Sbostic register struct uda_softc *sc; 55332523Sbostic register struct udadevice *udaddr; 55432523Sbostic struct uba_ctlr *um; 55532523Sbostic int timo, ubinfo; 55632523Sbostic 55732523Sbostic sc = &uda_softc[ctlr]; 55832523Sbostic um = udaminfo[ctlr]; 55932523Sbostic if ((sc->sc_flags & SC_MAPPED) == 0) { 56032523Sbostic /* 56132523Sbostic * Map the communication area and command and 56232523Sbostic * response packets into Unibus space. 56332523Sbostic */ 56432523Sbostic ubinfo = uballoc(um->um_ubanum, (caddr_t) &uda[ctlr], 56532523Sbostic sizeof (struct uda), UBA_CANTWAIT); 56632523Sbostic if (ubinfo == 0) { 56732523Sbostic printf("uda%d: uballoc map failed\n", ctlr); 56832523Sbostic return (-1); 56932523Sbostic } 57032523Sbostic sc->sc_uda = (struct uda *) (ubinfo & 0x3ffff); 57132523Sbostic sc->sc_flags |= SC_MAPPED; 57232523Sbostic } 57332523Sbostic 57430536Skarels /* 57532523Sbostic * While we are thinking about it, reset the next command 57632523Sbostic * and response indicies. 57730536Skarels */ 57832523Sbostic sc->sc_mi.mi_cmd.mri_next = 0; 57932523Sbostic sc->sc_mi.mi_rsp.mri_next = 0; 58032523Sbostic 58132523Sbostic /* 58232523Sbostic * Start up the hardware initialisation sequence. 58332523Sbostic */ 58432523Sbostic #define STEP0MASK (UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \ 58532523Sbostic UDA_STEP1 | UDA_NV) 58632523Sbostic 58732523Sbostic sc->sc_state = ST_IDLE; /* in case init fails */ 58832523Sbostic udaddr = (struct udadevice *) um->um_addr; 58932523Sbostic udaddr->udaip = 0; 59032523Sbostic timo = todr() + 1000; 59132523Sbostic while ((udaddr->udasa & STEP0MASK) == 0) { 59232523Sbostic if (todr() > timo) { 59332523Sbostic printf("uda%d: timeout during init\n", ctlr); 59432523Sbostic return (-1); 59532523Sbostic } 59632523Sbostic } 59732523Sbostic if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) { 59832523Sbostic printf("uda%d: init failed, sa=%b\n", ctlr, 59932523Sbostic udaddr->udasa, udasr_bits); 60032523Sbostic return (-1); 60132523Sbostic } 60232523Sbostic 60332523Sbostic /* 60432523Sbostic * Success! Record new state, and start step 1 initialisation. 60532523Sbostic * The rest is done in the interrupt handler. 60632523Sbostic */ 60732523Sbostic sc->sc_state = ST_STEP1; 60832523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 60932523Sbostic (sc->sc_ivec >> 2); 61032523Sbostic return (0); 6114743Swnj } 6124743Swnj 6134743Swnj /* 61432523Sbostic * Open a drive. 6154743Swnj */ 61632523Sbostic /*ARGSUSED*/ 61732523Sbostic udaopen(dev, flag, fmt) 6184743Swnj dev_t dev; 61930773Skarels int flag, fmt; 6204743Swnj { 62132523Sbostic register int unit; 6224743Swnj register struct uba_device *ui; 6234743Swnj register struct uda_softc *sc; 62430536Skarels register struct disklabel *lp; 62530536Skarels register struct partition *pp; 62630916Skarels register struct ra_info *ra; 62732523Sbostic int s, i, part, mask, error = 0; 62830536Skarels daddr_t start, end; 62930536Skarels 63032523Sbostic /* 63132523Sbostic * Make sure this is a reasonable open request. 63232523Sbostic */ 63332523Sbostic unit = udaunit(dev); 63432523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0) 6358576Sroot return (ENXIO); 63632523Sbostic 63732523Sbostic /* 63832523Sbostic * Make sure the controller is running, by (re)initialising it if 63932523Sbostic * necessary. 64032523Sbostic */ 6414743Swnj sc = &uda_softc[ui->ui_ctlr]; 6425434Sroot s = spl5(); 64332523Sbostic if (sc->sc_state != ST_RUN) { 64432523Sbostic if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) { 64532523Sbostic splx(s); 6468576Sroot return (EIO); 64717553Skarels } 64832523Sbostic /* 64932523Sbostic * In case it does not come up, make sure we will be 65032523Sbostic * restarted in 10 seconds. This corresponds to the 65132523Sbostic * 10 second timeouts in udaprobe() and udaslave(). 65232523Sbostic */ 65332523Sbostic sc->sc_flags |= SC_DOWAKE; 65432523Sbostic timeout(wakeup, (caddr_t) sc, 10 * hz); 65532523Sbostic sleep((caddr_t) sc, PRIBIO); 65632523Sbostic if (sc->sc_state != ST_RUN) { 65732523Sbostic splx(s); 65832523Sbostic printf("uda%d: controller hung\n", ui->ui_ctlr); 65932523Sbostic return (EIO); 66032523Sbostic } 66132523Sbostic untimeout(wakeup, (caddr_t) sc); 6624743Swnj } 66332523Sbostic 66432523Sbostic /* 66532523Sbostic * Wait for the state to settle 66632523Sbostic */ 66732523Sbostic ra = &ra_info[unit]; 66832523Sbostic while (ra->ra_state != OPEN && ra->ra_state != OPENRAW && 66932523Sbostic ra->ra_state != CLOSED) 67032523Sbostic sleep((caddr_t)ra, PZERO + 1); 67132523Sbostic 67232523Sbostic /* 67332523Sbostic * If not on line, or we are not sure of the label, reinitialise 67432523Sbostic * the drive. 67532523Sbostic */ 67632523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0 || 67732523Sbostic (ra->ra_state != OPEN && ra->ra_state != OPENRAW)) 67832523Sbostic error = uda_rainit(ui, flag); 67930916Skarels splx(s); 68032523Sbostic if (error) 68132523Sbostic return (error); 68230536Skarels 68332523Sbostic part = udapart(dev); 68432523Sbostic lp = &udalabel[unit]; 68530536Skarels if (part >= lp->d_npartitions) 68630536Skarels return (ENXIO); 68730536Skarels /* 68832523Sbostic * Warn if a partition is opened that overlaps another 68932523Sbostic * already open, unless either is the `raw' partition 69032523Sbostic * (whole disk). 69130536Skarels */ 69232523Sbostic #define RAWPART 2 /* 'c' partition */ /* XXX */ 69332523Sbostic mask = 1 << part; 69432523Sbostic if ((ra->ra_openpart & mask) == 0 && part != RAWPART) { 69530536Skarels pp = &lp->d_partitions[part]; 69630536Skarels start = pp->p_offset; 69730536Skarels end = pp->p_offset + pp->p_size; 69832523Sbostic for (pp = lp->d_partitions, i = 0; 69932523Sbostic i < lp->d_npartitions; pp++, i++) { 70030536Skarels if (pp->p_offset + pp->p_size <= start || 70132523Sbostic pp->p_offset >= end || i == RAWPART) 70230536Skarels continue; 70332523Sbostic if (ra->ra_openpart & (1 << i)) 70430536Skarels log(LOG_WARNING, 70530536Skarels "ra%d%c: overlaps open partition (%c)\n", 70632523Sbostic unit, part + 'a', i + 'a'); 70717553Skarels } 70817553Skarels } 70930773Skarels switch (fmt) { 71030773Skarels case S_IFCHR: 71132523Sbostic ra->ra_copenpart |= mask; 71230773Skarels break; 71330773Skarels case S_IFBLK: 71432523Sbostic ra->ra_bopenpart |= mask; 71530773Skarels break; 71630773Skarels } 71732523Sbostic ra->ra_openpart |= mask; 7188576Sroot return (0); 7194743Swnj } 7204743Swnj 72132523Sbostic udaclose(dev, flags, fmt) 72230536Skarels dev_t dev; 72330773Skarels int flags, fmt; 72430536Skarels { 72532523Sbostic register int unit = udaunit(dev); 72630773Skarels register struct ra_info *ra = &ra_info[unit]; 72732523Sbostic int s, mask = (1 << udapart(dev)); 72830536Skarels 72930773Skarels switch (fmt) { 73030773Skarels case S_IFCHR: 73132523Sbostic ra->ra_copenpart &= ~mask; 73230773Skarels break; 73330773Skarels case S_IFBLK: 73432523Sbostic ra->ra_bopenpart &= ~mask; 73530773Skarels break; 73630773Skarels } 73732523Sbostic ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; 73832523Sbostic 73930536Skarels /* 74032523Sbostic * Should wait for I/O to complete on this partition even if 74132523Sbostic * others are open, but wait for work on blkflush(). 74230536Skarels */ 74332523Sbostic if (ra->ra_openpart == 0) { 74430536Skarels s = spl5(); 74532523Sbostic while (udautab[unit].b_actf) 74632523Sbostic sleep((caddr_t)&udautab[unit], PZERO - 1); 74730536Skarels splx(s); 74832523Sbostic ra->ra_state = CLOSED; 74930536Skarels } 75030773Skarels return (0); 75130536Skarels } 75230536Skarels 7534743Swnj /* 75432523Sbostic * Initialise a drive. If it is not already, bring it on line, 75532523Sbostic * and set a timeout on it in case it fails to respond. 75632523Sbostic * When on line, read in the pack label. 7574743Swnj */ 75832523Sbostic uda_rainit(ui, flags) 75930536Skarels register struct uba_device *ui; 76032523Sbostic int flags; 76130536Skarels { 76232523Sbostic register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; 76332523Sbostic register struct disklabel *lp; 76430536Skarels register struct mscp *mp; 76532523Sbostic register int unit = ui->ui_unit; 76632523Sbostic register struct ra_info *ra; 76730773Skarels char *msg, *readdisklabel(); 76832523Sbostic int s, i, udastrategy(); 76930536Skarels extern int cold; 77030536Skarels 77132523Sbostic ra = &ra_info[unit]; 77232523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 77332523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); 77432523Sbostic mp->mscp_opcode = M_OP_ONLINE; 77532523Sbostic mp->mscp_unit = ui->ui_slave; 77632523Sbostic mp->mscp_cmdref = (long)&ui->ui_flags; 77732523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 77832523Sbostic ra->ra_state = WANTOPEN; 77932523Sbostic if (!cold) 78032523Sbostic s = spl5(); 78132523Sbostic i = ((struct udadevice *)ui->ui_addr)->udaip; 78230536Skarels 78330916Skarels if (cold) { 78432523Sbostic i = todr() + 1000; 78532523Sbostic while ((ui->ui_flags & UNIT_ONLINE) == 0) 78632523Sbostic if (todr() > i) 78732523Sbostic break; 78830916Skarels } else { 78932523Sbostic timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); 79032523Sbostic sleep((caddr_t)&ui->ui_flags, PSWP + 1); 79132523Sbostic splx(s); 79232523Sbostic untimeout(wakeup, (caddr_t)&ui->ui_flags); 79330916Skarels } 79432523Sbostic if (ra->ra_state != OPENRAW) { 79532523Sbostic ra->ra_state = CLOSED; 79632523Sbostic wakeup((caddr_t)ra); 79730916Skarels return (EIO); 79830916Skarels } 79930536Skarels } 80030536Skarels 80132523Sbostic lp = &udalabel[unit]; 80230916Skarels lp->d_secsize = DEV_BSIZE; 80332523Sbostic lp->d_secperunit = ra->ra_dsize; 80430916Skarels 80530536Skarels if (flags & O_NDELAY) 80630536Skarels return (0); 80732523Sbostic ra->ra_state = RDLABEL; 80830536Skarels /* 80932523Sbostic * Set up default sizes until we have the label, or longer 81032523Sbostic * if there is none. Set secpercyl, as readdisklabel wants 81132523Sbostic * to compute b_cylin (although we do not need it). 81230536Skarels */ 81330916Skarels lp->d_secpercyl = 1; 81430536Skarels lp->d_npartitions = 1; 81530536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 81630536Skarels lp->d_partitions[0].p_offset = 0; 81732523Sbostic 81830536Skarels /* 81930536Skarels * Read pack label. 82030536Skarels */ 82132523Sbostic if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp)) != NULL) { 82230916Skarels log(LOG_ERR, "ra%d: %s\n", unit, msg); 82330536Skarels #ifdef COMPAT_42 82432523Sbostic if (udamaptype(unit, lp)) 82532523Sbostic ra->ra_state = OPEN; 82630536Skarels else 82732523Sbostic ra->ra_state = OPENRAW; 82831022Skarels #else 82932523Sbostic ra->ra_state = OPENRAW; 83032523Sbostic /* uda_makefakelabel(ra, lp); */ 83130536Skarels #endif 83230773Skarels } else 83332523Sbostic ra->ra_state = OPEN; 83430916Skarels wakeup((caddr_t)ra); 83530916Skarels return (0); 83630536Skarels } 83730536Skarels 83832523Sbostic /* 83932523Sbostic * Copy the geometry information for the given ra from a 84032523Sbostic * GET UNIT STATUS response. If check, see if it changed. 84132523Sbostic */ 84232523Sbostic uda_rasave(unit, mp, check) 84332523Sbostic int unit; 84432523Sbostic register struct mscp *mp; 84532523Sbostic int check; 84632523Sbostic { 84732523Sbostic register struct ra_info *ra = &ra_info[unit]; 84832523Sbostic 84932523Sbostic if (check && ra->ra_type != mp->mscp_guse.guse_drivetype) { 85032523Sbostic printf("ra%d: changed types! was %d now %d\n", 85132523Sbostic ra->ra_type, mp->mscp_guse.guse_drivetype); 85232523Sbostic ra->ra_state = CLOSED; /* ??? */ 85332523Sbostic } 85432523Sbostic ra->ra_type = mp->mscp_guse.guse_drivetype; 85532523Sbostic ra->ra_mediaid = mp->mscp_guse.guse_mediaid; 85632523Sbostic ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt; 85732523Sbostic ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group; 85832523Sbostic ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc; 85932523Sbostic ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc; 86032523Sbostic /* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */ 86132523Sbostic #ifdef notyet 86232523Sbostic ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize; 86332523Sbostic ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt; 86432523Sbostic ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct; 86532523Sbostic #endif 86632523Sbostic } 86732523Sbostic 86832523Sbostic /* 86932523Sbostic * Queue a transfer request, and if possible, hand it to the controller. 87032523Sbostic * 87132523Sbostic * This routine is broken into two so that the internal version 87232523Sbostic * udastrat1() can be called by the (nonexistent, as yet) bad block 87332523Sbostic * revectoring routine. 87432523Sbostic */ 87532523Sbostic udastrategy(bp) 8764743Swnj register struct buf *bp; 8774743Swnj { 87832523Sbostic register int unit; 8794743Swnj register struct uba_device *ui; 88030536Skarels register struct disklabel *lp; 88132523Sbostic register struct ra_info *ra; 88232523Sbostic struct partition *pp; 88332523Sbostic int p; 8844743Swnj daddr_t sz, maxsz; 8854743Swnj 88632523Sbostic /* 88732523Sbostic * Make sure this is a reasonable drive to use. 88832523Sbostic */ 88932523Sbostic if ((unit = udaunit(bp->b_dev)) >= NRA || 89032523Sbostic (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || 89132523Sbostic (ra = &ra_info[unit])->ra_state == CLOSED) { 89224742Sbloom bp->b_error = ENXIO; 8934743Swnj goto bad; 89424742Sbloom } 89532523Sbostic 89632523Sbostic /* 89732523Sbostic * If drive is open `raw' or reading label, let it at it. 89832523Sbostic */ 89932523Sbostic if (ra->ra_state < OPEN) { 90032523Sbostic udastrat1(bp); 90132523Sbostic return; 90224742Sbloom } 90332523Sbostic p = udapart(bp->b_dev); 90432523Sbostic if ((ra->ra_openpart & (1 << p)) == 0) /* can't happen? */ 90532523Sbostic panic("udastrategy"); 90632523Sbostic /* alternatively, ENODEV */ 90732523Sbostic 90832523Sbostic /* 90932523Sbostic * Determine the size of the transfer, and make sure it is 91032523Sbostic * within the boundaries of the partition. 91132523Sbostic */ 91232523Sbostic pp = &udalabel[unit].d_partitions[p]; 91332523Sbostic maxsz = pp->p_size; 91432523Sbostic if (pp->p_offset + pp->p_size > ra->ra_dsize) 91532523Sbostic maxsz = ra->ra_dsize - pp->p_offset; 91630536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 91730536Skarels if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 91832523Sbostic /* if exactly at end of disk, return an EOF */ 91924787Skarels if (bp->b_blkno == maxsz) { 92024787Skarels bp->b_resid = bp->b_bcount; 92132523Sbostic biodone(bp); 92232523Sbostic return; 92324787Skarels } 92432523Sbostic /* or truncate if part of it fits */ 92530536Skarels sz = maxsz - bp->b_blkno; 92630536Skarels if (sz <= 0) { 92732523Sbostic bp->b_error = EINVAL; /* or hang it up */ 92830536Skarels goto bad; 92930536Skarels } 93030536Skarels bp->b_bcount = sz << DEV_BSHIFT; 93124742Sbloom } 93232523Sbostic udastrat1(bp); 93332523Sbostic return; 93432523Sbostic bad: 93532523Sbostic bp->b_flags |= B_ERROR; 93632523Sbostic biodone(bp); 93732523Sbostic } 93832523Sbostic 93932523Sbostic /* 94032523Sbostic * Work routine for udastrategy. 94132523Sbostic */ 94232523Sbostic udastrat1(bp) 94332523Sbostic register struct buf *bp; 94432523Sbostic { 94532523Sbostic register int unit = udaunit(bp->b_dev); 94632523Sbostic register struct uba_ctlr *um; 94732523Sbostic register struct buf *dp; 94832523Sbostic struct uba_device *ui; 94932523Sbostic int s = spl5(); 95032523Sbostic 9514743Swnj /* 95232523Sbostic * Append the buffer to the drive queue, and if it is not 95332523Sbostic * already there, the drive to the controller queue. (However, 95432523Sbostic * if the drive queue is marked to be requeued, we must be 95532523Sbostic * awaiting an on line or get unit status command; in this 95632523Sbostic * case, leave it off the controller queue.) 9574743Swnj */ 95832523Sbostic um = (ui = udadinfo[unit])->ui_mi; 95932523Sbostic dp = &udautab[unit]; 96032523Sbostic APPEND(bp, dp, av_forw); 96132523Sbostic if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { 96232523Sbostic APPEND(dp, &um->um_tab, b_forw); 96332523Sbostic dp->b_active++; 96432523Sbostic } 96532523Sbostic 9664743Swnj /* 96732523Sbostic * Start activity on the controller. Note that unlike other 96832523Sbostic * Unibus drivers, we must always do this, not just when the 96932523Sbostic * controller is not active. 9704743Swnj */ 97132523Sbostic udastart(um); 9725434Sroot splx(s); 9734743Swnj } 9744743Swnj 97532523Sbostic /* 97632523Sbostic * Start up whatever transfers we can find. 97732523Sbostic * Note that udastart() must be called at spl5(). 97832523Sbostic */ 97932523Sbostic udastart(um) 9804743Swnj register struct uba_ctlr *um; 9814743Swnj { 98232523Sbostic register struct uda_softc *sc = &uda_softc[um->um_ctlr]; 9834743Swnj register struct buf *bp, *dp; 9844743Swnj register struct mscp *mp; 98532523Sbostic struct uba_device *ui; 9864743Swnj struct udadevice *udaddr; 98732523Sbostic struct partition *pp; 98832523Sbostic int i, sz; 9894743Swnj 99032523Sbostic #ifdef lint 99132523Sbostic i = 0; i = i; 99232523Sbostic #endif 99332523Sbostic /* 99432523Sbostic * If it is not running, try (again and again...) to initialise 99532523Sbostic * it. If it is currently initialising just ignore it for now. 99632523Sbostic */ 99732523Sbostic if (sc->sc_state != ST_RUN) { 99832523Sbostic if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr)) 99932523Sbostic printf("uda%d: still hung\n", um->um_ctlr); 100032523Sbostic return; 100132523Sbostic } 100232523Sbostic 100332523Sbostic /* 100432523Sbostic * If um_cmd is nonzero, this controller is on the Unibus 100532523Sbostic * resource wait queue. It will not help to try more requests; 100632523Sbostic * instead, when the Unibus unblocks and calls udadgo(), we 100732523Sbostic * will call udastart() again. 100832523Sbostic */ 100932523Sbostic if (um->um_cmd) 101032523Sbostic return; 101132523Sbostic 101232523Sbostic sc->sc_flags |= SC_INSTART; 101332523Sbostic udaddr = (struct udadevice *) um->um_addr; 101432523Sbostic 10154743Swnj loop: 101632523Sbostic /* 101732523Sbostic * Service the drive at the head of the queue. It may not 101832523Sbostic * need anything, in which case it might be shutting down 101932523Sbostic * in udaclose(). 102032523Sbostic */ 102132523Sbostic if ((dp = um->um_tab.b_actf) == NULL) 102232523Sbostic goto out; 10234743Swnj if ((bp = dp->b_actf) == NULL) { 10244743Swnj dp->b_active = 0; 10254743Swnj um->um_tab.b_actf = dp->b_forw; 102632523Sbostic if (ra_info[dp - udautab].ra_openpart == 0) 102732523Sbostic wakeup((caddr_t)dp); /* finish close protocol */ 102832523Sbostic goto loop; 10294743Swnj } 103032523Sbostic 103132523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 103232523Sbostic udasaerror(um); 103332523Sbostic goto out; 10344743Swnj } 103532523Sbostic 103632523Sbostic /* 103732523Sbostic * Get an MSCP packet, then figure out what to do. If 103832523Sbostic * we cannot get a command packet, the command ring may 103932523Sbostic * be too small: We should have at least as many command 104032523Sbostic * packets as credits, for best performance. 104132523Sbostic */ 104232523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) { 104332523Sbostic if (sc->sc_mi.mi_credits > MSCP_MINCREDITS && 104432523Sbostic (sc->sc_flags & SC_GRIPED) == 0) { 104532523Sbostic log(LOG_NOTICE, "uda%d: command ring too small\n", 104632523Sbostic um->um_ctlr); 104732523Sbostic sc->sc_flags |= SC_GRIPED;/* complain only once */ 104817553Skarels } 104932523Sbostic goto out; 10504743Swnj } 10514743Swnj 105232523Sbostic /* 105332523Sbostic * Bring the drive on line if it is not already. Get its status 105432523Sbostic * if we do not already have it. Otherwise just start the transfer. 105532523Sbostic */ 105632523Sbostic ui = udadinfo[udaunit(bp->b_dev)]; 105732523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 105832523Sbostic mp->mscp_opcode = M_OP_ONLINE; 105932523Sbostic goto common; 10604743Swnj } 106132523Sbostic if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) { 106232523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 106332523Sbostic common: 106432523Sbostic if (ui->ui_flags & UNIT_REQUEUE) panic("udastart"); 106532523Sbostic /* 106632523Sbostic * Take the drive off the controller queue. When the 106732523Sbostic * command finishes, make sure the drive is requeued. 106832523Sbostic */ 106932523Sbostic um->um_tab.b_actf = dp->b_forw; 107032523Sbostic dp->b_active = 0; 107132523Sbostic ui->ui_flags |= UNIT_REQUEUE; 107232523Sbostic mp->mscp_unit = ui->ui_slave; 107332523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 107432523Sbostic sc->sc_flags |= SC_STARTPOLL; 107532523Sbostic #ifdef POLLSTATS 107632523Sbostic sc->sc_ncmd++; 107725653Skarels #endif 107832523Sbostic goto loop; 107917553Skarels } 108032523Sbostic 108132523Sbostic pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)]; 108232523Sbostic mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; 10834743Swnj mp->mscp_unit = ui->ui_slave; 108432523Sbostic mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset; 108532523Sbostic pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)]; 108630536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 108732523Sbostic mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ? 108832523Sbostic (pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount; 108932523Sbostic /* mscp_cmdref is filled in by mscp_go() */ 10904743Swnj 10914743Swnj /* 109232523Sbostic * Drop the packet pointer into the `command' field so udadgo() 109332523Sbostic * can tell what to start. If ubago returns 1, we can do another 109432523Sbostic * transfer. If not, um_cmd will still point at mp, so we will 109532523Sbostic * know that we are waiting for resources. 10964743Swnj */ 109732523Sbostic um->um_cmd = (int)mp; 109832523Sbostic if (ubago(ui)) 109932523Sbostic goto loop; 110032523Sbostic 110132523Sbostic /* 110232523Sbostic * All done, or blocked in ubago(). If we managed to 110332523Sbostic * issue some commands, start up the beast. 110432523Sbostic */ 110532523Sbostic out: 110632523Sbostic if (sc->sc_flags & SC_STARTPOLL) { 110732523Sbostic #ifdef POLLSTATS 110832523Sbostic udastats.cmd[sc->sc_ncmd]++; 110932523Sbostic sc->sc_ncmd = 0; 111032523Sbostic #endif 111132523Sbostic i = ((struct udadevice *) um->um_addr)->udaip; 11124743Swnj } 111332523Sbostic sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL); 111432523Sbostic } 111532523Sbostic 111632523Sbostic /* 111732523Sbostic * Start a transfer. 111832523Sbostic * 111932523Sbostic * If we are not called from within udastart(), we must have been 112032523Sbostic * blocked, so call udastart to do more requests (if any). If 112132523Sbostic * this calls us again immediately we will not recurse, because 112232523Sbostic * that time we will be in udastart(). Clever.... 112332523Sbostic */ 112432523Sbostic udadgo(um) 112532523Sbostic register struct uba_ctlr *um; 112632523Sbostic { 112732523Sbostic struct uda_softc *sc = &uda_softc[um->um_ctlr]; 112832523Sbostic struct mscp *mp = (struct mscp *)um->um_cmd; 112932523Sbostic 113032523Sbostic um->um_tab.b_active++; /* another transfer going */ 113132523Sbostic 11324743Swnj /* 113332523Sbostic * Fill in the MSCP packet and move the buffer to the 113432523Sbostic * I/O wait queue. Mark the controller as no longer on 113532523Sbostic * the resource queue, and remember to initiate polling. 11364743Swnj */ 113732523Sbostic mp->mscp_seq.seq_buffer = (um->um_ubinfo & 0x3ffff) | 113832523Sbostic (UBAI_BDP(um->um_ubinfo) << 24); 113932523Sbostic mscp_go(&sc->sc_mi, mp, um->um_ubinfo); 114032523Sbostic um->um_cmd = 0; 114132523Sbostic um->um_ubinfo = 0; /* tyke it awye */ 114232523Sbostic sc->sc_flags |= SC_STARTPOLL; 114332523Sbostic #ifdef POLLSTATS 114432523Sbostic sc->sc_ncmd++; 114532523Sbostic #endif 114632523Sbostic if ((sc->sc_flags & SC_INSTART) == 0) 114732523Sbostic udastart(um); 11484743Swnj } 11494743Swnj 115032523Sbostic udaiodone(mi, bp, info) 115132523Sbostic register struct mscp_info *mi; 115232523Sbostic struct buf *bp; 115332523Sbostic int info; 115432523Sbostic { 115532523Sbostic register struct uba_ctlr *um = udaminfo[mi->mi_ctlr]; 115632523Sbostic 115732523Sbostic um->um_ubinfo = info; 115832523Sbostic ubadone(um); 115932523Sbostic biodone(bp); 116032523Sbostic if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab) 116132523Sbostic ubarelse(um->um_ubanum, &um->um_bdp); 116232523Sbostic um->um_tab.b_active--; /* another transfer done */ 116332523Sbostic } 116432523Sbostic 11654743Swnj /* 116632523Sbostic * The error bit was set in the controller status register. Gripe, 116732523Sbostic * reset the controller, requeue pending transfers. 11684743Swnj */ 116932523Sbostic udasaerror(um) 117032523Sbostic register struct uba_ctlr *um; 11714743Swnj { 117232523Sbostic 117332523Sbostic printf("uda%d: controller error, sa=%b\n", um->um_ctlr, 117432523Sbostic ((struct udadevice *) um->um_addr)->udasa, udasr_bits); 117532523Sbostic mscp_requeue(&uda_softc[um->um_ctlr].sc_mi); 117632523Sbostic (void) udainit(um->um_ctlr); 117732523Sbostic } 117832523Sbostic 117932523Sbostic /* 118032523Sbostic * Interrupt routine. Depending on the state of the controller, 118132523Sbostic * continue initialisation, or acknowledge command and response 118232523Sbostic * interrupts, and process responses. 118332523Sbostic */ 118432523Sbostic udaintr(ctlr) 118532523Sbostic int ctlr; 118632523Sbostic { 118732523Sbostic register struct uba_ctlr *um = udaminfo[ctlr]; 118832523Sbostic register struct uda_softc *sc = &uda_softc[ctlr]; 118932523Sbostic register struct udadevice *udaddr = (struct udadevice *) um->um_addr; 119032523Sbostic register struct uda *ud; 119132523Sbostic register struct mscp *mp; 11924743Swnj register int i; 11934743Swnj 119427254Skridle #ifdef VAX630 119532523Sbostic (void) spl5(); /* Qbus interrupt protocol is odd */ 119627254Skridle #endif 119732523Sbostic sc->sc_wticks = 0; /* reset interrupt watchdog */ 119832523Sbostic 119932523Sbostic /* 120032523Sbostic * Combinations during steps 1, 2, and 3: STEPnMASK 120132523Sbostic * corresponds to which bits should be tested; 120232523Sbostic * STEPnGOOD corresponds to the pattern that should 120332523Sbostic * appear after the interrupt from STEPn initialisation. 120432523Sbostic * All steps test the bits in ALLSTEPS. 120532523Sbostic */ 120632523Sbostic #define ALLSTEPS (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1) 120732523Sbostic 120832523Sbostic #define STEP1MASK (ALLSTEPS | UDA_IE | UDA_NCNRMASK) 120932523Sbostic #define STEP1GOOD (UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2) 121032523Sbostic 121132523Sbostic #define STEP2MASK (ALLSTEPS | UDA_IE | UDA_IVECMASK) 121232523Sbostic #define STEP2GOOD (UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2)) 121332523Sbostic 121432523Sbostic #define STEP3MASK ALLSTEPS 121532523Sbostic #define STEP3GOOD UDA_STEP4 121632523Sbostic 12174743Swnj switch (sc->sc_state) { 121832523Sbostic 121932523Sbostic case ST_IDLE: 122032523Sbostic /* 122132523Sbostic * Ignore unsolicited interrupts. 122232523Sbostic */ 122332523Sbostic log(LOG_WARNING, "uda%d: stray intr\n", ctlr); 12244743Swnj return; 12254743Swnj 122632523Sbostic case ST_STEP1: 122732523Sbostic /* 122832523Sbostic * Begin step two initialisation. 122932523Sbostic */ 123032523Sbostic if ((udaddr->udasa & STEP1MASK) != STEP1GOOD) { 123132523Sbostic i = 1; 123232523Sbostic initfailed: 123332523Sbostic printf("uda%d: init step %d failed, sa=%b\n", 123432523Sbostic ctlr, i, udaddr->udasa, udasr_bits); 123532523Sbostic sc->sc_state = ST_IDLE; 123632523Sbostic if (sc->sc_flags & SC_DOWAKE) { 123732523Sbostic sc->sc_flags &= ~SC_DOWAKE; 123832523Sbostic wakeup((caddr_t) sc); 123932523Sbostic } 12404743Swnj return; 12414743Swnj } 124232523Sbostic udaddr->udasa = (int) &sc->sc_uda->uda_ca.ca_rspdsc[0] | 124332523Sbostic (cpu == VAX_780 || cpu == VAX_8600 ? UDA_PI : 0); 124432523Sbostic sc->sc_state = ST_STEP2; 12454743Swnj return; 12464743Swnj 124732523Sbostic case ST_STEP2: 124832523Sbostic /* 124932523Sbostic * Begin step 3 initialisation. 125032523Sbostic */ 125132523Sbostic if ((udaddr->udasa & STEP2MASK) != STEP2GOOD) { 125232523Sbostic i = 2; 125332523Sbostic goto initfailed; 12544743Swnj } 125532523Sbostic udaddr->udasa = ((int) &sc->sc_uda->uda_ca.ca_rspdsc[0]) >> 16; 125632523Sbostic sc->sc_state = ST_STEP3; 12574743Swnj return; 12584743Swnj 125932523Sbostic case ST_STEP3: 126032523Sbostic /* 126132523Sbostic * Set controller characteristics (finish initialisation). 126232523Sbostic */ 126332523Sbostic if ((udaddr->udasa & STEP3MASK) != STEP3GOOD) { 126432523Sbostic i = 3; 126532523Sbostic goto initfailed; 12664743Swnj } 126732523Sbostic i = udaddr->udasa & 0xff; 126832523Sbostic if (i != sc->sc_micro) { 126932523Sbostic sc->sc_micro = i; 127032523Sbostic printf("uda%d: version %d model %d\n", 127132523Sbostic ctlr, i & 0xf, i >> 4); 127232523Sbostic } 127332523Sbostic 127417553Skarels /* 127532523Sbostic * Present the burst size, then remove it. Why this 127632523Sbostic * should be done this way, I have no idea. 127732523Sbostic * 127832523Sbostic * Note that this assumes udaburst[ctlr] > 0. 127917553Skarels */ 128032523Sbostic udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2; 12814743Swnj udaddr->udasa = UDA_GO; 128232523Sbostic printf("uda%d: DMA burst size set to %d\n", 128332523Sbostic ctlr, udaburst[ctlr]); 12844743Swnj 128532523Sbostic udainitds(ctlr); /* initialise data structures */ 128632523Sbostic 12874743Swnj /* 128832523Sbostic * Before we can get a command packet, we need some 128932523Sbostic * credits. Fake some up to keep mscp_getcp() happy, 129032523Sbostic * get a packet, and cancel all credits (the right 129132523Sbostic * number should come back in the response to the 129232523Sbostic * SCC packet). 12934743Swnj */ 129432523Sbostic sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1; 129532523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT); 129632523Sbostic if (mp == NULL) /* `cannot happen' */ 129732523Sbostic panic("udaintr"); 129832523Sbostic sc->sc_mi.mi_credits = 0; 129932523Sbostic mp->mscp_opcode = M_OP_SETCTLRC; 130032523Sbostic mp->mscp_unit = 0; 130132523Sbostic mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | 130232523Sbostic M_CF_THIS; 130332523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 130432523Sbostic i = udaddr->udaip; 130532523Sbostic sc->sc_state = ST_SETCHAR; 13064743Swnj return; 13074743Swnj 130832523Sbostic case ST_SETCHAR: 130932523Sbostic case ST_RUN: 131032523Sbostic /* 131132523Sbostic * Handle Set Ctlr Characteristics responses and operational 131232523Sbostic * responses (via mscp_dorsp). 131332523Sbostic */ 13144743Swnj break; 13154743Swnj 13164743Swnj default: 131732523Sbostic printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state); 131832523Sbostic panic("udastate"); 13194743Swnj } 13204743Swnj 132132523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 132232523Sbostic udasaerror(um); 132332523Sbostic return; 13244743Swnj } 13254743Swnj 132632523Sbostic ud = &uda[ctlr]; 132732523Sbostic 13284743Swnj /* 132932523Sbostic * Handle buffer purge requests. 133032523Sbostic * I have never seen these to work usefully, thus the log(). 13314743Swnj */ 13324743Swnj if (ud->uda_ca.ca_bdp) { 133332523Sbostic log(LOG_DEBUG, "uda%d: purge bdp %d\n", 133432523Sbostic ctlr, ud->uda_ca.ca_bdp); 133526372Skarels UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); 13364743Swnj ud->uda_ca.ca_bdp = 0; 133732523Sbostic udaddr->udasa = 0; /* signal purge complete */ 13384743Swnj } 13394743Swnj 13404743Swnj /* 134132523Sbostic * Check for response and command ring transitions. 13424743Swnj */ 13434743Swnj if (ud->uda_ca.ca_rspint) { 13444743Swnj ud->uda_ca.ca_rspint = 0; 134532523Sbostic mscp_dorsp(&sc->sc_mi); 13464743Swnj } 13474743Swnj if (ud->uda_ca.ca_cmdint) { 13484743Swnj ud->uda_ca.ca_cmdint = 0; 134932523Sbostic MSCP_DOCMD(&sc->sc_mi); 13504743Swnj } 135132523Sbostic udastart(um); 13524743Swnj } 13534743Swnj 135432523Sbostic #ifndef GENERIC_RAW 135532523Sbostic struct buf rudabuf[NRA]; 135632523Sbostic 13574743Swnj /* 135832523Sbostic * Read and write. 13594743Swnj */ 136032523Sbostic udaread(dev, uio) 136132523Sbostic dev_t dev; 136232523Sbostic struct uio *uio; 13634743Swnj { 13644743Swnj 136532523Sbostic return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_READ, 136632523Sbostic minphys, uio)); 136732523Sbostic } 13684743Swnj 136932523Sbostic udawrite(dev, uio) 137032523Sbostic dev_t dev; 137132523Sbostic struct uio *uio; 137232523Sbostic { 13734743Swnj 137432523Sbostic return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_WRITE, 137532523Sbostic minphys, uio)); 137632523Sbostic } 137732523Sbostic #endif /* GENERIC_RAW */ 13784743Swnj 137917553Skarels /* 138032523Sbostic * Initialise the various data structures that control the UDA50. 138117553Skarels */ 138232523Sbostic udainitds(ctlr) 138332523Sbostic int ctlr; 138432523Sbostic { 138532523Sbostic register struct uda *ud = &uda[ctlr]; 138632523Sbostic register struct uda *uud = uda_softc[ctlr].sc_uda; 138732523Sbostic register struct mscp *mp; 138832523Sbostic register int i; 13894743Swnj 139032523Sbostic for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) { 139132523Sbostic ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | 139232523Sbostic (long)&uud->uda_rsp[i].mscp_cmdref; 139332523Sbostic mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i]; 139432523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 13954743Swnj } 139632523Sbostic for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) { 139732523Sbostic ud->uda_ca.ca_cmddsc[i] = MSCP_INT | 139832523Sbostic (long)&uud->uda_cmd[i].mscp_cmdref; 139932523Sbostic mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i]; 140032523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 140132523Sbostic } 14024743Swnj } 14034743Swnj 14044743Swnj /* 140532523Sbostic * Handle an error datagram. All we do now is decode it. 14064743Swnj */ 140732523Sbostic udadgram(mi, mp) 140832523Sbostic struct mscp_info *mi; 140932523Sbostic struct mscp *mp; 14104743Swnj { 141117553Skarels 141232523Sbostic mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); 141332523Sbostic } 141417553Skarels 141532523Sbostic /* 141632523Sbostic * The Set Controller Characteristics command finished. 141732523Sbostic * Record the new state of the controller. 141832523Sbostic */ 141932523Sbostic udactlrdone(mi, mp) 142032523Sbostic register struct mscp_info *mi; 142132523Sbostic struct mscp *mp; 142232523Sbostic { 142332523Sbostic register struct uda_softc *sc = &uda_softc[mi->mi_ctlr]; 142417553Skarels 142532523Sbostic if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) 142632523Sbostic sc->sc_state = ST_RUN; 142732523Sbostic else { 142832523Sbostic printf("uda%d: SETCTLRC failed: ", 142932523Sbostic mi->mi_ctlr, mp->mscp_status); 143032523Sbostic mscp_printevent(mp); 143132523Sbostic sc->sc_state = ST_IDLE; 14324743Swnj } 143332523Sbostic if (sc->sc_flags & SC_DOWAKE) { 143432523Sbostic sc->sc_flags &= ~SC_DOWAKE; 143532523Sbostic wakeup((caddr_t)sc); 14366964Ssam } 14374743Swnj } 14384743Swnj 14394743Swnj /* 144032523Sbostic * Received a response from an as-yet unconfigured drive. Configure it 144132523Sbostic * in, if possible. 14424743Swnj */ 144332523Sbostic udaunconf(mi, mp) 144432523Sbostic struct mscp_info *mi; 144532523Sbostic register struct mscp *mp; 14464743Swnj { 14474743Swnj 144817553Skarels /* 144932523Sbostic * If it is a slave response, copy it to udaslavereply for 145032523Sbostic * udaslave() to look at. 145117553Skarels */ 145232523Sbostic if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && 145332523Sbostic (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) { 145432523Sbostic udaslavereply = *mp; 145532523Sbostic return (MSCP_DONE); 14564743Swnj } 145732523Sbostic 145832523Sbostic /* 145932523Sbostic * Otherwise, it had better be an available attention response. 146032523Sbostic */ 146132523Sbostic if (mp->mscp_opcode != M_OP_AVAILATTN) 146232523Sbostic return (MSCP_FAILED); 146332523Sbostic 146432523Sbostic /* do what autoconf does */ 146532523Sbostic return (MSCP_FAILED); /* not yet, arwhite, not yet */ 14664743Swnj } 14674743Swnj 146832523Sbostic /* 146932523Sbostic * A drive came on line. Check its type and size. Return DONE if 147032523Sbostic * we think the drive is truly on line. In any case, awaken anyone 147132523Sbostic * sleeping on the drive on-line-ness. 147232523Sbostic */ 147332523Sbostic udaonline(ui, mp) 147432523Sbostic register struct uba_device *ui; 147532523Sbostic struct mscp *mp; 14764743Swnj { 147732523Sbostic register struct ra_info *ra = &ra_info[ui->ui_unit]; 14784743Swnj 147932523Sbostic wakeup((caddr_t)&ui->ui_flags); 148032523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 148132523Sbostic printf("uda%d: attempt to bring ra%d on line failed: ", 148232523Sbostic ui->ui_ctlr, ui->ui_unit); 148332523Sbostic mscp_printevent(mp); 148432523Sbostic ra->ra_state = CLOSED; 148532523Sbostic return (MSCP_FAILED); 148632523Sbostic } 148732523Sbostic 148832523Sbostic ra->ra_state = OPENRAW; 148932523Sbostic ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize; 149032523Sbostic printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit, 149132523Sbostic ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize); 149232523Sbostic /* can now compute ncyl */ 149332523Sbostic ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks / 149432523Sbostic ra->ra_geom.rg_nsectors; 149532523Sbostic return (MSCP_DONE); 14964743Swnj } 14974743Swnj 149832523Sbostic /* 149932523Sbostic * We got some (configured) unit's status. Return DONE if it succeeded. 150032523Sbostic */ 150132523Sbostic udagotstatus(ui, mp) 150232523Sbostic register struct uba_device *ui; 150332523Sbostic register struct mscp *mp; 15044743Swnj { 15054743Swnj 150632523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 150732523Sbostic printf("uda%d: attempt to get status for ra%d failed: ", 150832523Sbostic ui->ui_ctlr, ui->ui_unit); 150932523Sbostic mscp_printevent(mp); 151032523Sbostic return (MSCP_FAILED); 151132523Sbostic } 151232523Sbostic /* record for (future) bad block forwarding and whatever else */ 151332523Sbostic uda_rasave(ui->ui_unit, mp, 1); 151432523Sbostic return (MSCP_DONE); 15154743Swnj } 15164743Swnj 151732523Sbostic /* 151832523Sbostic * A transfer failed. We get a chance to fix or restart it. 151932523Sbostic * Need to write the bad block forwaring code first.... 152032523Sbostic */ 152132523Sbostic /*ARGSUSED*/ 152232523Sbostic udaioerror(ui, mp, bp) 152332523Sbostic register struct uba_device *ui; 152432523Sbostic register struct mscp *mp; 152532523Sbostic struct buf *bp; 15264743Swnj { 15274743Swnj 152832523Sbostic if (mp->mscp_flags & M_EF_BBLKR) { 152932523Sbostic /* 153032523Sbostic * A bad block report. Eventually we will 153132523Sbostic * restart this transfer, but for now, just 153232523Sbostic * log it and give up. 153332523Sbostic */ 153432523Sbostic log(LOG_ERR, "ra%d: bad block report: %d%s\n", 153532523Sbostic ui->ui_unit, mp->mscp_seq.seq_lbn, 153632523Sbostic mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); 153732523Sbostic } else { 153832523Sbostic /* 153932523Sbostic * What the heck IS a `serious exception' anyway? 154032523Sbostic * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION 154132523Sbostic * FOR THEIR OWN CONTROLLERS. 154232523Sbostic */ 154332523Sbostic if (mp->mscp_flags & M_EF_SEREX) 154432523Sbostic log(LOG_ERR, "ra%d: serious exception reported\n", 154532523Sbostic ui->ui_unit); 15464743Swnj } 154732523Sbostic return (MSCP_FAILED); 15484743Swnj } 15494743Swnj 155032523Sbostic /* 155132523Sbostic * A replace operation finished. 155232523Sbostic */ 155332523Sbostic /*ARGSUSED*/ 155432523Sbostic udareplace(ui, mp) 155532523Sbostic struct uba_device *ui; 155632523Sbostic struct mscp *mp; 15574743Swnj { 155817553Skarels 155932523Sbostic panic("udareplace"); 15604743Swnj } 156117553Skarels 156232523Sbostic /* 156332523Sbostic * A bad block related operation finished. 156432523Sbostic */ 156532523Sbostic /*ARGSUSED*/ 156632523Sbostic udabb(ui, mp, bp) 156732523Sbostic struct uba_device *ui; 156832523Sbostic struct mscp *mp; 156932523Sbostic struct buf *bp; 157017553Skarels { 157117553Skarels 157232523Sbostic panic("udabb"); 157317553Skarels } 157417553Skarels 157532523Sbostic 157632523Sbostic /* 157732523Sbostic * I/O controls. 157832523Sbostic */ 157932523Sbostic udaioctl(dev, cmd, data, flag) 158012511Ssam dev_t dev; 158130536Skarels int cmd; 158230536Skarels caddr_t data; 158330536Skarels int flag; 158412511Ssam { 158532523Sbostic register int unit = udaunit(dev); 158630536Skarels register struct disklabel *lp; 158730536Skarels int error = 0; 158812511Ssam 158932523Sbostic lp = &udalabel[unit]; 159030536Skarels 159130536Skarels switch (cmd) { 159230536Skarels 159330536Skarels case DIOCGDINFO: 159430536Skarels *(struct disklabel *)data = *lp; 159530536Skarels break; 159630536Skarels 159730773Skarels case DIOCGPART: 159830773Skarels ((struct partinfo *)data)->disklab = lp; 159930773Skarels ((struct partinfo *)data)->part = 160032523Sbostic &lp->d_partitions[udapart(dev)]; 160130536Skarels break; 160230536Skarels 160330536Skarels case DIOCSDINFO: 160430536Skarels if ((flag & FWRITE) == 0) 160530536Skarels error = EBADF; 160630536Skarels else 1607*32574Skarels error = setdisklabel(lp, (struct disklabel *)data, 1608*32574Skarels ra_info[unit].ra_openpart); 160930536Skarels break; 161030536Skarels 1611*32574Skarels case DIOCWDINFO: 1612*32574Skarels if ((flag & FWRITE) == 0) 161332523Sbostic error = EBADF; 1614*32574Skarels else if ((error = setdisklabel(lp, (struct disklabel *)data, 1615*32574Skarels ra_info[unit].ra_openpart)) == 0) 1616*32574Skarels error = writedisklabel(dev, udastrategy, lp); 161730536Skarels break; 161830536Skarels 161932523Sbostic #ifdef notyet 162032523Sbostic case UDAIOCREPLACE: 162132523Sbostic /* 162232523Sbostic * Initiate bad block replacement for the given LBN. 162332523Sbostic * (Should we allow modifiers?) 162432523Sbostic */ 162532523Sbostic error = EOPNOTSUPP; 162632523Sbostic break; 162732523Sbostic 162832523Sbostic case UDAIOCGMICRO: 162932523Sbostic /* 163032523Sbostic * Return the microcode revision for the UDA50 running 163132523Sbostic * this drive. 163232523Sbostic */ 163332523Sbostic *(int *) data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro; 163432523Sbostic break; 163532523Sbostic #endif 163632523Sbostic 163730536Skarels default: 163830536Skarels error = ENOTTY; 163930536Skarels break; 164030536Skarels } 164132523Sbostic return (error); 164232523Sbostic } 164332523Sbostic 164432523Sbostic /* 164532523Sbostic * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) 164632523Sbostic * on that Unibus, and requeue outstanding I/O. 164732523Sbostic */ 164832523Sbostic udareset(uban) 164932523Sbostic int uban; 165032523Sbostic { 165132523Sbostic register struct uba_ctlr *um; 165232523Sbostic register struct uda_softc *sc; 165332523Sbostic register int ctlr; 165432523Sbostic 165532523Sbostic for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) { 165632523Sbostic if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban || 165732523Sbostic um->um_alive == 0) 165832523Sbostic continue; 165932523Sbostic printf(" uda%d", ctlr); 166032523Sbostic 166132523Sbostic /* 166232523Sbostic * Our BDP (if any) is gone; our command (if any) is 166332523Sbostic * flushed; the device is no longer mapped; and the 166432523Sbostic * UDA50 is not yet initialised. 166532523Sbostic */ 166632523Sbostic if (um->um_bdp) { 166732523Sbostic printf("<%d>", UBAI_BDP(um->um_bdp)); 166832523Sbostic um->um_bdp = 0; 166932523Sbostic } 167032523Sbostic um->um_ubinfo = 0; 167132523Sbostic um->um_cmd = 0; 167232523Sbostic sc->sc_flags &= ~SC_MAPPED; 167332523Sbostic sc->sc_state = ST_IDLE; 167432523Sbostic 167532523Sbostic /* reset queues and requeue pending transfers */ 167632523Sbostic mscp_requeue(&sc->sc_mi); 167732523Sbostic 167832523Sbostic /* 167932523Sbostic * If it fails to initialise we will notice later and 168032523Sbostic * try again (and again...). Do not call udastart() 168132523Sbostic * here; it will be done after the controller finishes 168232523Sbostic * initialisation. 168332523Sbostic */ 168432523Sbostic if (udainit(ctlr)) 168532523Sbostic printf(" (hung)"); 168632523Sbostic } 168732523Sbostic } 168832523Sbostic 168932523Sbostic /* 169032523Sbostic * Watchdog timer: If the controller is active, and no interrupts 169132523Sbostic * have occurred for 30 seconds, assume it has gone away. 169232523Sbostic */ 169332523Sbostic udawatch() 169432523Sbostic { 169532523Sbostic register int i; 169632523Sbostic register struct uba_ctlr *um; 169732523Sbostic register struct uda_softc *sc; 169832523Sbostic 169932523Sbostic timeout(udawatch, (caddr_t) 0, hz); /* every second */ 170032523Sbostic for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) { 170132523Sbostic if ((um = udaminfo[i]) == 0 || !um->um_alive) 170232523Sbostic continue; 170332523Sbostic if (sc->sc_state == ST_IDLE) 170432523Sbostic continue; 170532523Sbostic if (sc->sc_state == ST_RUN && !um->um_tab.b_active) 170632523Sbostic sc->sc_wticks = 0; 170732523Sbostic else if (++sc->sc_wticks >= 30) { 170832523Sbostic sc->sc_wticks = 0; 170932523Sbostic printf("uda%d: lost interrupt\n", i); 171032523Sbostic ubareset(um->um_ubanum); 171132523Sbostic } 171232523Sbostic } 171332523Sbostic } 171432523Sbostic 171532523Sbostic /* 171632523Sbostic * Do a panic dump. We set up the controller for one command packet 171732523Sbostic * and one response packet, for which we use `struct uda1'. 171832523Sbostic */ 171932523Sbostic struct uda1 { 172032523Sbostic struct uda1ca uda1_ca; /* communications area */ 172132523Sbostic struct mscp uda1_rsp; /* response packet */ 172232523Sbostic struct mscp uda1_cmd; /* command packet */ 172332523Sbostic } uda1; 172432523Sbostic 172532523Sbostic #define DBSIZE 32 /* dump 16K at a time */ 172632523Sbostic 172732523Sbostic udadump(dev) 172832523Sbostic dev_t dev; 172932523Sbostic { 173032523Sbostic struct udadevice *udaddr; 173132523Sbostic struct uda1 *ud_ubaddr; 173232523Sbostic char *start; 173332523Sbostic int num, blk, unit, maxsz, blkoff, reg; 173432523Sbostic struct partition *pp; 173532523Sbostic register struct uba_regs *uba; 173632523Sbostic register struct uba_device *ui; 173732523Sbostic register struct uda1 *ud; 173832523Sbostic register struct pte *io; 173932523Sbostic register int i; 174032523Sbostic 174132523Sbostic /* 174232523Sbostic * Make sure the device is a reasonable place on which to dump. 174332523Sbostic */ 174432523Sbostic unit = udaunit(dev); 174532523Sbostic if (unit >= NRA) 174632523Sbostic return (ENXIO); 174732523Sbostic #define phys(cast, addr) ((cast) ((int) addr & 0x7fffffff)) 174832523Sbostic ui = phys(struct uba_device *, udadinfo[unit]); 174932523Sbostic if (ui == NULL || ui->ui_alive == 0) 175032523Sbostic return (ENXIO); 175132523Sbostic 175232523Sbostic /* 175332523Sbostic * Find and initialise the UBA; get the physical address of the 175432523Sbostic * device registers, and of communications area and command and 175532523Sbostic * response packet. 175632523Sbostic */ 175732523Sbostic uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 175832523Sbostic ubainit(uba); 175932523Sbostic udaddr = (struct udadevice *)ui->ui_physaddr; 176032523Sbostic ud = phys(struct uda1 *, &uda1); 176132523Sbostic 176232523Sbostic /* 176332523Sbostic * Map the ca+packets into Unibus I/O space so the UDA50 can get 176432523Sbostic * at them. Use the registers at the end of the Unibus map (since 176532523Sbostic * we will use the registers at the beginning to map the memory 176632523Sbostic * we are dumping). 176732523Sbostic */ 176832523Sbostic num = btoc(sizeof(struct uda1)) + 1; 176932523Sbostic reg = NUBMREG - num; 177032523Sbostic io = &uba->uba_map[reg]; 177132523Sbostic for (i = 0; i < num; i++) 177232523Sbostic *(int *)io++ = UBAMR_MRV | (btop(ud) + i); 177332523Sbostic ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); 177432523Sbostic 177532523Sbostic /* 177632523Sbostic * Initialise the controller, with one command and one response 177732523Sbostic * packet. 177832523Sbostic */ 177932523Sbostic udaddr->udaip = 0; 178032523Sbostic if (udadumpwait(udaddr, UDA_STEP1)) 178132523Sbostic return (EFAULT); 178232523Sbostic udaddr->udasa = UDA_ERR; 178332523Sbostic if (udadumpwait(udaddr, UDA_STEP2)) 178432523Sbostic return (EFAULT); 178532523Sbostic udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; 178632523Sbostic if (udadumpwait(udaddr, UDA_STEP3)) 178732523Sbostic return (EFAULT); 178832523Sbostic udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; 178932523Sbostic if (udadumpwait(udaddr, UDA_STEP4)) 179032523Sbostic return (EFAULT); 179132523Sbostic uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff; 179232523Sbostic udaddr->udasa = UDA_GO; 179332523Sbostic 179432523Sbostic /* 179532523Sbostic * Set up the command and response descriptor, then set the 179632523Sbostic * controller characteristics and bring the drive on line. 179732523Sbostic * Note that all uninitialised locations in uda1_cmd are zero. 179832523Sbostic */ 179932523Sbostic ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; 180032523Sbostic ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; 180132523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ 180232523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ 180332523Sbostic if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) 180432523Sbostic return (EFAULT); 180532523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 180632523Sbostic if (udadumpcmd(M_OP_ONLINE, ud, ui)) 180732523Sbostic return (EFAULT); 180832523Sbostic 180932523Sbostic pp = phys(struct partition *, 181032523Sbostic &udalabel[unit].d_partitions[udapart(dev)]); 181132523Sbostic maxsz = pp->p_size; 181232523Sbostic blkoff = pp->p_offset; 181332523Sbostic 181432523Sbostic /* 181532523Sbostic * Dump all of physical memory, or as much as will fit in the 181632523Sbostic * space provided. 181732523Sbostic */ 181832523Sbostic start = 0; 181932523Sbostic num = maxfree; 182032523Sbostic if (dumplo < 0) 182132523Sbostic return (EINVAL); 182232523Sbostic if (dumplo + num >= maxsz) 182332523Sbostic num = maxsz - dumplo; 182432523Sbostic blkoff += dumplo; 182532523Sbostic 182632523Sbostic /* 182732523Sbostic * Write out memory, DBSIZE pages at a time. 182832523Sbostic * N.B.: this code depends on the fact that the sector 182932523Sbostic * size == the page size. 183032523Sbostic */ 183132523Sbostic while (num > 0) { 183232523Sbostic blk = num > DBSIZE ? DBSIZE : num; 183332523Sbostic io = uba->uba_map; 183432523Sbostic /* 183532523Sbostic * Map in the pages to write, leaving an invalid entry 183632523Sbostic * at the end to guard against wild Unibus transfers. 183732523Sbostic * Then do the write. 183832523Sbostic */ 183932523Sbostic for (i = 0; i < blk; i++) 184032523Sbostic *(int *) io++ = UBAMR_MRV | (btop(start) + i); 184132523Sbostic *(int *) io = 0; 184232523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 184332523Sbostic ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; 184432523Sbostic ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; 184532523Sbostic if (udadumpcmd(M_OP_WRITE, ud, ui)) 184632523Sbostic return (EIO); 184732523Sbostic start += blk << PGSHIFT; 184832523Sbostic num -= blk; 184932523Sbostic } 185032523Sbostic return (0); /* made it! */ 185132523Sbostic } 185232523Sbostic 185332523Sbostic /* 185432523Sbostic * Wait for some of the bits in `bits' to come on. If the error bit 185532523Sbostic * comes on, or ten seconds pass without response, return true (error). 185632523Sbostic */ 185732523Sbostic udadumpwait(udaddr, bits) 185832523Sbostic register struct udadevice *udaddr; 185932523Sbostic register int bits; 186032523Sbostic { 186132523Sbostic register int timo = todr() + 1000; 186232523Sbostic 186332523Sbostic while ((udaddr->udasa & bits) == 0) { 186432523Sbostic if (udaddr->udasa & UDA_ERR) { 186532523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 186632523Sbostic return (1); 186732523Sbostic } 186832523Sbostic if (todr() >= timo) { 186932523Sbostic printf("timeout\ndump "); 187032523Sbostic return (1); 187132523Sbostic } 187232523Sbostic } 187330536Skarels return (0); 187430536Skarels } 187530536Skarels 187632523Sbostic /* 187732523Sbostic * Feed a command to the UDA50, wait for its response, and return 187832523Sbostic * true iff something went wrong. 187932523Sbostic */ 188032523Sbostic udadumpcmd(op, ud, ui) 188132523Sbostic int op; 188232523Sbostic register struct uda1 *ud; 188332523Sbostic struct uba_device *ui; 188432523Sbostic { 188532523Sbostic register struct udadevice *udaddr; 188632523Sbostic register int n; 188732523Sbostic #define mp (&ud->uda1_rsp) 188832523Sbostic 188932523Sbostic udaddr = (struct udadevice *) ui->ui_physaddr; 189032523Sbostic ud->uda1_cmd.mscp_opcode = op; 189132523Sbostic ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; 189232523Sbostic ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; 189332523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 189432523Sbostic ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; 189532523Sbostic if (udaddr->udasa & UDA_ERR) { 189632523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 189732523Sbostic return (1); 189832523Sbostic } 189932523Sbostic n = udaddr->udaip; 190032523Sbostic n = todr() + 1000; 190132523Sbostic for (;;) { 190232523Sbostic if (todr() > n) { 190332523Sbostic printf("timeout\ndump "); 190432523Sbostic return (1); 190532523Sbostic } 190632523Sbostic if (ud->uda1_ca.ca_cmdint) 190732523Sbostic ud->uda1_ca.ca_cmdint = 0; 190832523Sbostic if (ud->uda1_ca.ca_rspint == 0) 190932523Sbostic continue; 191032523Sbostic ud->uda1_ca.ca_rspint = 0; 191132523Sbostic if (mp->mscp_opcode == (op | M_OP_END)) 191232523Sbostic break; 191332523Sbostic printf("\n"); 191432523Sbostic switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { 191532523Sbostic 191632523Sbostic case MSCPT_SEQ: 191732523Sbostic printf("sequential"); 191832523Sbostic break; 191932523Sbostic 192032523Sbostic case MSCPT_DATAGRAM: 192132523Sbostic mscp_decodeerror("uda", ui->ui_ctlr, mp); 192232523Sbostic printf("datagram"); 192332523Sbostic break; 192432523Sbostic 192532523Sbostic case MSCPT_CREDITS: 192632523Sbostic printf("credits"); 192732523Sbostic break; 192832523Sbostic 192932523Sbostic case MSCPT_MAINTENANCE: 193032523Sbostic printf("maintenance"); 193132523Sbostic break; 193232523Sbostic 193332523Sbostic default: 193432523Sbostic printf("unknown (type 0x%x)", 193532523Sbostic MSCP_MSGTYPE(mp->mscp_msgtc)); 193632523Sbostic break; 193732523Sbostic } 193832523Sbostic printf(" ignored\ndump "); 193932523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 194032523Sbostic } 194132523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 194232523Sbostic printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, 194332523Sbostic mp->mscp_opcode, mp->mscp_status); 194432523Sbostic return (1); 194532523Sbostic } 194632523Sbostic return (0); 194732523Sbostic #undef mp 194832523Sbostic } 194932523Sbostic 195032523Sbostic /* 195132523Sbostic * Return the size of a partition, if known, or -1 if not. 195232523Sbostic */ 195332523Sbostic udasize(dev) 195430536Skarels dev_t dev; 195530536Skarels { 195632523Sbostic register int unit = udaunit(dev); 195730536Skarels register struct uba_device *ui; 195832523Sbostic register struct size *st; 195930536Skarels 196032523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == NULL || 196132523Sbostic ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 || 196232523Sbostic ra_info[unit].ra_state != OPEN) 196312511Ssam return (-1); 196432523Sbostic return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size); 196512511Ssam } 196617553Skarels 196730536Skarels #ifdef COMPAT_42 196832523Sbostic /* 196932523Sbostic * Tables mapping unlabelled drives. 197032523Sbostic */ 197130536Skarels struct size { 197230536Skarels daddr_t nblocks; 197330536Skarels daddr_t blkoff; 197432523Sbostic } ra25_sizes[8] = { 197530536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 197630536Skarels 10032, 15884, /* B=blk 15884 thru 49323 */ 197730536Skarels -1, 0, /* C=blk 0 thru end */ 197830536Skarels 0, 0, /* D=blk 340670 thru 356553 */ 197930536Skarels 0, 0, /* E=blk 356554 thru 412489 */ 198030536Skarels 0, 0, /* F=blk 412490 thru end */ 198130536Skarels -1, 25916, /* G=blk 49324 thru 131403 */ 198230536Skarels 0, 0, /* H=blk 131404 thru end */ 198332523Sbostic }, rx50_sizes[8] = { 198432523Sbostic 800, 0, /* A=blk 0 thru 799 */ 198532523Sbostic 0, 0, 198632523Sbostic -1, 0, /* C=blk 0 thru end */ 198732523Sbostic 0, 0, 198832523Sbostic 0, 0, 198932523Sbostic 0, 0, 199032523Sbostic 0, 0, 199132523Sbostic 0, 0, 199230536Skarels }, rd52_sizes[8] = { 199330536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 199430536Skarels 9766, 15884, /* B=blk 15884 thru 25649 */ 199530536Skarels -1, 0, /* C=blk 0 thru end */ 199630536Skarels 0, 0, /* D=unused */ 199730536Skarels 0, 0, /* E=unused */ 199830536Skarels 0, 0, /* F=unused */ 199930536Skarels -1, 25650, /* G=blk 25650 thru end */ 200030536Skarels 0, 0, /* H=unused */ 200130536Skarels }, rd53_sizes[8] = { 200230536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 200330536Skarels 33440, 15884, /* B=blk 15884 thru 49323 */ 200430536Skarels -1, 0, /* C=blk 0 thru end */ 200530536Skarels 0, 0, /* D=unused */ 200630536Skarels 33440, 0, /* E=blk 0 thru 33439 */ 200730536Skarels -1, 33440, /* F=blk 33440 thru end */ 200830536Skarels -1, 49324, /* G=blk 49324 thru end */ 200930536Skarels -1, 15884, /* H=blk 15884 thru end */ 201030536Skarels }, ra60_sizes[8] = { 201130536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 201230536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 201330536Skarels 400176, 0, /* C=sectors 0 thru 400175 */ 201430536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 201530536Skarels 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ 201630536Skarels 350852, 49324, /* F=sectors 49324 thru 400175 */ 201730536Skarels 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ 201830536Skarels 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */ 201930536Skarels }, ra80_sizes[8] = { 202030536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 202130536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 202230536Skarels 242606, 0, /* C=sectors 0 thru 242605 */ 202330536Skarels 0, 0, /* D=unused */ 202430536Skarels 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ 202530536Skarels 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ 202630536Skarels 192696, 49910, /* G=sectors 49910 thru 242605 */ 202730536Skarels 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */ 202830536Skarels }, ra81_sizes[8] ={ 202930536Skarels /* 203030536Skarels * These are the new standard partition sizes for ra81's. 203130536Skarels * An RA_COMPAT system is compiled with D, E, and F corresponding 203230536Skarels * to the 4.2 partitions for G, H, and F respectively. 203330536Skarels */ 203430536Skarels #ifndef UCBRA 203530536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 203630536Skarels 66880, 16422, /* B=sectors 16422 thru 83301 */ 203730536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 203830536Skarels #ifdef RA_COMPAT 203930536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 204030536Skarels 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ 204130536Skarels 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */ 204230536Skarels #else 204330536Skarels 15884, 375564, /* D=sectors 375564 thru 391447 */ 204430536Skarels 307200, 391986, /* E=sectors 391986 thru 699185 */ 204530536Skarels 191352, 699720, /* F=sectors 699720 thru 891071 */ 204630536Skarels #endif RA_COMPAT 204730536Skarels 515508, 375564, /* G=sectors 375564 thru 891071 */ 204830536Skarels 291346, 83538, /* H=sectors 83538 thru 374883 */ 204930536Skarels 205030536Skarels /* 205130536Skarels * These partitions correspond to the sizes used by sites at Berkeley, 205230536Skarels * and by those sites that have received copies of the Berkeley driver 205330536Skarels * with deltas 6.2 or greater (11/15/83). 205430536Skarels */ 205530536Skarels #else UCBRA 205630536Skarels 205730536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 205830536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 205930536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 206030536Skarels 15884, 242606, /* D=sectors 242606 thru 258489 */ 206130536Skarels 307200, 258490, /* E=sectors 258490 thru 565689 */ 206230536Skarels 325382, 565690, /* F=sectors 565690 thru 891071 */ 206330536Skarels 648466, 242606, /* G=sectors 242606 thru 891071 */ 206430536Skarels 193282, 49324, /* H=sectors 49324 thru 242605 */ 206530536Skarels 206630536Skarels #endif UCBRA 206730536Skarels }; 206830536Skarels 206932523Sbostic /* 207032523Sbostic * Drive type index decoding table. `ut_name' is null iff the 207132523Sbostic * type is not known. 207232523Sbostic */ 207332523Sbostic struct udatypes { 207432523Sbostic char *ut_name; /* drive type name */ 207532523Sbostic struct size *ut_sizes; /* partition tables */ 207632523Sbostic int ut_nsectors, ut_ntracks, ut_ncylinders; 207732523Sbostic } udatypes[] = { 207832523Sbostic NULL, NULL, 207932523Sbostic 0, 0, 0, 208032523Sbostic "ra80", ra80_sizes, /* 1 = ra80 */ 208132523Sbostic 31, 14, 559, 208232523Sbostic "rc25-removable", ra25_sizes, /* 2 = rc25-r */ 208332523Sbostic 42, 4, 302, 208432523Sbostic "rc25-fixed", ra25_sizes, /* 3 = rc25-f */ 208532523Sbostic 42, 4, 302, 208632523Sbostic "ra60", ra60_sizes, /* 4 = ra60 */ 208732523Sbostic 42, 4, 2382, 208832523Sbostic "ra81", ra81_sizes, /* 5 = ra81 */ 208932523Sbostic 51, 14, 1248, 209032523Sbostic NULL, NULL, /* 6 = ? */ 209132523Sbostic 0, 0, 0, 209232523Sbostic "rx50", rx50_sizes, /* 7 = rx50 */ 209332523Sbostic 10, 1, 80, 209432523Sbostic "rd52", rd52_sizes, /* 8 = rd52 */ 209532523Sbostic 18, 7, 480, 209632523Sbostic "rd53", rd53_sizes, /* 9 = rd53 */ 209732523Sbostic 18, 8, 963, 209832523Sbostic }; 209932523Sbostic 210032523Sbostic #define NTYPES (sizeof(udatypes) / sizeof(*udatypes)) 210132523Sbostic 210232523Sbostic udamaptype(unit, lp) 210332523Sbostic int unit; 210430536Skarels register struct disklabel *lp; 210530536Skarels { 210632523Sbostic register struct udatypes *ut; 210732523Sbostic register struct size *sz; 210830536Skarels register struct partition *pp; 210932523Sbostic register char *p; 211032523Sbostic register int i; 211132523Sbostic register struct ra_info *ra = &ra_info[unit]; 211230536Skarels 211332523Sbostic lp->d_secsize = 512; 211432523Sbostic lp->d_secperunit = ra->ra_dsize; 211532523Sbostic if ((u_long)ra->ra_type >= NTYPES) { 211632523Sbostic printf("ra%d: don't have a partition table for", unit); 211732523Sbostic mscp_printmedia(ra->ra_mediaid); 211832523Sbostic lp->d_nsectors = ra->ra_geom.rg_nsectors; 211932523Sbostic lp->d_ntracks = ra->ra_geom.rg_ntracks; 212032523Sbostic lp->d_ncylinders = ra->ra_geom.rg_ncyl; 212132523Sbostic printf(";\nusing (t,s,c)=(%d,%d,%d)\n", lp->d_nsectors, 212232523Sbostic lp->d_ntracks, lp->d_ncylinders); 212332523Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 212432523Sbostic lp->d_typename[0] = 'r'; 212532523Sbostic lp->d_typename[1] = 'a'; 212632523Sbostic lp->d_typename[2] = '?'; 212732523Sbostic lp->d_typename[3] = '?'; 212832523Sbostic lp->d_typename[4] = 0; 212930536Skarels lp->d_npartitions = 1; 213030536Skarels lp->d_partitions[0].p_offset = 0; 213130536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 213230536Skarels return (0); 213330536Skarels } 213432523Sbostic ut = &udatypes[ra->ra_type]; 213532523Sbostic p = ut->ut_name; 213632523Sbostic for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++) 213732523Sbostic lp->d_typename[i] = *p++; 213832523Sbostic lp->d_typename[i] = 0; 213932523Sbostic sz = ut->ut_sizes; 214032523Sbostic /* GET nsectors, ntracks, ncylinders FROM SAVED GEOMETRY? */ 214132523Sbostic lp->d_nsectors = ut->ut_nsectors; 214232523Sbostic lp->d_ntracks = ut->ut_ntracks; 214332523Sbostic lp->d_ncylinders = ut->ut_ncylinders; 214430536Skarels lp->d_npartitions = 8; 214530536Skarels lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 214632523Sbostic for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) { 214732523Sbostic pp->p_offset = sz->blkoff; 214832523Sbostic if ((pp->p_size = sz->nblocks) == (u_long)-1) 214932523Sbostic pp->p_size = ra->ra_dsize - sz->blkoff; 215030536Skarels } 215130536Skarels return (1); 215230536Skarels } 215332523Sbostic #endif /* COMPAT_42 */ 215432523Sbostic #endif /* NUDA > 0 */ 2155