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*33195Sbostic * @(#)uda.c 7.11 (Berkeley) 01/02/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 */ 164*33195Sbostic #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; 17932523Sbostic u_long ra_openpart; /* partitions open */ 18032523Sbostic u_long ra_bopenpart; /* block partitions open */ 18132523Sbostic u_long ra_copenpart; /* character partitions open */ 18232523Sbostic } ra_info[NRA]; 18317553Skarels 18430536Skarels /* 18530536Skarels * Software state, per drive 18630536Skarels */ 18730536Skarels #define CLOSED 0 18830536Skarels #define WANTOPEN 1 18930536Skarels #define RDLABEL 2 19030536Skarels #define OPEN 3 19130536Skarels #define OPENRAW 4 19217553Skarels 19332523Sbostic /* 19432523Sbostic * Definition of the driver for autoconf. 19532523Sbostic */ 19632523Sbostic int udaprobe(), udaslave(), udaattach(), udadgo(), udaintr(); 19732523Sbostic struct uba_ctlr *udaminfo[NUDA]; 19832523Sbostic struct uba_device *udadinfo[NRA]; 19932523Sbostic struct disklabel udalabel[NRA]; 20017553Skarels 20132523Sbostic u_short udastd[] = { 0772150, 0772550, 0777550, 0 }; 20232523Sbostic struct uba_driver udadriver = 20332523Sbostic { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda", 20432523Sbostic udaminfo }; 20517553Skarels 20632523Sbostic /* 20732523Sbostic * More driver definitions, for generic MSCP code. 20832523Sbostic */ 20932523Sbostic int udadgram(), udactlrdone(), udaunconf(), udaiodone(); 21032523Sbostic int udaonline(), udagotstatus(), udaioerror(), udareplace(), udabb(); 2114743Swnj 21232523Sbostic struct buf udautab[NRA]; /* per drive transfer queue */ 2134743Swnj 21432523Sbostic struct mscp_driver udamscpdriver = 21532523Sbostic { MAXUNIT, NRA, UNITSHIFT, udautab, udadinfo, 21632523Sbostic udadgram, udactlrdone, udaunconf, udaiodone, 21732523Sbostic udaonline, udagotstatus, udareplace, udaioerror, udabb, 21832523Sbostic "uda", "ra" }; 21932523Sbostic 22032523Sbostic /* 22132523Sbostic * Miscellaneous private variables. 22232523Sbostic */ 22332523Sbostic char udasr_bits[] = UDASR_BITS; 22432523Sbostic 22532523Sbostic struct uba_device *udaip[NUDA][MAXUNIT]; 22632523Sbostic /* inverting pointers: ctlr & unit => Unibus 22732523Sbostic device pointer */ 22832523Sbostic 22932523Sbostic int udaburst[NUDA] = { 0 }; /* burst size, per UDA50, zero => default; 23032523Sbostic in data space so patchable via adb */ 23132523Sbostic 23232523Sbostic struct mscp udaslavereply; /* get unit status response packet, set 23332523Sbostic for udaslave by udaunconf, via udaintr */ 23432523Sbostic 23532523Sbostic static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr 23632523Sbostic info to slave routine; instead, we remember 23732523Sbostic the last ctlr argument to probe */ 23832523Sbostic 23932523Sbostic int udawstart, udawatch(); /* watchdog timer */ 24032523Sbostic 24132523Sbostic /* 24232523Sbostic * Externals 24332523Sbostic */ 24432523Sbostic int wakeup(); 24532523Sbostic int hz; 24632523Sbostic 24732523Sbostic /* 24832523Sbostic * Poke at a supposed UDA50 to see if it is there. 24932523Sbostic * This routine duplicates some of the code in udainit() only 25032523Sbostic * because autoconf has not set up the right information yet. 25132523Sbostic * We have to do everything `by hand'. 25232523Sbostic */ 25332523Sbostic udaprobe(reg, ctlr, um) 2544743Swnj caddr_t reg; 2554743Swnj int ctlr; 25632523Sbostic struct uba_ctlr *um; 2574743Swnj { 2584743Swnj register int br, cvec; 25932523Sbostic register struct uda_softc *sc; 26032523Sbostic register struct udadevice *udaddr; 26132523Sbostic register struct mscp_info *mi; 26232523Sbostic int timeout, tries; 2634743Swnj 26432523Sbostic #ifdef VAX750 26532523Sbostic /* 26632523Sbostic * The UDA50 wants to share BDPs on 750s, but not on 780s or 26732523Sbostic * 8600s. (730s have no BDPs anyway.) Toward this end, we 26832523Sbostic * here set the `keep bdp' flag in the per-driver information 26932523Sbostic * if this is a 750. (We just need to do it once, but it is 27032523Sbostic * easiest to do it now, for each UDA50.) 27132523Sbostic */ 27232523Sbostic if (cpu == VAX_750) 27332523Sbostic udadriver.ud_keepbdp = 1; 27432523Sbostic #endif 27517553Skarels 27632523Sbostic probeum = um; /* remember for udaslave() */ 2774743Swnj #ifdef lint 27832523Sbostic br = 0; cvec = br; br = cvec; udaintr(0); 2794743Swnj #endif 28032523Sbostic /* 28132523Sbostic * Set up the controller-specific generic MSCP driver info. 28232523Sbostic * Note that this should really be done in the (nonexistent) 28332523Sbostic * controller attach routine. 28432523Sbostic */ 28532523Sbostic sc = &uda_softc[ctlr]; 28632523Sbostic mi = &sc->sc_mi; 28732523Sbostic mi->mi_md = &udamscpdriver; 28832523Sbostic mi->mi_ctlr = um->um_ctlr; 28932523Sbostic mi->mi_tab = &um->um_tab; 29032523Sbostic mi->mi_ip = udaip[ctlr]; 29132523Sbostic mi->mi_cmd.mri_size = NCMD; 29232523Sbostic mi->mi_cmd.mri_desc = uda[ctlr].uda_ca.ca_cmddsc; 29332523Sbostic mi->mi_cmd.mri_ring = uda[ctlr].uda_cmd; 29432523Sbostic mi->mi_rsp.mri_size = NRSP; 29532523Sbostic mi->mi_rsp.mri_desc = uda[ctlr].uda_ca.ca_rspdsc; 29632523Sbostic mi->mi_rsp.mri_ring = uda[ctlr].uda_rsp; 29732523Sbostic mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab; 29832523Sbostic 29932523Sbostic /* 30032523Sbostic * More controller specific variables. Again, this should 30132523Sbostic * be in the controller attach routine. 30232523Sbostic */ 30332523Sbostic if (udaburst[ctlr] == 0) 30432523Sbostic udaburst[ctlr] = DEFAULT_BURST; 30532523Sbostic 30632523Sbostic /* 30732523Sbostic * Get an interrupt vector. Note that even if the controller 30832523Sbostic * does not respond, we keep the vector. This is not a serious 30932523Sbostic * problem; but it would be easily fixed if we had a controller 31032523Sbostic * attach routine. Sigh. 31132523Sbostic */ 31232523Sbostic sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 31317553Skarels udaddr = (struct udadevice *) reg; 31417553Skarels 31532523Sbostic /* 31632523Sbostic * Initialise the controller (partially). The UDA50 programmer's 31732523Sbostic * manual states that if initialisation fails, it should be retried 31832523Sbostic * at least once, but after a second failure the port should be 31932523Sbostic * considered `down'; it also mentions that the controller should 32032523Sbostic * initialise within ten seconds. Or so I hear; I have not seen 32132523Sbostic * this manual myself. 32232523Sbostic */ 32332523Sbostic tries = 0; 32432523Sbostic again: 32532523Sbostic udaddr->udaip = 0; /* start initialisation */ 32632523Sbostic timeout = todr() + 1000; /* timeout in 10 seconds */ 32732523Sbostic while ((udaddr->udasa & UDA_STEP1) == 0) 32832523Sbostic if (todr() > timeout) 32932523Sbostic goto bad; 33032523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 33132523Sbostic (sc->sc_ivec >> 2); 33232523Sbostic while ((udaddr->udasa & UDA_STEP2) == 0) 33332523Sbostic if (todr() > timeout) 33432523Sbostic goto bad; 33532523Sbostic 33632523Sbostic /* should have interrupted by now */ 33732523Sbostic #ifdef VAX630 33832523Sbostic if (cpu == VAX_630) 33932523Sbostic br = 0x15; /* screwy interrupt structure */ 34027254Skridle #endif 34132523Sbostic return (sizeof (struct udadevice)); 34232523Sbostic bad: 34332523Sbostic if (++tries < 2) 34432523Sbostic goto again; 34532523Sbostic return (0); 3464743Swnj } 3474743Swnj 34832523Sbostic /* 34932523Sbostic * Find a slave. We allow wildcard slave numbers (something autoconf 35032523Sbostic * is not really prepared to deal with); and we need to know the 35132523Sbostic * controller number to talk to the UDA. For the latter, we keep 35232523Sbostic * track of the last controller probed, since a controller probe 35332523Sbostic * immediately precedes all slave probes for that controller. For the 35432523Sbostic * former, we simply put the unit number into ui->ui_slave after we 35532523Sbostic * have found one. 35632523Sbostic * 35732523Sbostic * Note that by the time udaslave is called, the interrupt vector 35832523Sbostic * for the UDA50 has been set up (so that udaunconf() will be called). 35932523Sbostic */ 36032523Sbostic udaslave(ui, reg) 36132523Sbostic register struct uba_device *ui; 3624743Swnj caddr_t reg; 3634743Swnj { 36432523Sbostic register struct uba_ctlr *um = probeum; 36532523Sbostic register struct mscp *mp; 36632523Sbostic register struct uda_softc *sc; 36732523Sbostic register struct ra_info *ra; 36832523Sbostic int next = 0, type, timeout, tries, i; 36917553Skarels 37032523Sbostic #ifdef lint 37132523Sbostic i = 0; i = i; 37232523Sbostic #endif 37332523Sbostic /* 37432523Sbostic * Make sure the controller is fully initialised, by waiting 37532523Sbostic * for it if necessary. 37632523Sbostic */ 37732523Sbostic sc = &uda_softc[um->um_ctlr]; 37832523Sbostic if (sc->sc_state == ST_RUN) 37932523Sbostic goto findunit; 38032523Sbostic tries = 0; 38132523Sbostic again: 38232523Sbostic if (udainit(ui->ui_ctlr)) 38332523Sbostic return (0); 38432523Sbostic timeout = todr() + 1000; /* 10 seconds */ 38532523Sbostic while (todr() < timeout) 38632523Sbostic if (sc->sc_state == ST_RUN) /* made it */ 38732523Sbostic goto findunit; 38832523Sbostic if (++tries < 2) 38932523Sbostic goto again; 39032523Sbostic printf("uda%d: controller hung\n", um->um_ctlr); 39132523Sbostic return (0); 39217553Skarels 39332523Sbostic /* 39432523Sbostic * The controller is all set; go find the unit. Grab an 39532523Sbostic * MSCP packet and send out a Get Unit Status command, with 39632523Sbostic * the `next unit' modifier if we are looking for a generic 39732523Sbostic * unit. We set the `in slave' flag so that udaunconf() 39832523Sbostic * knows to copy the response to `udaslavereply'. 39932523Sbostic */ 40032523Sbostic findunit: 40132523Sbostic udaslavereply.mscp_opcode = 0; 40232523Sbostic sc->sc_flags |= SC_INSLAVE; 40332523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) 40432523Sbostic panic("udaslave"); /* `cannot happen' */ 40532523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 40632523Sbostic if (ui->ui_slave == '?') { 40732523Sbostic mp->mscp_unit = next; 40832523Sbostic mp->mscp_modifier = M_GUM_NEXTUNIT; 40932523Sbostic } else { 41032523Sbostic mp->mscp_unit = ui->ui_slave; 41132523Sbostic mp->mscp_modifier = 0; 41217553Skarels } 41332523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 41432523Sbostic i = ((struct udadevice *) reg)->udaip; /* initiate polling */ 41532523Sbostic mp = &udaslavereply; 41632523Sbostic timeout = todr() + 1000; 41732523Sbostic while (todr() < timeout) 41832523Sbostic if (mp->mscp_opcode) 41932523Sbostic goto gotit; 42032523Sbostic printf("uda%d: no response to Get Unit Status request\n", 42132523Sbostic um->um_ctlr); 42232523Sbostic sc->sc_flags &= ~SC_INSLAVE; 42332523Sbostic return (0); 42432523Sbostic 42532523Sbostic gotit: 42632523Sbostic sc->sc_flags &= ~SC_INSLAVE; 42732523Sbostic 42832523Sbostic /* 42932523Sbostic * Got a slave response. If the unit is there, use it. 43032523Sbostic */ 43132523Sbostic switch (mp->mscp_status & M_ST_MASK) { 43232523Sbostic 43332523Sbostic case M_ST_SUCCESS: /* worked */ 43432523Sbostic case M_ST_AVAILABLE: /* found another drive */ 43532523Sbostic break; /* use it */ 43632523Sbostic 43732523Sbostic case M_ST_OFFLINE: 43832523Sbostic /* 43932523Sbostic * Figure out why it is off line. It may be because 44032523Sbostic * it is nonexistent, or because it is spun down, or 44132523Sbostic * for some other reason. 44232523Sbostic */ 44332523Sbostic switch (mp->mscp_status & ~M_ST_MASK) { 44432523Sbostic 44532523Sbostic case M_OFFLINE_UNKNOWN: 44632523Sbostic /* 44732523Sbostic * No such drive, and there are none with 44832523Sbostic * higher unit numbers either, if we are 44932523Sbostic * using M_GUM_NEXTUNIT. 45032523Sbostic */ 45132523Sbostic return (0); 45232523Sbostic 45332523Sbostic case M_OFFLINE_UNMOUNTED: 45432523Sbostic /* 45532523Sbostic * The drive is not spun up. Use it anyway. 45632523Sbostic * 45732523Sbostic * N.B.: this seems to be a common occurrance 45832523Sbostic * after a power failure. The first attempt 45932523Sbostic * to bring it on line seems to spin it up 46032523Sbostic * (and thus takes several minutes). Perhaps 46132523Sbostic * we should note here that the on-line may 46232523Sbostic * take longer than usual. 46332523Sbostic */ 46432523Sbostic break; 46532523Sbostic 46632523Sbostic default: 46732523Sbostic /* 46832523Sbostic * In service, or something else equally unusable. 46932523Sbostic */ 47032523Sbostic printf("uda%d: unit %d off line: ", um->um_ctlr, 47132523Sbostic mp->mscp_unit); 47232523Sbostic mscp_printevent(mp); 47332523Sbostic goto try_another; 47432523Sbostic } 47532523Sbostic break; 47632523Sbostic 47732523Sbostic default: 47832523Sbostic printf("uda%d: unable to get unit status: ", um->um_ctlr); 47932523Sbostic mscp_printevent(mp); 48032523Sbostic return (0); 48117553Skarels } 48232523Sbostic 48332523Sbostic /* 48432523Sbostic * Does this ever happen? What (if anything) does it mean? 48532523Sbostic */ 48632523Sbostic if (mp->mscp_unit < next) { 48732523Sbostic printf("uda%d: unit %d, next %d\n", 48832523Sbostic um->um_ctlr, mp->mscp_unit, next); 48932523Sbostic return (0); 49017553Skarels } 49132523Sbostic 49232523Sbostic if (mp->mscp_unit >= MAXUNIT) { 49332523Sbostic printf("uda%d: cannot handle unit number %d (max is %d)\n", 49432523Sbostic um->um_ctlr, mp->mscp_unit, MAXUNIT - 1); 49532523Sbostic return (0); 49632523Sbostic } 49732523Sbostic 49832523Sbostic /* 49932523Sbostic * See if we already handle this drive. 50032523Sbostic * (Only likely if ui->ui_slave=='?'.) 50132523Sbostic */ 50232523Sbostic if (udaip[um->um_ctlr][mp->mscp_unit] != NULL) { 50332523Sbostic try_another: 50432523Sbostic if (ui->ui_slave != '?') 50532523Sbostic return (0); 50632523Sbostic next = mp->mscp_unit + 1; 50732523Sbostic goto findunit; 50832523Sbostic } 50932523Sbostic 51032523Sbostic /* 51132523Sbostic * Voila! 51232523Sbostic */ 51332523Sbostic uda_rasave(ui->ui_unit, mp, 0); 51432523Sbostic ui->ui_flags = 0; /* not on line, nor anything else */ 51532523Sbostic ui->ui_slave = mp->mscp_unit; 51632523Sbostic return (1); 5174743Swnj } 5184743Swnj 51932523Sbostic /* 52032523Sbostic * Attach a found slave. Make sure the watchdog timer is running. 52132523Sbostic * If this disk is being profiled, fill in the `mspw' value (used by 52232523Sbostic * what?). Set up the inverting pointer, and attempt to bring the 52332523Sbostic * drive on line and read its label. 52432523Sbostic */ 52532523Sbostic udaattach(ui) 5264743Swnj register struct uba_device *ui; 5274743Swnj { 52832523Sbostic register int unit = ui->ui_unit; 52932523Sbostic 53032523Sbostic if (udawstart == 0) { 53132523Sbostic timeout(udawatch, (caddr_t) 0, hz); 53232523Sbostic udawstart++; 53332523Sbostic } 53412443Ssam if (ui->ui_dk >= 0) 53532523Sbostic dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ 53632523Sbostic udaip[ui->ui_ctlr][ui->ui_slave] = ui; 537*33195Sbostic 538*33195Sbostic /* 539*33195Sbostic * RX50s cannot be brought on line unless there is 540*33195Sbostic * a floppy in the drive. Since an ONLINE while cold 541*33195Sbostic * takes ten seconds to fail, and (when notyet becomes now) 542*33195Sbostic * no sensible person will swap to an RX50, we just 543*33195Sbostic * defer the ONLINE until someone tries to use the drive. 544*33195Sbostic */ 545*33195Sbostic if (ra_info[unit].ra_type == RA_TYPE_RX50) { 546*33195Sbostic printf("ra%d: rx50\n", unit); 547*33195Sbostic return; 548*33195Sbostic } 54932523Sbostic if (uda_rainit(ui, 0)) 55032574Skarels printf("ra%d: offline\n", unit); 55132523Sbostic else { 55232523Sbostic printf("ra%d: %s\n", unit, udalabel[unit].d_typename); 55332523Sbostic #ifdef notyet 55432523Sbostic addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]); 55526295Skarels #endif 55630536Skarels } 55732523Sbostic } 55832523Sbostic 55932523Sbostic /* 56032523Sbostic * Initialise a UDA50. Return true iff something goes wrong. 56132523Sbostic */ 56232523Sbostic udainit(ctlr) 56332523Sbostic int ctlr; 56432523Sbostic { 56532523Sbostic register struct uda_softc *sc; 56632523Sbostic register struct udadevice *udaddr; 56732523Sbostic struct uba_ctlr *um; 56832523Sbostic int timo, ubinfo; 56932523Sbostic 57032523Sbostic sc = &uda_softc[ctlr]; 57132523Sbostic um = udaminfo[ctlr]; 57232523Sbostic if ((sc->sc_flags & SC_MAPPED) == 0) { 57332523Sbostic /* 57432523Sbostic * Map the communication area and command and 57532523Sbostic * response packets into Unibus space. 57632523Sbostic */ 57732523Sbostic ubinfo = uballoc(um->um_ubanum, (caddr_t) &uda[ctlr], 57832523Sbostic sizeof (struct uda), UBA_CANTWAIT); 57932523Sbostic if (ubinfo == 0) { 58032523Sbostic printf("uda%d: uballoc map failed\n", ctlr); 58132523Sbostic return (-1); 58232523Sbostic } 58332523Sbostic sc->sc_uda = (struct uda *) (ubinfo & 0x3ffff); 58432523Sbostic sc->sc_flags |= SC_MAPPED; 58532523Sbostic } 58632523Sbostic 58730536Skarels /* 58832523Sbostic * While we are thinking about it, reset the next command 58932523Sbostic * and response indicies. 59030536Skarels */ 59132523Sbostic sc->sc_mi.mi_cmd.mri_next = 0; 59232523Sbostic sc->sc_mi.mi_rsp.mri_next = 0; 59332523Sbostic 59432523Sbostic /* 59532523Sbostic * Start up the hardware initialisation sequence. 59632523Sbostic */ 59732523Sbostic #define STEP0MASK (UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \ 59832523Sbostic UDA_STEP1 | UDA_NV) 59932523Sbostic 60032523Sbostic sc->sc_state = ST_IDLE; /* in case init fails */ 60132523Sbostic udaddr = (struct udadevice *) um->um_addr; 60232523Sbostic udaddr->udaip = 0; 60332523Sbostic timo = todr() + 1000; 60432523Sbostic while ((udaddr->udasa & STEP0MASK) == 0) { 60532523Sbostic if (todr() > timo) { 60632523Sbostic printf("uda%d: timeout during init\n", ctlr); 60732523Sbostic return (-1); 60832523Sbostic } 60932523Sbostic } 61032523Sbostic if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) { 61132523Sbostic printf("uda%d: init failed, sa=%b\n", ctlr, 61232523Sbostic udaddr->udasa, udasr_bits); 61332523Sbostic return (-1); 61432523Sbostic } 61532523Sbostic 61632523Sbostic /* 61732523Sbostic * Success! Record new state, and start step 1 initialisation. 61832523Sbostic * The rest is done in the interrupt handler. 61932523Sbostic */ 62032523Sbostic sc->sc_state = ST_STEP1; 62132523Sbostic udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE | 62232523Sbostic (sc->sc_ivec >> 2); 62332523Sbostic return (0); 6244743Swnj } 6254743Swnj 6264743Swnj /* 62732523Sbostic * Open a drive. 6284743Swnj */ 62932523Sbostic /*ARGSUSED*/ 63032523Sbostic udaopen(dev, flag, fmt) 6314743Swnj dev_t dev; 63230773Skarels int flag, fmt; 6334743Swnj { 63432523Sbostic register int unit; 6354743Swnj register struct uba_device *ui; 6364743Swnj register struct uda_softc *sc; 63730536Skarels register struct disklabel *lp; 63830536Skarels register struct partition *pp; 63930916Skarels register struct ra_info *ra; 64032523Sbostic int s, i, part, mask, error = 0; 64130536Skarels daddr_t start, end; 64230536Skarels 64332523Sbostic /* 64432523Sbostic * Make sure this is a reasonable open request. 64532523Sbostic */ 64632523Sbostic unit = udaunit(dev); 64732523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0) 6488576Sroot return (ENXIO); 64932523Sbostic 65032523Sbostic /* 65132523Sbostic * Make sure the controller is running, by (re)initialising it if 65232523Sbostic * necessary. 65332523Sbostic */ 6544743Swnj sc = &uda_softc[ui->ui_ctlr]; 6555434Sroot s = spl5(); 65632523Sbostic if (sc->sc_state != ST_RUN) { 65732523Sbostic if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) { 65832523Sbostic splx(s); 6598576Sroot return (EIO); 66017553Skarels } 66132523Sbostic /* 66232523Sbostic * In case it does not come up, make sure we will be 66332523Sbostic * restarted in 10 seconds. This corresponds to the 66432523Sbostic * 10 second timeouts in udaprobe() and udaslave(). 66532523Sbostic */ 66632523Sbostic sc->sc_flags |= SC_DOWAKE; 66732523Sbostic timeout(wakeup, (caddr_t) sc, 10 * hz); 66832523Sbostic sleep((caddr_t) sc, PRIBIO); 66932523Sbostic if (sc->sc_state != ST_RUN) { 67032523Sbostic splx(s); 67132523Sbostic printf("uda%d: controller hung\n", ui->ui_ctlr); 67232523Sbostic return (EIO); 67332523Sbostic } 67432523Sbostic untimeout(wakeup, (caddr_t) sc); 6754743Swnj } 67632523Sbostic 67732523Sbostic /* 67832523Sbostic * Wait for the state to settle 67932523Sbostic */ 68032523Sbostic ra = &ra_info[unit]; 68132523Sbostic while (ra->ra_state != OPEN && ra->ra_state != OPENRAW && 68232523Sbostic ra->ra_state != CLOSED) 68332523Sbostic sleep((caddr_t)ra, PZERO + 1); 68432523Sbostic 68532523Sbostic /* 68632523Sbostic * If not on line, or we are not sure of the label, reinitialise 68732523Sbostic * the drive. 68832523Sbostic */ 68932523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0 || 69032523Sbostic (ra->ra_state != OPEN && ra->ra_state != OPENRAW)) 69132523Sbostic error = uda_rainit(ui, flag); 69230916Skarels splx(s); 69332523Sbostic if (error) 69432523Sbostic return (error); 69530536Skarels 69632523Sbostic part = udapart(dev); 69732523Sbostic lp = &udalabel[unit]; 69830536Skarels if (part >= lp->d_npartitions) 69930536Skarels return (ENXIO); 70030536Skarels /* 70132523Sbostic * Warn if a partition is opened that overlaps another 70232523Sbostic * already open, unless either is the `raw' partition 70332523Sbostic * (whole disk). 70430536Skarels */ 70532523Sbostic #define RAWPART 2 /* 'c' partition */ /* XXX */ 70632523Sbostic mask = 1 << part; 70732523Sbostic if ((ra->ra_openpart & mask) == 0 && part != RAWPART) { 70830536Skarels pp = &lp->d_partitions[part]; 70930536Skarels start = pp->p_offset; 71030536Skarels end = pp->p_offset + pp->p_size; 71132523Sbostic for (pp = lp->d_partitions, i = 0; 71232523Sbostic i < lp->d_npartitions; pp++, i++) { 71330536Skarels if (pp->p_offset + pp->p_size <= start || 71432523Sbostic pp->p_offset >= end || i == RAWPART) 71530536Skarels continue; 71632523Sbostic if (ra->ra_openpart & (1 << i)) 71730536Skarels log(LOG_WARNING, 71830536Skarels "ra%d%c: overlaps open partition (%c)\n", 71932523Sbostic unit, part + 'a', i + 'a'); 72017553Skarels } 72117553Skarels } 72230773Skarels switch (fmt) { 72330773Skarels case S_IFCHR: 72432523Sbostic ra->ra_copenpart |= mask; 72530773Skarels break; 72630773Skarels case S_IFBLK: 72732523Sbostic ra->ra_bopenpart |= mask; 72830773Skarels break; 72930773Skarels } 73032523Sbostic ra->ra_openpart |= mask; 7318576Sroot return (0); 7324743Swnj } 7334743Swnj 73432523Sbostic udaclose(dev, flags, fmt) 73530536Skarels dev_t dev; 73630773Skarels int flags, fmt; 73730536Skarels { 73832523Sbostic register int unit = udaunit(dev); 73930773Skarels register struct ra_info *ra = &ra_info[unit]; 74032523Sbostic int s, mask = (1 << udapart(dev)); 74130536Skarels 74230773Skarels switch (fmt) { 74330773Skarels case S_IFCHR: 74432523Sbostic ra->ra_copenpart &= ~mask; 74530773Skarels break; 74630773Skarels case S_IFBLK: 74732523Sbostic ra->ra_bopenpart &= ~mask; 74830773Skarels break; 74930773Skarels } 75032523Sbostic ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart; 75132523Sbostic 75230536Skarels /* 75332523Sbostic * Should wait for I/O to complete on this partition even if 75432523Sbostic * others are open, but wait for work on blkflush(). 75530536Skarels */ 75632523Sbostic if (ra->ra_openpart == 0) { 75730536Skarels s = spl5(); 75832523Sbostic while (udautab[unit].b_actf) 75932523Sbostic sleep((caddr_t)&udautab[unit], PZERO - 1); 76030536Skarels splx(s); 76132523Sbostic ra->ra_state = CLOSED; 76230536Skarels } 76330773Skarels return (0); 76430536Skarels } 76530536Skarels 7664743Swnj /* 76732523Sbostic * Initialise a drive. If it is not already, bring it on line, 76832523Sbostic * and set a timeout on it in case it fails to respond. 76932523Sbostic * When on line, read in the pack label. 7704743Swnj */ 77132523Sbostic uda_rainit(ui, flags) 77230536Skarels register struct uba_device *ui; 77332523Sbostic int flags; 77430536Skarels { 77532523Sbostic register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; 77632523Sbostic register struct disklabel *lp; 77730536Skarels register struct mscp *mp; 77832523Sbostic register int unit = ui->ui_unit; 77932523Sbostic register struct ra_info *ra; 78030773Skarels char *msg, *readdisklabel(); 78132523Sbostic int s, i, udastrategy(); 78230536Skarels extern int cold; 78330536Skarels 78432523Sbostic ra = &ra_info[unit]; 78532523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 78632523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT); 78732523Sbostic mp->mscp_opcode = M_OP_ONLINE; 78832523Sbostic mp->mscp_unit = ui->ui_slave; 78932523Sbostic mp->mscp_cmdref = (long)&ui->ui_flags; 79032523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 79132523Sbostic ra->ra_state = WANTOPEN; 79232523Sbostic if (!cold) 79332523Sbostic s = spl5(); 79432523Sbostic i = ((struct udadevice *)ui->ui_addr)->udaip; 79530536Skarels 79630916Skarels if (cold) { 79732523Sbostic i = todr() + 1000; 79832523Sbostic while ((ui->ui_flags & UNIT_ONLINE) == 0) 79932523Sbostic if (todr() > i) 80032523Sbostic break; 80130916Skarels } else { 80232523Sbostic timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz); 80332523Sbostic sleep((caddr_t)&ui->ui_flags, PSWP + 1); 80432523Sbostic splx(s); 80532523Sbostic untimeout(wakeup, (caddr_t)&ui->ui_flags); 80630916Skarels } 80732523Sbostic if (ra->ra_state != OPENRAW) { 80832523Sbostic ra->ra_state = CLOSED; 80932523Sbostic wakeup((caddr_t)ra); 81030916Skarels return (EIO); 81130916Skarels } 81230536Skarels } 81330536Skarels 81432523Sbostic lp = &udalabel[unit]; 81530916Skarels lp->d_secsize = DEV_BSIZE; 81632523Sbostic lp->d_secperunit = ra->ra_dsize; 81730916Skarels 81830536Skarels if (flags & O_NDELAY) 81930536Skarels return (0); 82032523Sbostic ra->ra_state = RDLABEL; 82130536Skarels /* 82232523Sbostic * Set up default sizes until we have the label, or longer 82332523Sbostic * if there is none. Set secpercyl, as readdisklabel wants 82432523Sbostic * to compute b_cylin (although we do not need it). 82530536Skarels */ 82630916Skarels lp->d_secpercyl = 1; 82730536Skarels lp->d_npartitions = 1; 82830536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 82930536Skarels lp->d_partitions[0].p_offset = 0; 83032523Sbostic 83130536Skarels /* 83230536Skarels * Read pack label. 83330536Skarels */ 83432523Sbostic if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp)) != NULL) { 83530916Skarels log(LOG_ERR, "ra%d: %s\n", unit, msg); 83630536Skarels #ifdef COMPAT_42 83732523Sbostic if (udamaptype(unit, lp)) 83832523Sbostic ra->ra_state = OPEN; 83930536Skarels else 84032523Sbostic ra->ra_state = OPENRAW; 84131022Skarels #else 84232523Sbostic ra->ra_state = OPENRAW; 84332523Sbostic /* uda_makefakelabel(ra, lp); */ 84430536Skarels #endif 84530773Skarels } else 84632523Sbostic ra->ra_state = OPEN; 84730916Skarels wakeup((caddr_t)ra); 84830916Skarels return (0); 84930536Skarels } 85030536Skarels 85132523Sbostic /* 85232523Sbostic * Copy the geometry information for the given ra from a 85332523Sbostic * GET UNIT STATUS response. If check, see if it changed. 85432523Sbostic */ 85532523Sbostic uda_rasave(unit, mp, check) 85632523Sbostic int unit; 85732523Sbostic register struct mscp *mp; 85832523Sbostic int check; 85932523Sbostic { 86032523Sbostic register struct ra_info *ra = &ra_info[unit]; 86132523Sbostic 86232523Sbostic if (check && ra->ra_type != mp->mscp_guse.guse_drivetype) { 86332523Sbostic printf("ra%d: changed types! was %d now %d\n", 86432523Sbostic ra->ra_type, mp->mscp_guse.guse_drivetype); 86532523Sbostic ra->ra_state = CLOSED; /* ??? */ 86632523Sbostic } 86732523Sbostic ra->ra_type = mp->mscp_guse.guse_drivetype; 86832523Sbostic ra->ra_mediaid = mp->mscp_guse.guse_mediaid; 86932523Sbostic ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt; 87032523Sbostic ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group; 87132523Sbostic ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc; 87232523Sbostic ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc; 87332523Sbostic /* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */ 87432523Sbostic #ifdef notyet 87532523Sbostic ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize; 87632523Sbostic ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt; 87732523Sbostic ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct; 87832523Sbostic #endif 87932523Sbostic } 88032523Sbostic 88132523Sbostic /* 88232523Sbostic * Queue a transfer request, and if possible, hand it to the controller. 88332523Sbostic * 88432523Sbostic * This routine is broken into two so that the internal version 88532523Sbostic * udastrat1() can be called by the (nonexistent, as yet) bad block 88632523Sbostic * revectoring routine. 88732523Sbostic */ 88832523Sbostic udastrategy(bp) 8894743Swnj register struct buf *bp; 8904743Swnj { 89132523Sbostic register int unit; 8924743Swnj register struct uba_device *ui; 89330536Skarels register struct disklabel *lp; 89432523Sbostic register struct ra_info *ra; 89532523Sbostic struct partition *pp; 89632523Sbostic int p; 8974743Swnj daddr_t sz, maxsz; 8984743Swnj 89932523Sbostic /* 90032523Sbostic * Make sure this is a reasonable drive to use. 90132523Sbostic */ 90232523Sbostic if ((unit = udaunit(bp->b_dev)) >= NRA || 90332523Sbostic (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || 90432523Sbostic (ra = &ra_info[unit])->ra_state == CLOSED) { 90524742Sbloom bp->b_error = ENXIO; 9064743Swnj goto bad; 90724742Sbloom } 90832523Sbostic 90932523Sbostic /* 91032523Sbostic * If drive is open `raw' or reading label, let it at it. 91132523Sbostic */ 91232523Sbostic if (ra->ra_state < OPEN) { 91332523Sbostic udastrat1(bp); 91432523Sbostic return; 91524742Sbloom } 91632523Sbostic p = udapart(bp->b_dev); 91732523Sbostic if ((ra->ra_openpart & (1 << p)) == 0) /* can't happen? */ 91832523Sbostic panic("udastrategy"); 91932523Sbostic /* alternatively, ENODEV */ 92032523Sbostic 92132523Sbostic /* 92232523Sbostic * Determine the size of the transfer, and make sure it is 92332523Sbostic * within the boundaries of the partition. 92432523Sbostic */ 92532523Sbostic pp = &udalabel[unit].d_partitions[p]; 92632523Sbostic maxsz = pp->p_size; 92732523Sbostic if (pp->p_offset + pp->p_size > ra->ra_dsize) 92832523Sbostic maxsz = ra->ra_dsize - pp->p_offset; 92930536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 93030536Skarels if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 93132523Sbostic /* if exactly at end of disk, return an EOF */ 93224787Skarels if (bp->b_blkno == maxsz) { 93324787Skarels bp->b_resid = bp->b_bcount; 93432523Sbostic biodone(bp); 93532523Sbostic return; 93624787Skarels } 93732523Sbostic /* or truncate if part of it fits */ 93830536Skarels sz = maxsz - bp->b_blkno; 93930536Skarels if (sz <= 0) { 94032523Sbostic bp->b_error = EINVAL; /* or hang it up */ 94130536Skarels goto bad; 94230536Skarels } 94330536Skarels bp->b_bcount = sz << DEV_BSHIFT; 94424742Sbloom } 94532523Sbostic udastrat1(bp); 94632523Sbostic return; 94732523Sbostic bad: 94832523Sbostic bp->b_flags |= B_ERROR; 94932523Sbostic biodone(bp); 95032523Sbostic } 95132523Sbostic 95232523Sbostic /* 95332523Sbostic * Work routine for udastrategy. 95432523Sbostic */ 95532523Sbostic udastrat1(bp) 95632523Sbostic register struct buf *bp; 95732523Sbostic { 95832523Sbostic register int unit = udaunit(bp->b_dev); 95932523Sbostic register struct uba_ctlr *um; 96032523Sbostic register struct buf *dp; 96132523Sbostic struct uba_device *ui; 96232523Sbostic int s = spl5(); 96332523Sbostic 9644743Swnj /* 96532523Sbostic * Append the buffer to the drive queue, and if it is not 96632523Sbostic * already there, the drive to the controller queue. (However, 96732523Sbostic * if the drive queue is marked to be requeued, we must be 96832523Sbostic * awaiting an on line or get unit status command; in this 96932523Sbostic * case, leave it off the controller queue.) 9704743Swnj */ 97132523Sbostic um = (ui = udadinfo[unit])->ui_mi; 97232523Sbostic dp = &udautab[unit]; 97332523Sbostic APPEND(bp, dp, av_forw); 97432523Sbostic if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) { 97532523Sbostic APPEND(dp, &um->um_tab, b_forw); 97632523Sbostic dp->b_active++; 97732523Sbostic } 97832523Sbostic 9794743Swnj /* 98032523Sbostic * Start activity on the controller. Note that unlike other 98132523Sbostic * Unibus drivers, we must always do this, not just when the 98232523Sbostic * controller is not active. 9834743Swnj */ 98432523Sbostic udastart(um); 9855434Sroot splx(s); 9864743Swnj } 9874743Swnj 98832523Sbostic /* 98932523Sbostic * Start up whatever transfers we can find. 99032523Sbostic * Note that udastart() must be called at spl5(). 99132523Sbostic */ 99232523Sbostic udastart(um) 9934743Swnj register struct uba_ctlr *um; 9944743Swnj { 99532523Sbostic register struct uda_softc *sc = &uda_softc[um->um_ctlr]; 9964743Swnj register struct buf *bp, *dp; 9974743Swnj register struct mscp *mp; 99832523Sbostic struct uba_device *ui; 9994743Swnj struct udadevice *udaddr; 100032523Sbostic struct partition *pp; 100132523Sbostic int i, sz; 10024743Swnj 100332523Sbostic #ifdef lint 100432523Sbostic i = 0; i = i; 100532523Sbostic #endif 100632523Sbostic /* 100732523Sbostic * If it is not running, try (again and again...) to initialise 100832523Sbostic * it. If it is currently initialising just ignore it for now. 100932523Sbostic */ 101032523Sbostic if (sc->sc_state != ST_RUN) { 101132523Sbostic if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr)) 101232523Sbostic printf("uda%d: still hung\n", um->um_ctlr); 101332523Sbostic return; 101432523Sbostic } 101532523Sbostic 101632523Sbostic /* 101732523Sbostic * If um_cmd is nonzero, this controller is on the Unibus 101832523Sbostic * resource wait queue. It will not help to try more requests; 101932523Sbostic * instead, when the Unibus unblocks and calls udadgo(), we 102032523Sbostic * will call udastart() again. 102132523Sbostic */ 102232523Sbostic if (um->um_cmd) 102332523Sbostic return; 102432523Sbostic 102532523Sbostic sc->sc_flags |= SC_INSTART; 102632523Sbostic udaddr = (struct udadevice *) um->um_addr; 102732523Sbostic 10284743Swnj loop: 102932523Sbostic /* 103032523Sbostic * Service the drive at the head of the queue. It may not 103132523Sbostic * need anything, in which case it might be shutting down 103232523Sbostic * in udaclose(). 103332523Sbostic */ 103432523Sbostic if ((dp = um->um_tab.b_actf) == NULL) 103532523Sbostic goto out; 10364743Swnj if ((bp = dp->b_actf) == NULL) { 10374743Swnj dp->b_active = 0; 10384743Swnj um->um_tab.b_actf = dp->b_forw; 103932523Sbostic if (ra_info[dp - udautab].ra_openpart == 0) 104032523Sbostic wakeup((caddr_t)dp); /* finish close protocol */ 104132523Sbostic goto loop; 10424743Swnj } 104332523Sbostic 104432523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 104532523Sbostic udasaerror(um); 104632523Sbostic goto out; 10474743Swnj } 104832523Sbostic 104932523Sbostic /* 105032523Sbostic * Get an MSCP packet, then figure out what to do. If 105132523Sbostic * we cannot get a command packet, the command ring may 105232523Sbostic * be too small: We should have at least as many command 105332523Sbostic * packets as credits, for best performance. 105432523Sbostic */ 105532523Sbostic if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) { 105632523Sbostic if (sc->sc_mi.mi_credits > MSCP_MINCREDITS && 105732523Sbostic (sc->sc_flags & SC_GRIPED) == 0) { 105832523Sbostic log(LOG_NOTICE, "uda%d: command ring too small\n", 105932523Sbostic um->um_ctlr); 106032523Sbostic sc->sc_flags |= SC_GRIPED;/* complain only once */ 106117553Skarels } 106232523Sbostic goto out; 10634743Swnj } 10644743Swnj 106532523Sbostic /* 106632523Sbostic * Bring the drive on line if it is not already. Get its status 106732523Sbostic * if we do not already have it. Otherwise just start the transfer. 106832523Sbostic */ 106932523Sbostic ui = udadinfo[udaunit(bp->b_dev)]; 107032523Sbostic if ((ui->ui_flags & UNIT_ONLINE) == 0) { 107132523Sbostic mp->mscp_opcode = M_OP_ONLINE; 107232523Sbostic goto common; 10734743Swnj } 107432523Sbostic if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) { 107532523Sbostic mp->mscp_opcode = M_OP_GETUNITST; 107632523Sbostic common: 107732523Sbostic if (ui->ui_flags & UNIT_REQUEUE) panic("udastart"); 107832523Sbostic /* 107932523Sbostic * Take the drive off the controller queue. When the 108032523Sbostic * command finishes, make sure the drive is requeued. 108132523Sbostic */ 108232523Sbostic um->um_tab.b_actf = dp->b_forw; 108332523Sbostic dp->b_active = 0; 108432523Sbostic ui->ui_flags |= UNIT_REQUEUE; 108532523Sbostic mp->mscp_unit = ui->ui_slave; 108632523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 108732523Sbostic sc->sc_flags |= SC_STARTPOLL; 108832523Sbostic #ifdef POLLSTATS 108932523Sbostic sc->sc_ncmd++; 109025653Skarels #endif 109132523Sbostic goto loop; 109217553Skarels } 109332523Sbostic 109432523Sbostic pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)]; 109532523Sbostic mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE; 10964743Swnj mp->mscp_unit = ui->ui_slave; 109732523Sbostic mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset; 109830536Skarels sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 109932523Sbostic mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ? 110032523Sbostic (pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount; 110132523Sbostic /* mscp_cmdref is filled in by mscp_go() */ 11024743Swnj 11034743Swnj /* 110432523Sbostic * Drop the packet pointer into the `command' field so udadgo() 110532523Sbostic * can tell what to start. If ubago returns 1, we can do another 110632523Sbostic * transfer. If not, um_cmd will still point at mp, so we will 110732523Sbostic * know that we are waiting for resources. 11084743Swnj */ 110932523Sbostic um->um_cmd = (int)mp; 111032523Sbostic if (ubago(ui)) 111132523Sbostic goto loop; 111232523Sbostic 111332523Sbostic /* 111432523Sbostic * All done, or blocked in ubago(). If we managed to 111532523Sbostic * issue some commands, start up the beast. 111632523Sbostic */ 111732523Sbostic out: 111832523Sbostic if (sc->sc_flags & SC_STARTPOLL) { 111932523Sbostic #ifdef POLLSTATS 112032523Sbostic udastats.cmd[sc->sc_ncmd]++; 112132523Sbostic sc->sc_ncmd = 0; 112232523Sbostic #endif 112332523Sbostic i = ((struct udadevice *) um->um_addr)->udaip; 11244743Swnj } 112532523Sbostic sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL); 112632523Sbostic } 112732523Sbostic 112832523Sbostic /* 112932523Sbostic * Start a transfer. 113032523Sbostic * 113132523Sbostic * If we are not called from within udastart(), we must have been 113232523Sbostic * blocked, so call udastart to do more requests (if any). If 113332523Sbostic * this calls us again immediately we will not recurse, because 113432523Sbostic * that time we will be in udastart(). Clever.... 113532523Sbostic */ 113632523Sbostic udadgo(um) 113732523Sbostic register struct uba_ctlr *um; 113832523Sbostic { 113932523Sbostic struct uda_softc *sc = &uda_softc[um->um_ctlr]; 114032523Sbostic struct mscp *mp = (struct mscp *)um->um_cmd; 114132523Sbostic 114232523Sbostic um->um_tab.b_active++; /* another transfer going */ 114332523Sbostic 11444743Swnj /* 114532523Sbostic * Fill in the MSCP packet and move the buffer to the 114632523Sbostic * I/O wait queue. Mark the controller as no longer on 114732523Sbostic * the resource queue, and remember to initiate polling. 11484743Swnj */ 114932523Sbostic mp->mscp_seq.seq_buffer = (um->um_ubinfo & 0x3ffff) | 115032523Sbostic (UBAI_BDP(um->um_ubinfo) << 24); 115132523Sbostic mscp_go(&sc->sc_mi, mp, um->um_ubinfo); 115232523Sbostic um->um_cmd = 0; 115332523Sbostic um->um_ubinfo = 0; /* tyke it awye */ 115432523Sbostic sc->sc_flags |= SC_STARTPOLL; 115532523Sbostic #ifdef POLLSTATS 115632523Sbostic sc->sc_ncmd++; 115732523Sbostic #endif 115832523Sbostic if ((sc->sc_flags & SC_INSTART) == 0) 115932523Sbostic udastart(um); 11604743Swnj } 11614743Swnj 116232523Sbostic udaiodone(mi, bp, info) 116332523Sbostic register struct mscp_info *mi; 116432523Sbostic struct buf *bp; 116532523Sbostic int info; 116632523Sbostic { 116732523Sbostic register struct uba_ctlr *um = udaminfo[mi->mi_ctlr]; 116832523Sbostic 116932523Sbostic um->um_ubinfo = info; 117032523Sbostic ubadone(um); 117132523Sbostic biodone(bp); 117232523Sbostic if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab) 117332523Sbostic ubarelse(um->um_ubanum, &um->um_bdp); 117432523Sbostic um->um_tab.b_active--; /* another transfer done */ 117532523Sbostic } 117632523Sbostic 11774743Swnj /* 117832523Sbostic * The error bit was set in the controller status register. Gripe, 117932523Sbostic * reset the controller, requeue pending transfers. 11804743Swnj */ 118132523Sbostic udasaerror(um) 118232523Sbostic register struct uba_ctlr *um; 11834743Swnj { 118432523Sbostic 118532523Sbostic printf("uda%d: controller error, sa=%b\n", um->um_ctlr, 118632523Sbostic ((struct udadevice *) um->um_addr)->udasa, udasr_bits); 118732523Sbostic mscp_requeue(&uda_softc[um->um_ctlr].sc_mi); 118832523Sbostic (void) udainit(um->um_ctlr); 118932523Sbostic } 119032523Sbostic 119132523Sbostic /* 119232523Sbostic * Interrupt routine. Depending on the state of the controller, 119332523Sbostic * continue initialisation, or acknowledge command and response 119432523Sbostic * interrupts, and process responses. 119532523Sbostic */ 119632523Sbostic udaintr(ctlr) 119732523Sbostic int ctlr; 119832523Sbostic { 119932523Sbostic register struct uba_ctlr *um = udaminfo[ctlr]; 120032523Sbostic register struct uda_softc *sc = &uda_softc[ctlr]; 120132523Sbostic register struct udadevice *udaddr = (struct udadevice *) um->um_addr; 120232523Sbostic register struct uda *ud; 120332523Sbostic register struct mscp *mp; 12044743Swnj register int i; 12054743Swnj 120627254Skridle #ifdef VAX630 120732523Sbostic (void) spl5(); /* Qbus interrupt protocol is odd */ 120827254Skridle #endif 120932523Sbostic sc->sc_wticks = 0; /* reset interrupt watchdog */ 121032523Sbostic 121132523Sbostic /* 121232523Sbostic * Combinations during steps 1, 2, and 3: STEPnMASK 121332523Sbostic * corresponds to which bits should be tested; 121432523Sbostic * STEPnGOOD corresponds to the pattern that should 121532523Sbostic * appear after the interrupt from STEPn initialisation. 121632523Sbostic * All steps test the bits in ALLSTEPS. 121732523Sbostic */ 121832523Sbostic #define ALLSTEPS (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1) 121932523Sbostic 122032523Sbostic #define STEP1MASK (ALLSTEPS | UDA_IE | UDA_NCNRMASK) 122132523Sbostic #define STEP1GOOD (UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2) 122232523Sbostic 122332523Sbostic #define STEP2MASK (ALLSTEPS | UDA_IE | UDA_IVECMASK) 122432523Sbostic #define STEP2GOOD (UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2)) 122532523Sbostic 122632523Sbostic #define STEP3MASK ALLSTEPS 122732523Sbostic #define STEP3GOOD UDA_STEP4 122832523Sbostic 12294743Swnj switch (sc->sc_state) { 123032523Sbostic 123132523Sbostic case ST_IDLE: 123232523Sbostic /* 123332523Sbostic * Ignore unsolicited interrupts. 123432523Sbostic */ 123532523Sbostic log(LOG_WARNING, "uda%d: stray intr\n", ctlr); 12364743Swnj return; 12374743Swnj 123832523Sbostic case ST_STEP1: 123932523Sbostic /* 124032523Sbostic * Begin step two initialisation. 124132523Sbostic */ 124232523Sbostic if ((udaddr->udasa & STEP1MASK) != STEP1GOOD) { 124332523Sbostic i = 1; 124432523Sbostic initfailed: 124532523Sbostic printf("uda%d: init step %d failed, sa=%b\n", 124632523Sbostic ctlr, i, udaddr->udasa, udasr_bits); 124732523Sbostic sc->sc_state = ST_IDLE; 124832523Sbostic if (sc->sc_flags & SC_DOWAKE) { 124932523Sbostic sc->sc_flags &= ~SC_DOWAKE; 125032523Sbostic wakeup((caddr_t) sc); 125132523Sbostic } 12524743Swnj return; 12534743Swnj } 125432523Sbostic udaddr->udasa = (int) &sc->sc_uda->uda_ca.ca_rspdsc[0] | 125532523Sbostic (cpu == VAX_780 || cpu == VAX_8600 ? UDA_PI : 0); 125632523Sbostic sc->sc_state = ST_STEP2; 12574743Swnj return; 12584743Swnj 125932523Sbostic case ST_STEP2: 126032523Sbostic /* 126132523Sbostic * Begin step 3 initialisation. 126232523Sbostic */ 126332523Sbostic if ((udaddr->udasa & STEP2MASK) != STEP2GOOD) { 126432523Sbostic i = 2; 126532523Sbostic goto initfailed; 12664743Swnj } 126732523Sbostic udaddr->udasa = ((int) &sc->sc_uda->uda_ca.ca_rspdsc[0]) >> 16; 126832523Sbostic sc->sc_state = ST_STEP3; 12694743Swnj return; 12704743Swnj 127132523Sbostic case ST_STEP3: 127232523Sbostic /* 127332523Sbostic * Set controller characteristics (finish initialisation). 127432523Sbostic */ 127532523Sbostic if ((udaddr->udasa & STEP3MASK) != STEP3GOOD) { 127632523Sbostic i = 3; 127732523Sbostic goto initfailed; 12784743Swnj } 127932523Sbostic i = udaddr->udasa & 0xff; 128032523Sbostic if (i != sc->sc_micro) { 128132523Sbostic sc->sc_micro = i; 128232523Sbostic printf("uda%d: version %d model %d\n", 128332523Sbostic ctlr, i & 0xf, i >> 4); 128432523Sbostic } 128532523Sbostic 128617553Skarels /* 128732523Sbostic * Present the burst size, then remove it. Why this 128832523Sbostic * should be done this way, I have no idea. 128932523Sbostic * 129032523Sbostic * Note that this assumes udaburst[ctlr] > 0. 129117553Skarels */ 129232523Sbostic udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2; 12934743Swnj udaddr->udasa = UDA_GO; 129432523Sbostic printf("uda%d: DMA burst size set to %d\n", 129532523Sbostic ctlr, udaburst[ctlr]); 12964743Swnj 129732523Sbostic udainitds(ctlr); /* initialise data structures */ 129832523Sbostic 12994743Swnj /* 130032523Sbostic * Before we can get a command packet, we need some 130132523Sbostic * credits. Fake some up to keep mscp_getcp() happy, 130232523Sbostic * get a packet, and cancel all credits (the right 130332523Sbostic * number should come back in the response to the 130432523Sbostic * SCC packet). 13054743Swnj */ 130632523Sbostic sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1; 130732523Sbostic mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT); 130832523Sbostic if (mp == NULL) /* `cannot happen' */ 130932523Sbostic panic("udaintr"); 131032523Sbostic sc->sc_mi.mi_credits = 0; 131132523Sbostic mp->mscp_opcode = M_OP_SETCTLRC; 131232523Sbostic mp->mscp_unit = 0; 131332523Sbostic mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | 131432523Sbostic M_CF_THIS; 131532523Sbostic *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 131632523Sbostic i = udaddr->udaip; 131732523Sbostic sc->sc_state = ST_SETCHAR; 13184743Swnj return; 13194743Swnj 132032523Sbostic case ST_SETCHAR: 132132523Sbostic case ST_RUN: 132232523Sbostic /* 132332523Sbostic * Handle Set Ctlr Characteristics responses and operational 132432523Sbostic * responses (via mscp_dorsp). 132532523Sbostic */ 13264743Swnj break; 13274743Swnj 13284743Swnj default: 132932523Sbostic printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state); 133032523Sbostic panic("udastate"); 13314743Swnj } 13324743Swnj 133332523Sbostic if (udaddr->udasa & UDA_ERR) { /* ctlr fatal error */ 133432523Sbostic udasaerror(um); 133532523Sbostic return; 13364743Swnj } 13374743Swnj 133832523Sbostic ud = &uda[ctlr]; 133932523Sbostic 13404743Swnj /* 134132523Sbostic * Handle buffer purge requests. 134232523Sbostic * I have never seen these to work usefully, thus the log(). 13434743Swnj */ 13444743Swnj if (ud->uda_ca.ca_bdp) { 134532523Sbostic log(LOG_DEBUG, "uda%d: purge bdp %d\n", 134632523Sbostic ctlr, ud->uda_ca.ca_bdp); 134726372Skarels UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); 13484743Swnj ud->uda_ca.ca_bdp = 0; 134932523Sbostic udaddr->udasa = 0; /* signal purge complete */ 13504743Swnj } 13514743Swnj 13524743Swnj /* 135332523Sbostic * Check for response and command ring transitions. 13544743Swnj */ 13554743Swnj if (ud->uda_ca.ca_rspint) { 13564743Swnj ud->uda_ca.ca_rspint = 0; 135732523Sbostic mscp_dorsp(&sc->sc_mi); 13584743Swnj } 13594743Swnj if (ud->uda_ca.ca_cmdint) { 13604743Swnj ud->uda_ca.ca_cmdint = 0; 136132523Sbostic MSCP_DOCMD(&sc->sc_mi); 13624743Swnj } 136332523Sbostic udastart(um); 13644743Swnj } 13654743Swnj 136632523Sbostic #ifndef GENERIC_RAW 136732523Sbostic struct buf rudabuf[NRA]; 136832523Sbostic 13694743Swnj /* 137032523Sbostic * Read and write. 13714743Swnj */ 137232523Sbostic udaread(dev, uio) 137332523Sbostic dev_t dev; 137432523Sbostic struct uio *uio; 13754743Swnj { 13764743Swnj 137732523Sbostic return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_READ, 137832523Sbostic minphys, uio)); 137932523Sbostic } 13804743Swnj 138132523Sbostic udawrite(dev, uio) 138232523Sbostic dev_t dev; 138332523Sbostic struct uio *uio; 138432523Sbostic { 13854743Swnj 138632523Sbostic return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_WRITE, 138732523Sbostic minphys, uio)); 138832523Sbostic } 138932523Sbostic #endif /* GENERIC_RAW */ 13904743Swnj 139117553Skarels /* 139232523Sbostic * Initialise the various data structures that control the UDA50. 139317553Skarels */ 139432523Sbostic udainitds(ctlr) 139532523Sbostic int ctlr; 139632523Sbostic { 139732523Sbostic register struct uda *ud = &uda[ctlr]; 139832523Sbostic register struct uda *uud = uda_softc[ctlr].sc_uda; 139932523Sbostic register struct mscp *mp; 140032523Sbostic register int i; 14014743Swnj 140232523Sbostic for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) { 140332523Sbostic ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT | 140432523Sbostic (long)&uud->uda_rsp[i].mscp_cmdref; 140532523Sbostic mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i]; 140632523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 14074743Swnj } 140832523Sbostic for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) { 140932523Sbostic ud->uda_ca.ca_cmddsc[i] = MSCP_INT | 141032523Sbostic (long)&uud->uda_cmd[i].mscp_cmdref; 141132523Sbostic mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i]; 141232523Sbostic mp->mscp_msglen = MSCP_MSGLEN; 141332523Sbostic } 14144743Swnj } 14154743Swnj 14164743Swnj /* 141732523Sbostic * Handle an error datagram. All we do now is decode it. 14184743Swnj */ 141932523Sbostic udadgram(mi, mp) 142032523Sbostic struct mscp_info *mi; 142132523Sbostic struct mscp *mp; 14224743Swnj { 142317553Skarels 142432523Sbostic mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp); 142532523Sbostic } 142617553Skarels 142732523Sbostic /* 142832523Sbostic * The Set Controller Characteristics command finished. 142932523Sbostic * Record the new state of the controller. 143032523Sbostic */ 143132523Sbostic udactlrdone(mi, mp) 143232523Sbostic register struct mscp_info *mi; 143332523Sbostic struct mscp *mp; 143432523Sbostic { 143532523Sbostic register struct uda_softc *sc = &uda_softc[mi->mi_ctlr]; 143617553Skarels 143732523Sbostic if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) 143832523Sbostic sc->sc_state = ST_RUN; 143932523Sbostic else { 144032523Sbostic printf("uda%d: SETCTLRC failed: ", 144132523Sbostic mi->mi_ctlr, mp->mscp_status); 144232523Sbostic mscp_printevent(mp); 144332523Sbostic sc->sc_state = ST_IDLE; 14444743Swnj } 144532523Sbostic if (sc->sc_flags & SC_DOWAKE) { 144632523Sbostic sc->sc_flags &= ~SC_DOWAKE; 144732523Sbostic wakeup((caddr_t)sc); 14486964Ssam } 14494743Swnj } 14504743Swnj 14514743Swnj /* 145232523Sbostic * Received a response from an as-yet unconfigured drive. Configure it 145332523Sbostic * in, if possible. 14544743Swnj */ 145532523Sbostic udaunconf(mi, mp) 145632523Sbostic struct mscp_info *mi; 145732523Sbostic register struct mscp *mp; 14584743Swnj { 14594743Swnj 146017553Skarels /* 146132523Sbostic * If it is a slave response, copy it to udaslavereply for 146232523Sbostic * udaslave() to look at. 146317553Skarels */ 146432523Sbostic if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) && 146532523Sbostic (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) { 146632523Sbostic udaslavereply = *mp; 146732523Sbostic return (MSCP_DONE); 14684743Swnj } 146932523Sbostic 147032523Sbostic /* 147132523Sbostic * Otherwise, it had better be an available attention response. 147232523Sbostic */ 147332523Sbostic if (mp->mscp_opcode != M_OP_AVAILATTN) 147432523Sbostic return (MSCP_FAILED); 147532523Sbostic 147632523Sbostic /* do what autoconf does */ 147732523Sbostic return (MSCP_FAILED); /* not yet, arwhite, not yet */ 14784743Swnj } 14794743Swnj 148032523Sbostic /* 148132523Sbostic * A drive came on line. Check its type and size. Return DONE if 148232523Sbostic * we think the drive is truly on line. In any case, awaken anyone 148332523Sbostic * sleeping on the drive on-line-ness. 148432523Sbostic */ 148532523Sbostic udaonline(ui, mp) 148632523Sbostic register struct uba_device *ui; 148732523Sbostic struct mscp *mp; 14884743Swnj { 148932523Sbostic register struct ra_info *ra = &ra_info[ui->ui_unit]; 14904743Swnj 149132523Sbostic wakeup((caddr_t)&ui->ui_flags); 149232523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 149332523Sbostic printf("uda%d: attempt to bring ra%d on line failed: ", 149432523Sbostic ui->ui_ctlr, ui->ui_unit); 149532523Sbostic mscp_printevent(mp); 149632523Sbostic ra->ra_state = CLOSED; 149732523Sbostic return (MSCP_FAILED); 149832523Sbostic } 149932523Sbostic 150032523Sbostic ra->ra_state = OPENRAW; 150132523Sbostic ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize; 150232523Sbostic printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit, 150332523Sbostic ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize); 150432523Sbostic /* can now compute ncyl */ 150532523Sbostic ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks / 150632523Sbostic ra->ra_geom.rg_nsectors; 150732523Sbostic return (MSCP_DONE); 15084743Swnj } 15094743Swnj 151032523Sbostic /* 151132523Sbostic * We got some (configured) unit's status. Return DONE if it succeeded. 151232523Sbostic */ 151332523Sbostic udagotstatus(ui, mp) 151432523Sbostic register struct uba_device *ui; 151532523Sbostic register struct mscp *mp; 15164743Swnj { 15174743Swnj 151832523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 151932523Sbostic printf("uda%d: attempt to get status for ra%d failed: ", 152032523Sbostic ui->ui_ctlr, ui->ui_unit); 152132523Sbostic mscp_printevent(mp); 152232523Sbostic return (MSCP_FAILED); 152332523Sbostic } 152432523Sbostic /* record for (future) bad block forwarding and whatever else */ 152532523Sbostic uda_rasave(ui->ui_unit, mp, 1); 152632523Sbostic return (MSCP_DONE); 15274743Swnj } 15284743Swnj 152932523Sbostic /* 153032523Sbostic * A transfer failed. We get a chance to fix or restart it. 153132523Sbostic * Need to write the bad block forwaring code first.... 153232523Sbostic */ 153332523Sbostic /*ARGSUSED*/ 153432523Sbostic udaioerror(ui, mp, bp) 153532523Sbostic register struct uba_device *ui; 153632523Sbostic register struct mscp *mp; 153732523Sbostic struct buf *bp; 15384743Swnj { 15394743Swnj 154032523Sbostic if (mp->mscp_flags & M_EF_BBLKR) { 154132523Sbostic /* 154232523Sbostic * A bad block report. Eventually we will 154332523Sbostic * restart this transfer, but for now, just 154432523Sbostic * log it and give up. 154532523Sbostic */ 154632523Sbostic log(LOG_ERR, "ra%d: bad block report: %d%s\n", 154732523Sbostic ui->ui_unit, mp->mscp_seq.seq_lbn, 154832523Sbostic mp->mscp_flags & M_EF_BBLKU ? " + others" : ""); 154932523Sbostic } else { 155032523Sbostic /* 155132523Sbostic * What the heck IS a `serious exception' anyway? 155232523Sbostic * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION 155332523Sbostic * FOR THEIR OWN CONTROLLERS. 155432523Sbostic */ 155532523Sbostic if (mp->mscp_flags & M_EF_SEREX) 155632523Sbostic log(LOG_ERR, "ra%d: serious exception reported\n", 155732523Sbostic ui->ui_unit); 15584743Swnj } 155932523Sbostic return (MSCP_FAILED); 15604743Swnj } 15614743Swnj 156232523Sbostic /* 156332523Sbostic * A replace operation finished. 156432523Sbostic */ 156532523Sbostic /*ARGSUSED*/ 156632523Sbostic udareplace(ui, mp) 156732523Sbostic struct uba_device *ui; 156832523Sbostic struct mscp *mp; 15694743Swnj { 157017553Skarels 157132523Sbostic panic("udareplace"); 15724743Swnj } 157317553Skarels 157432523Sbostic /* 157532523Sbostic * A bad block related operation finished. 157632523Sbostic */ 157732523Sbostic /*ARGSUSED*/ 157832523Sbostic udabb(ui, mp, bp) 157932523Sbostic struct uba_device *ui; 158032523Sbostic struct mscp *mp; 158132523Sbostic struct buf *bp; 158217553Skarels { 158317553Skarels 158432523Sbostic panic("udabb"); 158517553Skarels } 158617553Skarels 158732523Sbostic 158832523Sbostic /* 158932523Sbostic * I/O controls. 159032523Sbostic */ 159132523Sbostic udaioctl(dev, cmd, data, flag) 159212511Ssam dev_t dev; 159330536Skarels int cmd; 159430536Skarels caddr_t data; 159530536Skarels int flag; 159612511Ssam { 159732523Sbostic register int unit = udaunit(dev); 159830536Skarels register struct disklabel *lp; 159930536Skarels int error = 0; 160012511Ssam 160132523Sbostic lp = &udalabel[unit]; 160230536Skarels 160330536Skarels switch (cmd) { 160430536Skarels 160530536Skarels case DIOCGDINFO: 160630536Skarels *(struct disklabel *)data = *lp; 160730536Skarels break; 160830536Skarels 160930773Skarels case DIOCGPART: 161030773Skarels ((struct partinfo *)data)->disklab = lp; 161130773Skarels ((struct partinfo *)data)->part = 161232523Sbostic &lp->d_partitions[udapart(dev)]; 161330536Skarels break; 161430536Skarels 161530536Skarels case DIOCSDINFO: 161630536Skarels if ((flag & FWRITE) == 0) 161730536Skarels error = EBADF; 161830536Skarels else 161932574Skarels error = setdisklabel(lp, (struct disklabel *)data, 162032574Skarels ra_info[unit].ra_openpart); 162130536Skarels break; 162230536Skarels 162332574Skarels case DIOCWDINFO: 162432574Skarels if ((flag & FWRITE) == 0) 162532523Sbostic error = EBADF; 162632574Skarels else if ((error = setdisklabel(lp, (struct disklabel *)data, 162732574Skarels ra_info[unit].ra_openpart)) == 0) 162832574Skarels error = writedisklabel(dev, udastrategy, lp); 162930536Skarels break; 163030536Skarels 163132523Sbostic #ifdef notyet 163232523Sbostic case UDAIOCREPLACE: 163332523Sbostic /* 163432523Sbostic * Initiate bad block replacement for the given LBN. 163532523Sbostic * (Should we allow modifiers?) 163632523Sbostic */ 163732523Sbostic error = EOPNOTSUPP; 163832523Sbostic break; 163932523Sbostic 164032523Sbostic case UDAIOCGMICRO: 164132523Sbostic /* 164232523Sbostic * Return the microcode revision for the UDA50 running 164332523Sbostic * this drive. 164432523Sbostic */ 164532523Sbostic *(int *) data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro; 164632523Sbostic break; 164732523Sbostic #endif 164832523Sbostic 164930536Skarels default: 165030536Skarels error = ENOTTY; 165130536Skarels break; 165230536Skarels } 165332523Sbostic return (error); 165432523Sbostic } 165532523Sbostic 165632523Sbostic /* 165732523Sbostic * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s) 165832523Sbostic * on that Unibus, and requeue outstanding I/O. 165932523Sbostic */ 166032523Sbostic udareset(uban) 166132523Sbostic int uban; 166232523Sbostic { 166332523Sbostic register struct uba_ctlr *um; 166432523Sbostic register struct uda_softc *sc; 166532523Sbostic register int ctlr; 166632523Sbostic 166732523Sbostic for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) { 166832523Sbostic if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban || 166932523Sbostic um->um_alive == 0) 167032523Sbostic continue; 167132523Sbostic printf(" uda%d", ctlr); 167232523Sbostic 167332523Sbostic /* 167432523Sbostic * Our BDP (if any) is gone; our command (if any) is 167532523Sbostic * flushed; the device is no longer mapped; and the 167632523Sbostic * UDA50 is not yet initialised. 167732523Sbostic */ 167832523Sbostic if (um->um_bdp) { 167932523Sbostic printf("<%d>", UBAI_BDP(um->um_bdp)); 168032523Sbostic um->um_bdp = 0; 168132523Sbostic } 168232523Sbostic um->um_ubinfo = 0; 168332523Sbostic um->um_cmd = 0; 168432523Sbostic sc->sc_flags &= ~SC_MAPPED; 168532523Sbostic sc->sc_state = ST_IDLE; 168632523Sbostic 168732523Sbostic /* reset queues and requeue pending transfers */ 168832523Sbostic mscp_requeue(&sc->sc_mi); 168932523Sbostic 169032523Sbostic /* 169132523Sbostic * If it fails to initialise we will notice later and 169232523Sbostic * try again (and again...). Do not call udastart() 169332523Sbostic * here; it will be done after the controller finishes 169432523Sbostic * initialisation. 169532523Sbostic */ 169632523Sbostic if (udainit(ctlr)) 169732523Sbostic printf(" (hung)"); 169832523Sbostic } 169932523Sbostic } 170032523Sbostic 170132523Sbostic /* 170232523Sbostic * Watchdog timer: If the controller is active, and no interrupts 170332523Sbostic * have occurred for 30 seconds, assume it has gone away. 170432523Sbostic */ 170532523Sbostic udawatch() 170632523Sbostic { 170732523Sbostic register int i; 170832523Sbostic register struct uba_ctlr *um; 170932523Sbostic register struct uda_softc *sc; 171032523Sbostic 171132523Sbostic timeout(udawatch, (caddr_t) 0, hz); /* every second */ 171232523Sbostic for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) { 171332523Sbostic if ((um = udaminfo[i]) == 0 || !um->um_alive) 171432523Sbostic continue; 171532523Sbostic if (sc->sc_state == ST_IDLE) 171632523Sbostic continue; 171732523Sbostic if (sc->sc_state == ST_RUN && !um->um_tab.b_active) 171832523Sbostic sc->sc_wticks = 0; 171932523Sbostic else if (++sc->sc_wticks >= 30) { 172032523Sbostic sc->sc_wticks = 0; 172132523Sbostic printf("uda%d: lost interrupt\n", i); 172232523Sbostic ubareset(um->um_ubanum); 172332523Sbostic } 172432523Sbostic } 172532523Sbostic } 172632523Sbostic 172732523Sbostic /* 172832523Sbostic * Do a panic dump. We set up the controller for one command packet 172932523Sbostic * and one response packet, for which we use `struct uda1'. 173032523Sbostic */ 173132523Sbostic struct uda1 { 173232523Sbostic struct uda1ca uda1_ca; /* communications area */ 173332523Sbostic struct mscp uda1_rsp; /* response packet */ 173432523Sbostic struct mscp uda1_cmd; /* command packet */ 173532523Sbostic } uda1; 173632523Sbostic 173732523Sbostic #define DBSIZE 32 /* dump 16K at a time */ 173832523Sbostic 173932523Sbostic udadump(dev) 174032523Sbostic dev_t dev; 174132523Sbostic { 174232523Sbostic struct udadevice *udaddr; 174332523Sbostic struct uda1 *ud_ubaddr; 174432523Sbostic char *start; 174532523Sbostic int num, blk, unit, maxsz, blkoff, reg; 174632523Sbostic struct partition *pp; 174732523Sbostic register struct uba_regs *uba; 174832523Sbostic register struct uba_device *ui; 174932523Sbostic register struct uda1 *ud; 175032523Sbostic register struct pte *io; 175132523Sbostic register int i; 175232523Sbostic 175332523Sbostic /* 175432523Sbostic * Make sure the device is a reasonable place on which to dump. 175532523Sbostic */ 175632523Sbostic unit = udaunit(dev); 175732523Sbostic if (unit >= NRA) 175832523Sbostic return (ENXIO); 175932523Sbostic #define phys(cast, addr) ((cast) ((int) addr & 0x7fffffff)) 176032523Sbostic ui = phys(struct uba_device *, udadinfo[unit]); 176132523Sbostic if (ui == NULL || ui->ui_alive == 0) 176232523Sbostic return (ENXIO); 176332523Sbostic 176432523Sbostic /* 176532523Sbostic * Find and initialise the UBA; get the physical address of the 176632523Sbostic * device registers, and of communications area and command and 176732523Sbostic * response packet. 176832523Sbostic */ 176932523Sbostic uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 177032523Sbostic ubainit(uba); 177132523Sbostic udaddr = (struct udadevice *)ui->ui_physaddr; 177232523Sbostic ud = phys(struct uda1 *, &uda1); 177332523Sbostic 177432523Sbostic /* 177532523Sbostic * Map the ca+packets into Unibus I/O space so the UDA50 can get 177632523Sbostic * at them. Use the registers at the end of the Unibus map (since 177732523Sbostic * we will use the registers at the beginning to map the memory 177832523Sbostic * we are dumping). 177932523Sbostic */ 178032523Sbostic num = btoc(sizeof(struct uda1)) + 1; 178132523Sbostic reg = NUBMREG - num; 178232523Sbostic io = &uba->uba_map[reg]; 178332523Sbostic for (i = 0; i < num; i++) 178432523Sbostic *(int *)io++ = UBAMR_MRV | (btop(ud) + i); 178532523Sbostic ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); 178632523Sbostic 178732523Sbostic /* 178832523Sbostic * Initialise the controller, with one command and one response 178932523Sbostic * packet. 179032523Sbostic */ 179132523Sbostic udaddr->udaip = 0; 179232523Sbostic if (udadumpwait(udaddr, UDA_STEP1)) 179332523Sbostic return (EFAULT); 179432523Sbostic udaddr->udasa = UDA_ERR; 179532523Sbostic if (udadumpwait(udaddr, UDA_STEP2)) 179632523Sbostic return (EFAULT); 179732523Sbostic udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; 179832523Sbostic if (udadumpwait(udaddr, UDA_STEP3)) 179932523Sbostic return (EFAULT); 180032523Sbostic udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; 180132523Sbostic if (udadumpwait(udaddr, UDA_STEP4)) 180232523Sbostic return (EFAULT); 180332523Sbostic uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff; 180432523Sbostic udaddr->udasa = UDA_GO; 180532523Sbostic 180632523Sbostic /* 180732523Sbostic * Set up the command and response descriptor, then set the 180832523Sbostic * controller characteristics and bring the drive on line. 180932523Sbostic * Note that all uninitialised locations in uda1_cmd are zero. 181032523Sbostic */ 181132523Sbostic ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; 181232523Sbostic ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; 181332523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ 181432523Sbostic /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ 181532523Sbostic if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) 181632523Sbostic return (EFAULT); 181732523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 181832523Sbostic if (udadumpcmd(M_OP_ONLINE, ud, ui)) 181932523Sbostic return (EFAULT); 182032523Sbostic 182132523Sbostic pp = phys(struct partition *, 182232523Sbostic &udalabel[unit].d_partitions[udapart(dev)]); 182332523Sbostic maxsz = pp->p_size; 182432523Sbostic blkoff = pp->p_offset; 182532523Sbostic 182632523Sbostic /* 182732523Sbostic * Dump all of physical memory, or as much as will fit in the 182832523Sbostic * space provided. 182932523Sbostic */ 183032523Sbostic start = 0; 183132523Sbostic num = maxfree; 183232523Sbostic if (dumplo < 0) 183332523Sbostic return (EINVAL); 183432523Sbostic if (dumplo + num >= maxsz) 183532523Sbostic num = maxsz - dumplo; 183632523Sbostic blkoff += dumplo; 183732523Sbostic 183832523Sbostic /* 183932523Sbostic * Write out memory, DBSIZE pages at a time. 184032523Sbostic * N.B.: this code depends on the fact that the sector 184132523Sbostic * size == the page size. 184232523Sbostic */ 184332523Sbostic while (num > 0) { 184432523Sbostic blk = num > DBSIZE ? DBSIZE : num; 184532523Sbostic io = uba->uba_map; 184632523Sbostic /* 184732523Sbostic * Map in the pages to write, leaving an invalid entry 184832523Sbostic * at the end to guard against wild Unibus transfers. 184932523Sbostic * Then do the write. 185032523Sbostic */ 185132523Sbostic for (i = 0; i < blk; i++) 185232523Sbostic *(int *) io++ = UBAMR_MRV | (btop(start) + i); 185332523Sbostic *(int *) io = 0; 185432523Sbostic ud->uda1_cmd.mscp_unit = ui->ui_slave; 185532523Sbostic ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; 185632523Sbostic ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; 185732523Sbostic if (udadumpcmd(M_OP_WRITE, ud, ui)) 185832523Sbostic return (EIO); 185932523Sbostic start += blk << PGSHIFT; 186032523Sbostic num -= blk; 186132523Sbostic } 186232523Sbostic return (0); /* made it! */ 186332523Sbostic } 186432523Sbostic 186532523Sbostic /* 186632523Sbostic * Wait for some of the bits in `bits' to come on. If the error bit 186732523Sbostic * comes on, or ten seconds pass without response, return true (error). 186832523Sbostic */ 186932523Sbostic udadumpwait(udaddr, bits) 187032523Sbostic register struct udadevice *udaddr; 187132523Sbostic register int bits; 187232523Sbostic { 187332523Sbostic register int timo = todr() + 1000; 187432523Sbostic 187532523Sbostic while ((udaddr->udasa & bits) == 0) { 187632523Sbostic if (udaddr->udasa & UDA_ERR) { 187732523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 187832523Sbostic return (1); 187932523Sbostic } 188032523Sbostic if (todr() >= timo) { 188132523Sbostic printf("timeout\ndump "); 188232523Sbostic return (1); 188332523Sbostic } 188432523Sbostic } 188530536Skarels return (0); 188630536Skarels } 188730536Skarels 188832523Sbostic /* 188932523Sbostic * Feed a command to the UDA50, wait for its response, and return 189032523Sbostic * true iff something went wrong. 189132523Sbostic */ 189232523Sbostic udadumpcmd(op, ud, ui) 189332523Sbostic int op; 189432523Sbostic register struct uda1 *ud; 189532523Sbostic struct uba_device *ui; 189632523Sbostic { 189732523Sbostic register struct udadevice *udaddr; 189832523Sbostic register int n; 189932523Sbostic #define mp (&ud->uda1_rsp) 190032523Sbostic 190132523Sbostic udaddr = (struct udadevice *) ui->ui_physaddr; 190232523Sbostic ud->uda1_cmd.mscp_opcode = op; 190332523Sbostic ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; 190432523Sbostic ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; 190532523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 190632523Sbostic ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; 190732523Sbostic if (udaddr->udasa & UDA_ERR) { 190832523Sbostic printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); 190932523Sbostic return (1); 191032523Sbostic } 191132523Sbostic n = udaddr->udaip; 191232523Sbostic n = todr() + 1000; 191332523Sbostic for (;;) { 191432523Sbostic if (todr() > n) { 191532523Sbostic printf("timeout\ndump "); 191632523Sbostic return (1); 191732523Sbostic } 191832523Sbostic if (ud->uda1_ca.ca_cmdint) 191932523Sbostic ud->uda1_ca.ca_cmdint = 0; 192032523Sbostic if (ud->uda1_ca.ca_rspint == 0) 192132523Sbostic continue; 192232523Sbostic ud->uda1_ca.ca_rspint = 0; 192332523Sbostic if (mp->mscp_opcode == (op | M_OP_END)) 192432523Sbostic break; 192532523Sbostic printf("\n"); 192632523Sbostic switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { 192732523Sbostic 192832523Sbostic case MSCPT_SEQ: 192932523Sbostic printf("sequential"); 193032523Sbostic break; 193132523Sbostic 193232523Sbostic case MSCPT_DATAGRAM: 193332523Sbostic mscp_decodeerror("uda", ui->ui_ctlr, mp); 193432523Sbostic printf("datagram"); 193532523Sbostic break; 193632523Sbostic 193732523Sbostic case MSCPT_CREDITS: 193832523Sbostic printf("credits"); 193932523Sbostic break; 194032523Sbostic 194132523Sbostic case MSCPT_MAINTENANCE: 194232523Sbostic printf("maintenance"); 194332523Sbostic break; 194432523Sbostic 194532523Sbostic default: 194632523Sbostic printf("unknown (type 0x%x)", 194732523Sbostic MSCP_MSGTYPE(mp->mscp_msgtc)); 194832523Sbostic break; 194932523Sbostic } 195032523Sbostic printf(" ignored\ndump "); 195132523Sbostic ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; 195232523Sbostic } 195332523Sbostic if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 195432523Sbostic printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, 195532523Sbostic mp->mscp_opcode, mp->mscp_status); 195632523Sbostic return (1); 195732523Sbostic } 195832523Sbostic return (0); 195932523Sbostic #undef mp 196032523Sbostic } 196132523Sbostic 196232523Sbostic /* 196332523Sbostic * Return the size of a partition, if known, or -1 if not. 196432523Sbostic */ 196532523Sbostic udasize(dev) 196630536Skarels dev_t dev; 196730536Skarels { 196832523Sbostic register int unit = udaunit(dev); 196930536Skarels register struct uba_device *ui; 197032523Sbostic register struct size *st; 197130536Skarels 197232523Sbostic if (unit >= NRA || (ui = udadinfo[unit]) == NULL || 197332523Sbostic ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 || 197432523Sbostic ra_info[unit].ra_state != OPEN) 197512511Ssam return (-1); 197632523Sbostic return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size); 197712511Ssam } 197817553Skarels 197930536Skarels #ifdef COMPAT_42 198032523Sbostic /* 198132523Sbostic * Tables mapping unlabelled drives. 198232523Sbostic */ 198330536Skarels struct size { 198430536Skarels daddr_t nblocks; 198530536Skarels daddr_t blkoff; 198632523Sbostic } ra25_sizes[8] = { 198730536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 198830536Skarels 10032, 15884, /* B=blk 15884 thru 49323 */ 198930536Skarels -1, 0, /* C=blk 0 thru end */ 199030536Skarels 0, 0, /* D=blk 340670 thru 356553 */ 199130536Skarels 0, 0, /* E=blk 356554 thru 412489 */ 199230536Skarels 0, 0, /* F=blk 412490 thru end */ 199330536Skarels -1, 25916, /* G=blk 49324 thru 131403 */ 199430536Skarels 0, 0, /* H=blk 131404 thru end */ 199532523Sbostic }, rx50_sizes[8] = { 199632523Sbostic 800, 0, /* A=blk 0 thru 799 */ 199732523Sbostic 0, 0, 199832523Sbostic -1, 0, /* C=blk 0 thru end */ 199932523Sbostic 0, 0, 200032523Sbostic 0, 0, 200132523Sbostic 0, 0, 200232523Sbostic 0, 0, 200332523Sbostic 0, 0, 200430536Skarels }, rd52_sizes[8] = { 200530536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 200630536Skarels 9766, 15884, /* B=blk 15884 thru 25649 */ 200730536Skarels -1, 0, /* C=blk 0 thru end */ 200830536Skarels 0, 0, /* D=unused */ 200930536Skarels 0, 0, /* E=unused */ 201030536Skarels 0, 0, /* F=unused */ 201130536Skarels -1, 25650, /* G=blk 25650 thru end */ 201230536Skarels 0, 0, /* H=unused */ 201330536Skarels }, rd53_sizes[8] = { 201430536Skarels 15884, 0, /* A=blk 0 thru 15883 */ 201530536Skarels 33440, 15884, /* B=blk 15884 thru 49323 */ 201630536Skarels -1, 0, /* C=blk 0 thru end */ 201730536Skarels 0, 0, /* D=unused */ 201830536Skarels 33440, 0, /* E=blk 0 thru 33439 */ 201930536Skarels -1, 33440, /* F=blk 33440 thru end */ 202030536Skarels -1, 49324, /* G=blk 49324 thru end */ 202130536Skarels -1, 15884, /* H=blk 15884 thru end */ 202230536Skarels }, ra60_sizes[8] = { 202330536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 202430536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 202530536Skarels 400176, 0, /* C=sectors 0 thru 400175 */ 202630536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 202730536Skarels 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ 202830536Skarels 350852, 49324, /* F=sectors 49324 thru 400175 */ 202930536Skarels 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ 203030536Skarels 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */ 203130536Skarels }, ra80_sizes[8] = { 203230536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 203330536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 203430536Skarels 242606, 0, /* C=sectors 0 thru 242605 */ 203530536Skarels 0, 0, /* D=unused */ 203630536Skarels 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ 203730536Skarels 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ 203830536Skarels 192696, 49910, /* G=sectors 49910 thru 242605 */ 203930536Skarels 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */ 204030536Skarels }, ra81_sizes[8] ={ 204130536Skarels /* 204230536Skarels * These are the new standard partition sizes for ra81's. 204330536Skarels * An RA_COMPAT system is compiled with D, E, and F corresponding 204430536Skarels * to the 4.2 partitions for G, H, and F respectively. 204530536Skarels */ 204630536Skarels #ifndef UCBRA 204730536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 204830536Skarels 66880, 16422, /* B=sectors 16422 thru 83301 */ 204930536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 205030536Skarels #ifdef RA_COMPAT 205130536Skarels 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 205230536Skarels 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ 205330536Skarels 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */ 205430536Skarels #else 205530536Skarels 15884, 375564, /* D=sectors 375564 thru 391447 */ 205630536Skarels 307200, 391986, /* E=sectors 391986 thru 699185 */ 205730536Skarels 191352, 699720, /* F=sectors 699720 thru 891071 */ 205830536Skarels #endif RA_COMPAT 205930536Skarels 515508, 375564, /* G=sectors 375564 thru 891071 */ 206030536Skarels 291346, 83538, /* H=sectors 83538 thru 374883 */ 206130536Skarels 206230536Skarels /* 206330536Skarels * These partitions correspond to the sizes used by sites at Berkeley, 206430536Skarels * and by those sites that have received copies of the Berkeley driver 206530536Skarels * with deltas 6.2 or greater (11/15/83). 206630536Skarels */ 206730536Skarels #else UCBRA 206830536Skarels 206930536Skarels 15884, 0, /* A=sectors 0 thru 15883 */ 207030536Skarels 33440, 15884, /* B=sectors 15884 thru 49323 */ 207130536Skarels 891072, 0, /* C=sectors 0 thru 891071 */ 207230536Skarels 15884, 242606, /* D=sectors 242606 thru 258489 */ 207330536Skarels 307200, 258490, /* E=sectors 258490 thru 565689 */ 207430536Skarels 325382, 565690, /* F=sectors 565690 thru 891071 */ 207530536Skarels 648466, 242606, /* G=sectors 242606 thru 891071 */ 207630536Skarels 193282, 49324, /* H=sectors 49324 thru 242605 */ 207730536Skarels 207830536Skarels #endif UCBRA 207930536Skarels }; 208030536Skarels 208132523Sbostic /* 208232523Sbostic * Drive type index decoding table. `ut_name' is null iff the 208332523Sbostic * type is not known. 208432523Sbostic */ 208532523Sbostic struct udatypes { 208632523Sbostic char *ut_name; /* drive type name */ 208732523Sbostic struct size *ut_sizes; /* partition tables */ 208832523Sbostic int ut_nsectors, ut_ntracks, ut_ncylinders; 208932523Sbostic } udatypes[] = { 209032523Sbostic NULL, NULL, 209132523Sbostic 0, 0, 0, 209232523Sbostic "ra80", ra80_sizes, /* 1 = ra80 */ 209332523Sbostic 31, 14, 559, 209432523Sbostic "rc25-removable", ra25_sizes, /* 2 = rc25-r */ 209532523Sbostic 42, 4, 302, 209632523Sbostic "rc25-fixed", ra25_sizes, /* 3 = rc25-f */ 209732523Sbostic 42, 4, 302, 209832523Sbostic "ra60", ra60_sizes, /* 4 = ra60 */ 209932523Sbostic 42, 4, 2382, 210032523Sbostic "ra81", ra81_sizes, /* 5 = ra81 */ 210132523Sbostic 51, 14, 1248, 210232523Sbostic NULL, NULL, /* 6 = ? */ 210332523Sbostic 0, 0, 0, 210432523Sbostic "rx50", rx50_sizes, /* 7 = rx50 */ 210532523Sbostic 10, 1, 80, 210632523Sbostic "rd52", rd52_sizes, /* 8 = rd52 */ 210732523Sbostic 18, 7, 480, 210832523Sbostic "rd53", rd53_sizes, /* 9 = rd53 */ 210932523Sbostic 18, 8, 963, 211032523Sbostic }; 211132523Sbostic 211232523Sbostic #define NTYPES (sizeof(udatypes) / sizeof(*udatypes)) 211332523Sbostic 211432523Sbostic udamaptype(unit, lp) 211532523Sbostic int unit; 211630536Skarels register struct disklabel *lp; 211730536Skarels { 211832523Sbostic register struct udatypes *ut; 211932523Sbostic register struct size *sz; 212030536Skarels register struct partition *pp; 212132523Sbostic register char *p; 212232523Sbostic register int i; 212332523Sbostic register struct ra_info *ra = &ra_info[unit]; 212430536Skarels 212532523Sbostic lp->d_secsize = 512; 212632523Sbostic lp->d_secperunit = ra->ra_dsize; 212732523Sbostic if ((u_long)ra->ra_type >= NTYPES) { 212832523Sbostic printf("ra%d: don't have a partition table for", unit); 212932523Sbostic mscp_printmedia(ra->ra_mediaid); 213032523Sbostic lp->d_nsectors = ra->ra_geom.rg_nsectors; 213132523Sbostic lp->d_ntracks = ra->ra_geom.rg_ntracks; 213232523Sbostic lp->d_ncylinders = ra->ra_geom.rg_ncyl; 213332523Sbostic printf(";\nusing (t,s,c)=(%d,%d,%d)\n", lp->d_nsectors, 213432523Sbostic lp->d_ntracks, lp->d_ncylinders); 213532523Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 213632523Sbostic lp->d_typename[0] = 'r'; 213732523Sbostic lp->d_typename[1] = 'a'; 213832523Sbostic lp->d_typename[2] = '?'; 213932523Sbostic lp->d_typename[3] = '?'; 214032523Sbostic lp->d_typename[4] = 0; 214130536Skarels lp->d_npartitions = 1; 214230536Skarels lp->d_partitions[0].p_offset = 0; 214330536Skarels lp->d_partitions[0].p_size = lp->d_secperunit; 214430536Skarels return (0); 214530536Skarels } 214632523Sbostic ut = &udatypes[ra->ra_type]; 214732523Sbostic p = ut->ut_name; 214832523Sbostic for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++) 214932523Sbostic lp->d_typename[i] = *p++; 215032523Sbostic lp->d_typename[i] = 0; 215132523Sbostic sz = ut->ut_sizes; 215232523Sbostic /* GET nsectors, ntracks, ncylinders FROM SAVED GEOMETRY? */ 215332523Sbostic lp->d_nsectors = ut->ut_nsectors; 215432523Sbostic lp->d_ntracks = ut->ut_ntracks; 215532523Sbostic lp->d_ncylinders = ut->ut_ncylinders; 215630536Skarels lp->d_npartitions = 8; 215730536Skarels lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 215832523Sbostic for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) { 215932523Sbostic pp->p_offset = sz->blkoff; 216032523Sbostic if ((pp->p_size = sz->nblocks) == (u_long)-1) 216132523Sbostic pp->p_size = ra->ra_dsize - sz->blkoff; 216230536Skarels } 216330536Skarels return (1); 216430536Skarels } 216532523Sbostic #endif /* COMPAT_42 */ 216632523Sbostic #endif /* NUDA > 0 */ 2167