w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
Rw11CntlRL11.cpp
Go to the documentation of this file.
1// $Id: Rw11CntlRL11.cpp 1186 2019-07-12 17:49:59Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2014-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4// Other credits:
5// the boot code is from the simh project and Copyright Robert M Supnik
6// CalcCrc() is adopted from the simh project and Copyright Robert M Supnik
7//
8// Revision History:
9// Date Rev Version Comment
10// 2019-04-14 1131 1.0.12 proper unit init, call UnitSetupAll() in Start()
11// 2019-02-23 1114 1.0.11 use std::bind instead of lambda
12// 2018-12-22 1091 1.0.10 AttnHandler(): sa->san (-Wshadow fix)
13// 2018-12-19 1090 1.0.9 use RosPrintf(bool)
14// 2018-12-15 1082 1.0.8 use std::bind or lambda instead of boost::bind
15// 2018-12-09 1080 1.0.7 use HasVirt(); Virt() returns ref
16// 2018-10-28 1062 1.0.6 replace boost/foreach
17// 2017-04-02 865 1.0.5 Dump(): add detail arg
18// 2017-03-03 858 1.0.4 use cntl name as message prefix
19// 2017-02-26 857 1.0.3 use kCPAH_M_UBM22
20// 2015-06-04 686 1.0.2 check for spurious lams
21// 2015-03-04 655 1.0.1 use original boot code again
22// 2015-03-01 653 1.0 Initial version
23// 2014-06-08 561 0.1 First draft
24// ---------------------------------------------------------------------------
25
30#include <functional>
31
32#include "librtools/RosFill.hpp"
36#include "librtools/RlogMsg.hpp"
37
38#include "Rw11CntlRL11.hpp"
39
40using namespace std;
41using namespace std::placeholders;
42
48// all method definitions in namespace Retro
49namespace Retro {
50
51//------------------------------------------+-----------------------------------
52// constants definitions
53
54const uint16_t Rw11CntlRL11::kIbaddr;
55const int Rw11CntlRL11::kLam;
56
57const uint16_t Rw11CntlRL11::kRLCS;
58const uint16_t Rw11CntlRL11::kRLBA;
59const uint16_t Rw11CntlRL11::kRLDA;
60const uint16_t Rw11CntlRL11::kRLMP;
61
62const uint16_t Rw11CntlRL11::kProbeOff;
65
66const uint16_t Rw11CntlRL11::kRLCS_M_ERR;
67const uint16_t Rw11CntlRL11::kRLCS_M_DE;
68const uint16_t Rw11CntlRL11::kRLCS_V_E;
69const uint16_t Rw11CntlRL11::kRLCS_B_E;
70const uint16_t Rw11CntlRL11::kRLCS_V_DS;
71const uint16_t Rw11CntlRL11::kRLCS_B_DS;
72const uint16_t Rw11CntlRL11::kRLCS_M_CRDY;
73const uint16_t Rw11CntlRL11::kRLCS_M_IE;
74const uint16_t Rw11CntlRL11::kRLCS_M_BAE;
75const uint16_t Rw11CntlRL11::kRLCS_V_BAE;
76const uint16_t Rw11CntlRL11::kRLCS_B_BAE;
77const uint16_t Rw11CntlRL11::kRLCS_V_FUNC;
78const uint16_t Rw11CntlRL11::kRLCS_B_FUNC;
79const uint16_t Rw11CntlRL11::kRLCS_M_DRDY;
80
81const uint16_t Rw11CntlRL11::kFUNC_NOOP;
82const uint16_t Rw11CntlRL11::kFUNC_WCHK;
83const uint16_t Rw11CntlRL11::kFUNC_GS;
84const uint16_t Rw11CntlRL11::kFUNC_SEEK;
85const uint16_t Rw11CntlRL11::kFUNC_RHDR;
86const uint16_t Rw11CntlRL11::kFUNC_WRITE;
87const uint16_t Rw11CntlRL11::kFUNC_READ;
88const uint16_t Rw11CntlRL11::kFUNC_RNHC;
89
90const uint16_t Rw11CntlRL11::kERR_M_DE;
91const uint16_t Rw11CntlRL11::kERR_OPI;
92const uint16_t Rw11CntlRL11::kERR_WCHK;
93const uint16_t Rw11CntlRL11::kERR_HCRC;
94const uint16_t Rw11CntlRL11::kERR_DLATE;
95const uint16_t Rw11CntlRL11::kERR_HNFND;
96const uint16_t Rw11CntlRL11::kERR_NXM;
97
98const uint16_t Rw11CntlRL11::kRLCS_V_MPREM;
99const uint16_t Rw11CntlRL11::kRLCS_B_MPREM;
100const uint16_t Rw11CntlRL11::kRLCS_V_MPLOC;
101const uint16_t Rw11CntlRL11::kRLCS_B_MPLOC;
102const uint16_t Rw11CntlRL11::kRLCS_ENA_MPREM;
103const uint16_t Rw11CntlRL11::kRLCS_ENA_MPLOC;
104
105const uint16_t Rw11CntlRL11::kRFUNC_WCS;
106const uint16_t Rw11CntlRL11::kRFUNC_WMP;
107
108const uint16_t Rw11CntlRL11::kMPREM_M_MAP;
109const uint16_t Rw11CntlRL11::kMPREM_M_SEQ;
110const uint16_t Rw11CntlRL11::kMPREM_S_MP;
111const uint16_t Rw11CntlRL11::kMPREM_S_STA;
112const uint16_t Rw11CntlRL11::kMPREM_S_POS;
113
114const uint16_t Rw11CntlRL11::kMPREM_MP;
115const uint16_t Rw11CntlRL11::kMPREM_CRC;
116const uint16_t Rw11CntlRL11::kMPREM_STA;
117const uint16_t Rw11CntlRL11::kMPREM_POS;
118
120
121const uint16_t Rw11CntlRL11::kMPLOC_MP;
122const uint16_t Rw11CntlRL11::kMPLOC_STA;
123const uint16_t Rw11CntlRL11::kMPLOC_POS;
124const uint16_t Rw11CntlRL11::kMPLOC_ZERO;
125const uint16_t Rw11CntlRL11::kMPLOC_CRC;
126
127const uint16_t Rw11CntlRL11::kRLDA_SE_M_DF;
128const uint16_t Rw11CntlRL11::kRLDA_SE_V_DF;
129const uint16_t Rw11CntlRL11::kRLDA_SE_B_DF;
130const uint16_t Rw11CntlRL11::kRLDA_SE_M_HS;
131const uint16_t Rw11CntlRL11::kRLDA_SE_M_DIR;
132const uint16_t Rw11CntlRL11::kRLDA_SE_X_MSK;
133const uint16_t Rw11CntlRL11::kRLDA_SE_X_VAL;
134
135const uint16_t Rw11CntlRL11::kRLDA_RW_M_CA;
136const uint16_t Rw11CntlRL11::kRLDA_RW_V_CA;
137const uint16_t Rw11CntlRL11::kRLDA_RW_B_CA;
138const uint16_t Rw11CntlRL11::kRLDA_RW_M_HS;
139const uint16_t Rw11CntlRL11::kRLDA_RW_V_HS;
140const uint16_t Rw11CntlRL11::kRLDA_RW_B_HS;
141const uint16_t Rw11CntlRL11::kRLDA_RW_B_SA;
142
143const uint16_t Rw11CntlRL11::kRLDA_GS_M_RST;
144const uint16_t Rw11CntlRL11::kRLDA_GS_X_MSK;
145const uint16_t Rw11CntlRL11::kRLDA_GS_X_VAL;
146
147const uint16_t Rw11CntlRL11::kSTA_M_WDE;
148const uint16_t Rw11CntlRL11::kSTA_M_CHE;
149const uint16_t Rw11CntlRL11::kSTA_M_WL;
150const uint16_t Rw11CntlRL11::kSTA_M_STO;
151const uint16_t Rw11CntlRL11::kSTA_M_SPE;
152const uint16_t Rw11CntlRL11::kSTA_M_WGE;
153const uint16_t Rw11CntlRL11::kSTA_M_VCE;
154const uint16_t Rw11CntlRL11::kSTA_M_DSE;
155const uint16_t Rw11CntlRL11::kSTA_M_DT;
156const uint16_t Rw11CntlRL11::kSTA_M_HS;
157const uint16_t Rw11CntlRL11::kSTA_M_CO;
158const uint16_t Rw11CntlRL11::kSTA_M_HO;
159const uint16_t Rw11CntlRL11::kSTA_M_BH;
160const uint16_t Rw11CntlRL11::kSTA_B_ST;
161
162const uint16_t Rw11CntlRL11::kST_LOAD;
163const uint16_t Rw11CntlRL11::kST_SPIN;
164const uint16_t Rw11CntlRL11::kST_BRUSH;
165const uint16_t Rw11CntlRL11::kST_HLOAD;
166const uint16_t Rw11CntlRL11::kST_SEEK;
167const uint16_t Rw11CntlRL11::kST_LOCK;
168const uint16_t Rw11CntlRL11::kST_UNL;
169const uint16_t Rw11CntlRL11::kST_DOWN;
170
171//------------------------------------------+-----------------------------------
173
175 : Rw11CntlBase<Rw11UnitRL11,4>("rl11"),
176 fPC_rlcs(0),
177 fPC_rlba(0),
178 fPC_rlda(0),
179 fPC_imp(0),
180 fPC_wc(0),
181 fPC_sta(0),
182 fPC_pos(0),
183 fRd_rlcs(0),
184 fRd_rlda(0),
185 fRd_rlmp(0),
186 fRd_sta(0),
187 fRd_pos(0),
188 fRd_addr(0),
189 fRd_lba(0),
190 fRd_nwrd(0),
191 fRd_fu(0),
192 fRd_ovr(false),
193 fRdma(this,
194 std::bind(&Rw11CntlRL11::RdmaPreExecCB, this, _1, _2, _3, _4),
195 std::bind(&Rw11CntlRL11::RdmaPostExecCB, this, _1, _2, _3, _4))
196{
197 // must be here because Units have a back-ptr (not available at Rw11CntlBase)
198 for (size_t i=0; i<NUnit(); i++) {
199 fspUnit[i].reset(new Rw11UnitRL11(this, i));
200 }
201
202 fStats.Define(kStatNFuncWchk , "NFuncWchk" , "func WCHK");
203 fStats.Define(kStatNFuncRhdr , "NFuncRhdr" , "func RHDR");
204 fStats.Define(kStatNFuncWrite , "NFuncWrite" , "func WRITE");
205 fStats.Define(kStatNFuncRead , "NFuncRead" , "func READ");
206 fStats.Define(kStatNFuncRnhc , "NFuncRnhc" , "func RNHC");
207}
208
209//------------------------------------------+-----------------------------------
211
213{}
214
215//------------------------------------------+-----------------------------------
217
218void Rw11CntlRL11::Config(const std::string& name, uint16_t base, int lam)
219{
220 ConfigCntl(name, base, lam, kProbeOff, kProbeInt, kProbeRem);
221 return;
222}
223
224//------------------------------------------+-----------------------------------
226
228{
229 if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
230 throw Rexception("Rw11CntlRL11::Start",
231 "Bad state: started, no lam, not enable, not found");
232
233 // add device register address ibus and rbus mappings
234 // done here because now Cntl bound to Cpu and Cntl probed
235 Cpu().AllIAddrMapInsert(Name()+".cs", Base() + kRLCS);
236 Cpu().AllIAddrMapInsert(Name()+".ba", Base() + kRLBA);
237 Cpu().AllIAddrMapInsert(Name()+".da", Base() + kRLDA);
238 Cpu().AllIAddrMapInsert(Name()+".mp", Base() + kRLMP);
239
240 // ensure unit status is initialized
241 UnitSetupAll();
242
243 // setup primary info clist
256
257 // add attn handler
259 uint16_t(1)<<fLam, this);
260
261 fStarted = true;
262 return;
263}
264
265//------------------------------------------+-----------------------------------
267
269{
270 Rw11UnitRL11& unit = *fspUnit[ind];
271 RlinkCommandList clist;
272
273 // only two mayor drive states are used
274 // on: st=lock; ho=1; bh=1; co=0; wl=? ( file attached)
275 // off: st=load; ho=0; bh=1; co=1; (no file attached)
276
277 uint16_t sta = 0;
278 if (unit.Type() == "rl02") // is it RL02
279 sta |= kSTA_M_DT; // set DT bit (1=RL02,0=RL01)
280
281 if (unit.HasVirt()) { // file attached
282 sta |= kSTA_M_HO | kSTA_M_BH | kST_LOCK; // HO=1; BH=1; ST=LOCK
283 if (unit.WProt()) // in case write protected
284 sta |= kSTA_M_WL; // WL=1
285 } else { // no file attached
286 sta |= kSTA_M_CO | kSTA_M_BH | kST_LOAD; // CO=1; BH=1; ST=LOAD
287 AddSetPosition(clist, ind, 0); // well defined value to pos
288 }
289
290 unit.SetRlsta(sta);
291 AddSetStatus(clist, ind, sta);
292 Server().Exec(clist);
293
294 return;
295}
296
297//------------------------------------------+-----------------------------------
299
300bool Rw11CntlRL11::BootCode(size_t unit, std::vector<uint16_t>& code,
301 uint16_t& aload, uint16_t& astart)
302{
303 uint16_t kBOOT_START = 02000;
304 uint16_t bootcode[] = { // rl11 boot loader - from simh pdp11_rl.c (v3.9)
305 0042114, // "LD"
306 0012706, kBOOT_START, // MOV #boot_start, SP
307 0012700, uint16_t(unit), // MOV #unit, R0
308 0010003, // MOV R0, R3
309 0000303, // SWAB R3
310 0012701, 0174400, // MOV #RLCS, R1 ; csr
311 0012761, 0000013, 0000004, // MOV #13, 4(R1) ; clr err
312 0052703, 0000004, // BIS #4, R3 ; unit+gstat
313 0010311, // MOV R3, (R1) ; issue cmd
314 0105711, // TSTB (R1) ; wait
315 0100376, // BPL .-2
316 0105003, // CLRB R3
317 0052703, 0000010, // BIS #10, R3 ; unit+rdhdr
318 0010311, // MOV R3, (R1) ; issue cmd
319 0105711, // TSTB (R1) ; wait
320 0100376, // BPL .-2
321 0016102, 0000006, // MOV 6(R1), R2 ; get hdr
322 0042702, 0000077, // BIC #077, R2 ; clr head+sector
323 0005202, // INC R2 ; magic bit
324 0010261, 0000004, // MOV R2, 4(R1) ; seek to 0
325 0105003, // CLRB R3
326 0052703, 0000006, // BIS #6, R3 ; unit+seek
327 0010311, // MOV R3, (R1) ; issue cmd
328 0105711, // TSTB (R1) ; wait
329 0100376, // BPL .-2
330 0005061, 0000002, // CLR 2(R1) ; clr ba
331 0005061, 0000004, // CLR 4(R1) ; clr da
332 0012761, 0177000, 0000006, // MOV #-512., 6(R1) ; set wc
333 0105003, // CLRB R3
334 0052703, 0000014, // BIS #14, R3 ; unit+read
335 0010311, // MOV R3, (R1) ; issue cmd
336 0105711, // TSTB (R1) ; wait
337 0100376, // BPL .-2
338 0042711, 0000377, // BIC #377, (R1)
339 0005002, // CLR R2
340 0005003, // CLR R3
341 0012704, uint16_t(kBOOT_START+020), // MOV #START+20, R4 ; load #rlcs
342 0005005, // CLR R5
343 0005007 // CLR PC
344 };
345
346 code.clear();
347 code.insert(code.end(), std::begin(bootcode), std::end(bootcode));
348 aload = kBOOT_START;
349 astart = kBOOT_START+2;
350 return true;
351}
352
353//------------------------------------------+-----------------------------------
355
356void Rw11CntlRL11::Dump(std::ostream& os, int ind, const char* text,
357 int detail) const
358{
359 RosFill bl(ind);
360 os << bl << (text?text:"--") << "Rw11CntlRL11 @ " << this << endl;
361 os << bl << " fPC_rlcs: " << RosPrintf(fPC_rlcs,"d",6) << endl;
362 os << bl << " fPC_rlba: " << RosPrintf(fPC_rlba,"d",6) << endl;
363 os << bl << " fPC_rlda: " << RosPrintf(fPC_rlda,"d",6) << endl;
364 os << bl << " fPC_imp: " << RosPrintf(fPC_imp,"d",6) << endl;
365 os << bl << " fPC_wc: " << RosPrintf(fPC_wc,"d",6) << endl;
366 os << bl << " fPC_sta: " << RosPrintf(fPC_sta,"d",6) << endl;
367 os << bl << " fPC_pos: " << RosPrintf(fPC_pos,"d",6) << endl;
368 os << bl << " fRd_rlcs: " << RosPrintBvi(fRd_rlcs,8) << endl;
369 os << bl << " fRd_rlda: " << RosPrintBvi(fRd_rlda,8) << endl;
370 os << bl << " fRd_rlmp: " << RosPrintBvi(fRd_rlmp,8) << endl;
371 os << bl << " fRd_sta: " << RosPrintBvi(fRd_sta,8) << endl;
372 os << bl << " fRd_pos: " << RosPrintBvi(fRd_pos,8) << endl;
373 os << bl << " fRd_addr: " << RosPrintBvi(fRd_addr,8,22) << endl;
374 os << bl << " fRd_lba: " << RosPrintf(fRd_lba,"d",6) << endl;
375 os << bl << " fRd_nwrd: " << RosPrintf(fRd_nwrd,"d",6) << endl;
376 os << bl << " fRd_fu: " << RosPrintf(fRd_fu,"d",6) << endl;
377 os << bl << " fRd_ovr: " << RosPrintf(fRd_ovr) << endl;
378 fRdma.Dump(os, ind+2, "fRdma: ", detail);
379 Rw11CntlBase<Rw11UnitRL11,4>::Dump(os, ind, " ^", detail);
380 return;
381}
382
383//------------------------------------------+-----------------------------------
385
387{
390
391 uint16_t rlcs = fPrimClist[fPC_rlcs].Data();
392 uint16_t rlba = fPrimClist[fPC_rlba].Data();
393 uint16_t rlda = fPrimClist[fPC_rlda].Data();
394 uint16_t wc = fPrimClist[fPC_wc ].Data();
395 uint16_t sta = fPrimClist[fPC_sta ].Data();
396 uint16_t pos = fPrimClist[fPC_pos ].Data();
397
398 uint16_t ds = (rlcs>>kRLCS_V_DS) & kRLCS_B_DS;
399 uint16_t fu = (rlcs>>kRLCS_V_FUNC) & kRLCS_B_FUNC;
400 uint16_t bae = (rlcs>>kRLCS_V_BAE) & kRLCS_B_BAE;
401
402 uint32_t addr = uint32_t(bae)<<16 | uint32_t(rlba);
403
404 uint16_t sa = rlda & kRLDA_RW_B_SA;
405 uint16_t hs = (rlda>>kRLDA_RW_V_HS) & kRLDA_RW_B_HS;
406 uint16_t ca = (rlda>>kRLDA_RW_V_CA) & kRLDA_RW_B_CA;
407
408 uint32_t nwrd = (~uint32_t(wc)&0xffff) + 1; // transfer size in words
409
410 // all 4 units are always available, but check anyway
411 if (ds > NUnit())
412 throw Rexception("Rw11CntlRL11::AttnHandler","Bad state: ds > NUnit()");
413
414 Rw11UnitRL11& unit = *fspUnit[ds];
415 Rw11Cpu& cpu = Cpu();
416 RlinkCommandList clist;
417
418 uint32_t lba = unit.Chs2Lba(ca,hs,sa);
419 uint32_t nblk = unit.Nwrd2Nblk(nwrd);
420
421 // check for overrun (read/write beyond track)
422 // if found, truncate request length
423 bool ovr = false;
424 if (fu==kFUNC_WRITE || fu==kFUNC_WCHK || fu==kFUNC_READ || fu==kFUNC_RNHC) {
425 ovr = sa + nblk > unit.NSector();
426 if (ovr) nwrd = (unit.NSector()-sa) * (unit.BlockSize()/2);
427 }
428
429 if (fTraceLevel>0) {
430 RlogMsg lmsg(LogFile());
431 static const char* fumnemo[8] = {"no","wc","gs","se","rh","w ","r ","rn"};
432 lmsg << "-I " << Name() << ":"
433 << " cs=" << RosPrintBvi(rlcs,8)
434 << " da=" << RosPrintBvi(rlda,8)
435 << " ad=" << RosPrintBvi(addr,8,18)
436 << " fu=" << fumnemo[fu&0x7]
437 << " pa=" << ds
438 << "," << RosPrintf(ca,"d",3)
439 << "," << hs
440 << "," << RosPrintf(sa,"d",2)
441 << " la,nw=" << RosPrintf(lba,"d",5)
442 << ",";
443 if (nwrd==65536) lmsg << " (0)"; else lmsg << RosPrintf(nwrd,"d",4);
444 if (ovr) lmsg << "!";
445 }
446
447 // check for spurious interrupts (either RDY=1 or RDY=0 and rdma busy)
448 if ((rlcs & kRLCS_M_CRDY) || fRdma.IsActive()) {
449 RlogMsg lmsg(LogFile());
450 lmsg << "-E " << Name() << ": err"
451 << " cr=" << RosPrintBvi(rlcs,8)
452 << " spurious lam: "
453 << (fRdma.IsActive() ? "RDY=0 and Rdma busy" : "RDY=1");
454 return 0;
455 }
456
457 // remember request parameters for call back and error exit handling
458 fRd_rlcs = rlcs;
459 fRd_rlda = rlda;
460 fRd_rlmp = wc;
461 fRd_sta = sta;
462 fRd_pos = pos;
463 fRd_addr = addr;
464 fRd_lba = lba;
465 fRd_nwrd = nwrd;
466 fRd_ovr = ovr;
467 fRd_fu = fu;
468
469 // check for general abort conditions
470 // note: only 'data transfer' functions handled via backend
471 // SEEK and GSTA are done in ibdr_rl11 autonomously
472
473 // not attached --> assumed Offline, status = load
474 if (! unit.HasVirt()) { // not attached
475 AddErrorExit(clist, kERR_OPI); // just signal OPI
476 // drive stat is LOAD anyway
477 Server().Exec(clist); // doit
478 return 0;
479 }
480
481 // handle Read Header
482 // no data transfer, done here to keep crc calc out of firmware
483 if (fu == kFUNC_RHDR) {
485 uint16_t buf[2] = {pos, 0};
486 uint16_t crc = CalcCrc(2, buf);
487
488 cpu.AddWibr(clist, fBase+kRLCS,
494 cpu.AddWibr(clist, fBase+kRLMP, crc);
495
496 // simulate rotation, inc sector number, wrap at end of track
497 uint16_t san = (pos & kRLDA_RW_B_SA) + 1;
498 if (san >= unit.NSector()) san = 0; // wrap to begin of track
499 uint16_t posn = (pos & (kRLDA_RW_M_CA|kRLDA_RW_M_HS)) + san;
500 AddSetPosition(clist, ds, posn);
501
502 uint16_t cs = kRLCS_M_CRDY | // signal command done
503 (rlcs & kRLCS_M_BAE) | // keep BAE
505
506 cpu.AddWibr(clist, fBase+kRLCS, cs);
507
508 if (fTraceLevel>1) {
509 RlogMsg lmsg(LogFile());
510 lmsg << "-I " << Name() << ":"
511 << " ok cs=" << RosPrintBvi(cs,8)
512 << " mp=" << RosPrintBvi(crc,8)
513 << " pos=" << RosPrintBvi(pos,8)
514 << "->" << RosPrintBvi(posn,8);
515 }
516 Server().Exec(clist); // doit
517 return 0;
518 }
519
520 // now only data transfer functions to handle
521
522 // check track number and proper head positioning
523 bool poserr = sa >= unit.NSector(); // track number valid ?
524 if (fu != kFUNC_RNHC) { // unless RNHC: check proper head pos
525 uint16_t pos_ch = pos & (kRLDA_RW_M_CA|kRLDA_RW_M_HS); // pos: cyl+hd
526 uint16_t rlda_ch = rlda & (kRLDA_RW_M_CA|kRLDA_RW_M_HS); // da: cyl+hd
527 poserr |= pos_ch != rlda_ch;
528 }
529 if (true && poserr) {
530 AddErrorExit(clist, kERR_HNFND);
531 Server().Exec(clist); // doit
532 return 0;
533 }
534
535 // now handle the functions
536
537 if (fu == kFUNC_WRITE) { // Write -------------------------
539 if (unit.WProt()) { // write on write locked drive ?
540 AddSetStatus(clist, ds, sta | kSTA_M_WGE);
541 AddErrorExit(clist, kERR_M_DE);
542 } else {
543 fRdma.QueueDiskWrite(addr, nwrd, Rw11Cpu::kCPAH_M_UBM22, lba, &unit);
544 }
545
546 } else if (fu == kFUNC_WCHK) { // Write Check -------------------
548 fRdma.QueueDiskWriteCheck(addr, nwrd, Rw11Cpu::kCPAH_M_UBM22, lba, &unit);
549
550 } else if (fu == kFUNC_READ || // Read or
551 fu == kFUNC_RNHC) { // Read No Header Check ----------
553
554 fRdma.QueueDiskRead(addr, nwrd, Rw11Cpu::kCPAH_M_UBM22, lba, &unit);
555 }
556
557 if (clist.Size()) { // if handled directly
558 Server().Exec(clist); // doit
559 }
560 return 0;
561}
562
563//------------------------------------------+-----------------------------------
565
566void Rw11CntlRL11::RdmaPreExecCB(int stat, size_t nwdone, size_t nwnext,
567 RlinkCommandList& clist)
568{
569 // if last chunk and not doing WCHK add a labo and normal exit csr update
570 if (stat == Rw11Rdma::kStatusBusyLast && fRd_fu != kFUNC_WCHK) {
571 clist.AddLabo();
572 AddNormalExit(clist, nwdone+nwnext, 0);
573 }
574 return;
575}
576
577//------------------------------------------+-----------------------------------
579
580void Rw11CntlRL11::RdmaPostExecCB(int stat, size_t ndone,
581 RlinkCommandList& clist, size_t ncmd)
582{
583 if (stat == Rw11Rdma::kStatusBusy) return;
584
585 uint16_t rlerr = 0;
586
587 // handle write check
588 if (fRd_fu == kFUNC_WCHK) {
589 size_t nwcok = fRdma.WriteCheck(ndone);
590 if (nwcok != ndone) { // if mismatch found
591 rlerr = kERR_WCHK; // set error
592 ndone = nwcok; // truncate word count
593 }
594 }
595
596 // handle Rdma aborts
597 if (stat == Rw11Rdma::kStatusFailRdma && rlerr == 0) rlerr = kERR_NXM;
598
599 // check for fused csr updates
600 if (clist.Size() > ncmd) {
601 uint8_t ccode = clist[ncmd].Command();
602 uint16_t cdata = clist[ncmd].Data();
603 if (ccode != RlinkCommand::kCmdLabo || (rlerr != 0 && cdata == 0))
604 throw Rexception("Rw11CntlRL11::RdmaPostExecCB",
605 "Bad state: Labo not found or missed abort");
606 if (cdata == 0) return;
607 }
608
609 // finally to RL11 register update
610 RlinkCommandList clist1;
611 AddNormalExit(clist1, ndone, rlerr);
612 Server().Exec(clist1);
613 return;
614}
615
616//------------------------------------------+-----------------------------------
618
619void Rw11CntlRL11::LogRler(uint16_t rlerr)
620{
621 RlogMsg lmsg(LogFile());
622 lmsg << "-E " << Name() << ":"
623 << " err=" << RosPrintBvi(rlerr,2,5) << " ERROR ABORT";
624 return;
625}
626
627//------------------------------------------+-----------------------------------
629
631 uint16_t pos)
632{
633 Rw11Cpu& cpu = Cpu();
634 cpu.AddWibr(clist, fBase+kRLCS,
635 ((kMPREM_POS+ind)<<kRLCS_V_MPREM) | // address pos(unit)
636 kRLCS_ENA_MPREM | // update MPREM
637 (kRFUNC_WMP << kRLCS_V_FUNC) ); // write MP
638 cpu.AddWibr(clist, fBase+kRLMP, pos);
639 return;
640}
641
642//------------------------------------------+-----------------------------------
644
646 uint16_t sta)
647{
648 Rw11Cpu& cpu = Cpu();
649 cpu.AddWibr(clist, fBase+kRLCS,
650 ((kMPREM_STA+ind)<<kRLCS_V_MPREM) | // address sta(unit)
651 kRLCS_ENA_MPREM | // update MPREM
652 (kRFUNC_WMP << kRLCS_V_FUNC) ); // write MP
653 cpu.AddWibr(clist, fBase+kRLMP, sta);
654 return;
655}
656
657//------------------------------------------+-----------------------------------
659
661{
662 Rw11Cpu& cpu = Cpu();
663 uint16_t cs = kRLCS_M_ERR | // set ERR flag
664 (rlerr << kRLCS_V_E) | // set DE and E fields
665 kRLCS_M_CRDY | // signal command done
666 (fRd_rlcs & kRLCS_M_BAE) | // keep BAE
667 (kRFUNC_WCS << kRLCS_V_FUNC); // write CS
668 cpu.AddWibr(clist, fBase+kRLCS, cs);
669
670 if (fTraceLevel>1) {
671 RlogMsg lmsg(LogFile());
672 lmsg << "-I " << Name() << ": err"
673 << " cs=" << RosPrintBvi(cs,8)
674 << " err=" << RosPrintBvi(rlerr,2,5)
675 << " pos=" << RosPrintBvi(fRd_pos,8);
676 }
677
678 return;
679}
680
681//------------------------------------------+-----------------------------------
683
685 uint16_t rlerr)
686{
687 Rw11Cpu& cpu = Cpu();
688 uint16_t ds = (fRd_rlcs>>kRLCS_V_DS) & kRLCS_B_DS;
689 Rw11UnitRL11& unit = *fspUnit[ds];
690
691 size_t nblk = unit.Nwrd2Nblk(ndone);
692
693 uint32_t addr = fRd_addr + 2*ndone;
694
695 uint16_t ba = addr & 0177776; // get lower 16 bits
696 uint16_t bae = (addr>>16) & 03; // get upper 2 bits
697
698 uint16_t da = fRd_rlda+uint16_t(nblk);
699
700 uint16_t rlmp = fRd_rlmp + uint16_t(ndone);
701
702 if (fRd_ovr && rlerr == 0) rlerr = kERR_HNFND;
703
704 cpu.AddWibr(clist, fBase+kRLBA, ba);
705 cpu.AddWibr(clist, fBase+kRLDA, da);
706 cpu.AddWibr(clist, fBase+kRLCS,
712 cpu.AddWibr(clist, fBase+kRLMP, rlmp);
713
714 // set drive position to one sector past the last the read sector
715 // Note: take sa from rlda, and ca+hs from fRd_pos (controller context!)
716 // in case of errors this probably the best solution
717 uint16_t sa = (fRd_rlda & kRLDA_RW_B_SA) + uint16_t(nblk);
718 if (sa >= unit.NSector()) sa = 0; // wrap to begin of track
719 uint16_t posn = (fRd_pos & (kRLDA_RW_M_CA|kRLDA_RW_M_HS)) + sa;
720 AddSetPosition(clist, ds, posn);
721
722 uint16_t cs = kRLCS_M_CRDY |
723 (bae << kRLCS_V_BAE) |
725 if (rlerr) cs |= (rlerr << kRLCS_V_E);
726 cpu.AddWibr(clist, fBase+kRLCS, cs);
727
728 if (fTraceLevel>1) {
729 RlogMsg lmsg(LogFile());
730 lmsg << "-I " << Name() << (rlerr==0 ? ": ok" : ": err")
731 << " cs=" << RosPrintBvi(cs,8)
732 << " ba=" << RosPrintBvi(ba,8)
733 << " da=" << RosPrintBvi(da,8)
734 << " mp=" << RosPrintBvi(rlmp,8);
735 if (rlerr) lmsg << " err=" << RosPrintBvi(rlerr,2,5);
736 lmsg << " pos=" << RosPrintBvi(fRd_pos,8)
737 << "->" << RosPrintBvi(posn,8);
738 }
739
740 return;
741}
742
743//------------------------------------------+-----------------------------------
745// Note:
746// CalcCrc() is adopted from the simh project and Copyright Robert M Supnik
747
748uint16_t Rw11CntlRL11::CalcCrc(size_t size, const uint16_t* data)
749{
750 uint32_t crc=0;
751
752 for (size_t i = 0; i < size; i++) {
753 uint32_t d = *data++;
754 /* cribbed from KG11-A */
755 for (size_t j = 0; j < 16; j++) {
756 crc = (crc & ~01) | ((crc & 01) ^ (d & 01));
757 crc = (crc & 01) ? (crc >> 1) ^ 0120001 : crc >> 1;
758 d >>= 1;
759 }
760 }
761 return crc;
762}
763
764
765} // end namespace Retro
FIXME_docs.
Definition: Rexception.hpp:29
size_t AddAttn()
FIXME_docs.
size_t Size() const
FIXME_docs.
size_t AddLabo()
FIXME_docs.
static const uint8_t kCmdLabo
command code list abort
void AddAttnHandler(attnhdl_t &&attnhdl, uint16_t mask, void *cdata=nullptr)
FIXME_docs.
void GetAttnInfo(AttnArgs &args, RlinkCommandList &clist)
FIXME_docs.
bool Exec(RlinkCommandList &clist, RerrMsg &emsg)
FIXME_docs.
Definition: RlinkServer.ipp:60
FIXME_docs.
Definition: RlogMsg.hpp:24
I/O appicator to generate fill characters.
Definition: RosFill.hpp:24
void Inc(size_t ind, double val=1.)
FIXME_docs.
Definition: Rstats.ipp:29
void Define(size_t ind, const std::string &name, const std::string &text)
FIXME_docs.
Definition: Rstats.cpp:72
Implemenation (inline) of Rw11CntlBase.
virtual void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
virtual size_t NUnit() const
FIXME_docs.
std::shared_ptr< Rw11UnitRL11 > fspUnit[NU]
static const uint16_t kMPREM_M_SEQ
uint16_t fRd_fu
Rdma: request fu code.
static const uint16_t kRLDA_SE_M_HS
static const uint16_t kMPLOC_STA
static const uint16_t kSTA_M_HO
uint16_t fRd_rlda
Rdma: request rlda.
static const bool kProbeRem
probr rem active
static const uint16_t kSTA_M_WL
static const uint16_t kMPREM_S_MP
bool fRd_ovr
Rdma: overrun condition found.
static const uint16_t kMPREM_SEQ_MPSTAPOS
~Rw11CntlRL11()
Destructor.
static const uint16_t kERR_HCRC
static const uint16_t kFUNC_READ
void RdmaPreExecCB(int stat, size_t nwdone, size_t nwnext, RlinkCommandList &clist)
FIXME_docs.
virtual bool BootCode(size_t unit, std::vector< uint16_t > &code, uint16_t &aload, uint16_t &astart)
FIXME_docs ????
size_t fPC_imp
PrimClist: imp index.
uint16_t fRd_rlcs
Rdma: request rlcs.
uint16_t fRd_rlmp
Rdma: request rlmp (~wc)
static const uint16_t kRLCS_M_CRDY
static const uint16_t kSTA_M_STO
void AddNormalExit(RlinkCommandList &clist, size_t ndone, uint16_t rlerr=0)
FIXME_docs.
static const uint16_t kRLDA_GS_X_VAL
static const uint16_t kRLDA_RW_B_CA
static const uint16_t kRLDA_SE_B_DF
Rw11RdmaDisk fRdma
Rdma controller.
static const uint16_t kRLCS_M_IE
static const uint16_t kIbaddr
RL11 default address.
static const uint16_t kMPREM_M_MAP
static const uint16_t kST_LOAD
static const int kLam
RL11 default lam.
static const uint16_t kRFUNC_WCS
static const uint16_t kERR_NXM
static const uint16_t kRLDA_RW_V_CA
size_t fPC_rlcs
PrimClist: rlcs index.
static const uint16_t kFUNC_WCHK
static const uint16_t kRLCS_M_BAE
static const uint16_t kRLCS_V_FUNC
static const uint16_t kProbeOff
probe address offset (rlcs)
uint16_t CalcCrc(size_t size, const uint16_t *data)
FIXME_docs.
static const uint16_t kMPREM_CRC
void LogRler(uint16_t rlerr)
FIXME_docs ????
static const uint16_t kRLCS_B_MPLOC
size_t fPC_pos
PrimClist: pos index.
void AddSetPosition(RlinkCommandList &clist, size_t ind, uint16_t pos)
FIXME_docs.
uint32_t fRd_addr
Rdma: current addr.
static const uint16_t kST_BRUSH
static const uint16_t kRLCS_ENA_MPLOC
static const uint16_t kRLDA_GS_X_MSK
static const uint16_t kMPREM_S_STA
void RdmaPostExecCB(int stat, size_t ndone, RlinkCommandList &clist, size_t ncmd)
FIXME_docs.
static const uint16_t kMPREM_S_POS
int AttnHandler(RlinkServer::AttnArgs &args)
FIXME_docs.
static const uint16_t kRLDA
RLDA reg offset.
static const uint16_t kSTA_M_HS
uint32_t fRd_lba
Rdma: current lba.
static const uint16_t kMPLOC_ZERO
static const uint16_t kRLDA_SE_M_DIR
size_t fPC_sta
PrimClist: sta index.
static const uint16_t kMPLOC_CRC
static const uint16_t kERR_WCHK
static const uint16_t kRLCS_ENA_MPREM
static const uint16_t kRLDA_RW_M_CA
void Config(const std::string &name, uint16_t base, int lam)
FIXME_docs.
void AddSetStatus(RlinkCommandList &clist, size_t ind, uint16_t sta)
FIXME_docs.
static const uint16_t kRLDA_RW_B_HS
static const uint16_t kRLBA
RLBA reg offset.
static const uint16_t kRLCS_M_DE
static const uint16_t kRLDA_SE_M_DF
static const uint16_t kST_SEEK
static const uint16_t kRLCS_B_E
static const uint16_t kSTA_M_VCE
static const bool kProbeInt
probe int active
static const uint16_t kSTA_M_CHE
uint16_t fRd_pos
Rdma: initial drive position.
static const uint16_t kFUNC_WRITE
static const uint16_t kSTA_M_DSE
static const uint16_t kERR_HNFND
static const uint16_t kST_DOWN
static const uint16_t kRLCS
RLCS reg offset.
static const uint16_t kFUNC_RNHC
static const uint16_t kRLCS_V_DS
static const uint16_t kERR_OPI
size_t fPC_rlba
PrimClist: rlba index.
static const uint16_t kRLCS_M_ERR
static const uint16_t kFUNC_RHDR
static const uint16_t kSTA_M_WDE
static const uint16_t kRLDA_SE_V_DF
static const uint16_t kRLDA_SE_X_MSK
Rw11CntlRL11()
Default constructor.
static const uint16_t kST_HLOAD
static const uint16_t kERR_M_DE
size_t fPC_wc
PrimClist: wc index.
static const uint16_t kRLDA_RW_V_HS
virtual void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
static const uint16_t kMPLOC_POS
static const uint16_t kSTA_B_ST
size_t fPC_rlda
PrimClist: rlda index.
static const uint16_t kSTA_M_WGE
static const uint16_t kMPLOC_MP
static const uint16_t kRLDA_GS_M_RST
static const uint16_t kSTA_M_SPE
static const uint16_t kRLCS_M_DRDY
static const uint16_t kRLCS_B_BAE
static const uint16_t kRLCS_B_FUNC
static const uint16_t kMPREM_POS
static const uint16_t kRLCS_V_MPREM
uint16_t fRd_sta
Rdma: initial drive status.
static const uint16_t kFUNC_GS
static const uint16_t kRLCS_V_BAE
static const uint16_t kRFUNC_WMP
static const uint16_t kMPREM_MP
static const uint16_t kRLDA_RW_B_SA
virtual void Start()
FIXME_docs.
static const uint16_t kRLCS_V_E
static const uint16_t kFUNC_SEEK
static const uint16_t kFUNC_NOOP
void AddErrorExit(RlinkCommandList &clist, uint16_t rlerr)
FIXME_docs.
static const uint16_t kRLDA_SE_X_VAL
static const uint16_t kST_LOCK
static const uint16_t kST_UNL
static const uint16_t kSTA_M_DT
static const uint16_t kST_SPIN
static const uint16_t kRLMP
RLMP reg offset.
static const uint16_t kRLCS_V_MPLOC
static const uint16_t kMPREM_STA
uint32_t fRd_nwrd
Rdma: current nwrd.
static const uint16_t kSTA_M_BH
virtual void UnitSetup(size_t ind)
FIXME_docs.
static const uint16_t kRLCS_B_MPREM
static const uint16_t kRLDA_RW_M_HS
static const uint16_t kERR_DLATE
static const uint16_t kRLCS_B_DS
static const uint16_t kSTA_M_CO
int fLam
attn bit number (-1 of none)
Definition: Rw11Cntl.hpp:110
uint32_t fTraceLevel
trace level; 0=off;1=cntl
Definition: Rw11Cntl.hpp:114
RlinkCommandList fPrimClist
clist for attn primary info
Definition: Rw11Cntl.hpp:115
uint16_t Base() const
FIXME_docs.
Definition: Rw11Cntl.ipp:88
Rstats fStats
statistics
Definition: Rw11Cntl.hpp:116
Rw11Probe fProbe
controller probe context
Definition: Rw11Cntl.hpp:113
Rw11Cpu & Cpu() const
FIXME_docs.
Definition: Rw11Cntl.ipp:32
void ConfigCntl(const std::string &name, uint16_t base, int lam, uint16_t probeoff, bool probeint, bool proberem)
FIXME_docs.
Definition: Rw11Cntl.cpp:156
bool fStarted
true if Start() called
Definition: Rw11Cntl.hpp:112
bool fEnable
enable flag
Definition: Rw11Cntl.hpp:111
RlinkServer & Server() const
FIXME_docs.
Definition: Rw11Cntl.ipp:48
const std::string & Name() const
FIXME_docs.
Definition: Rw11Cntl.ipp:80
RlogFile & LogFile() const
FIXME_docs.
Definition: Rw11Cntl.ipp:64
virtual void UnitSetupAll()
FIXME_docs.
Definition: Rw11Cntl.cpp:113
uint16_t fBase
controller base address
Definition: Rw11Cntl.hpp:109
FIXME_docs.
Definition: Rw11Cpu.hpp:66
void AllIAddrMapInsert(const std::string &name, uint16_t ibaddr)
FIXME_docs.
Definition: Rw11Cpu.cpp:902
int AddWibr(RlinkCommandList &clist, uint16_t ibaddr, uint16_t data)
FIXME_docs.
Definition: Rw11Cpu.cpp:365
int AddRibr(RlinkCommandList &clist, uint16_t ibaddr)
FIXME_docs.
Definition: Rw11Cpu.cpp:354
static const uint16_t kCPAH_M_UBM22
ubmap+22bit
Definition: Rw11Cpu.hpp:228
void QueueDiskWrite(uint32_t addr, size_t size, uint16_t mode, uint32_t lba, Rw11UnitDisk *punit)
FIXME_docs.
void QueueDiskWriteCheck(uint32_t addr, size_t size, uint16_t mode, uint32_t lba, Rw11UnitDisk *punit)
FIXME_docs.
virtual void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
size_t WriteCheck(size_t nwdone)
FIXME_docs.
void QueueDiskRead(uint32_t addr, size_t size, uint16_t mode, uint32_t lba, Rw11UnitDisk *punit)
FIXME_docs.
bool IsActive() const
FIXME_docs.
Definition: Rw11Rdma.ipp:77
@ kStatusBusyLast
last chunk to come
Definition: Rw11Rdma.hpp:85
@ kStatusFailRdma
last rdma transfer failed
Definition: Rw11Rdma.hpp:86
@ kStatusBusy
more chunks to come
Definition: Rw11Rdma.hpp:84
bool WProt() const
FIXME_docs.
const std::string & Type() const
FIXME_docs.
uint32_t Chs2Lba(uint16_t cy, uint16_t hd, uint16_t se)
FIXME_docs.
size_t NSector() const
FIXME_docs.
size_t BlockSize() const
FIXME_docs.
uint32_t Nwrd2Nblk(uint32_t nwrd)
FIXME_docs.
void SetRlsta(uint16_t rlsta)
FIXME_docs.
bool HasVirt() const
FIXME_docs.
RosPrintfS< bool > RosPrintf(bool value, const char *form=0, int width=0, int prec=0)
Creates a print object for the formatted output of a bool value.
Definition: RosPrintf.ipp:38
Declaration of class ReventLoop.
Definition: ReventLoop.cpp:47
bool Found() const
FIXME_docs.
Definition: Rw11Probe.cpp:52