w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
Rw11VirtDiskRam.cpp
Go to the documentation of this file.
1// $Id: Rw11VirtDiskRam.cpp 1186 2019-07-12 17:49:59Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2018-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4//
5// Revision History:
6// Date Rev Version Comment
7// 2019-05-01 1143 1.1 add noboot option
8// 2018-10-28 1063 1.0 Initial version
9// 2018-10-27 1061 0.1 First draft
10// ---------------------------------------------------------------------------
11
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19#include <unistd.h>
20
21#include <sstream>
22
23#include "librtools/RosFill.hpp"
25
26#include "Rw11VirtDiskRam.hpp"
27
28using namespace std;
29
35// all method definitions in namespace Retro
36namespace Retro {
37
38//------------------------------------------+-----------------------------------
40
42 : Rw11VirtDisk(punit),
43 fNoBoot(false),
44 fPatTyp(kPatZero),
45 fBlkMap()
46{
47 fStats.Define(kStatNVDReadRam, "NVDReadRam", "ram: blocks read from ram");
48 fStats.Define(kStatNVDWriteOver, "NVDWriteOver", "ram: blocks overwritten");
49}
50
51//------------------------------------------+-----------------------------------
53
55{}
56
57//------------------------------------------+-----------------------------------
59
60bool Rw11VirtDiskRam::Open(const std::string& url, RerrMsg& emsg)
61{
62 return Open(url, "file", emsg);
63}
64
65//------------------------------------------+-----------------------------------
67
68bool Rw11VirtDiskRam::Open(const std::string& url, const std::string& scheme,
69 RerrMsg& emsg)
70{
71 if (!fUrl.Set(url, "|wpro|noboot|pat=|", scheme, emsg)) return false;
72 fWProt = fUrl.FindOpt("wpro");
73 fNoBoot = fUrl.FindOpt("noboot");
74
75 string pat;
77 if (fUrl.FindOpt("pat", pat)) {
78 if (pat == "zero") {
80 } else if (pat == "ones") {
82 } else if (pat == "dead") {
84 } else if (pat == "test") {
86 } else {
87 emsg.Init("Rw11VirtDiskRam::Open()",
88 string("invalid pattern name '") + pat + "'");
89 return false;
90 }
91 }
92
93 return true;
94}
95
96//------------------------------------------+-----------------------------------
98
99bool Rw11VirtDiskRam::Read(size_t lba, size_t nblk, uint8_t* data,
100 RerrMsg& /*emsg*/)
101{
103 fStats.Inc(kStatNVDReadBlk, double(nblk));
104
105 for (size_t i=0; i<nblk; i++) {
106 auto it = fBlkMap.find(lba+i);
107 if (it == fBlkMap.end()) {
108 ReadPattern(lba+i, data+i*fBlkSize);
109 } else {
111 (it->second).Read(data+i*fBlkSize);
112 }
113 }
114
115 return true;
116}
117
118//------------------------------------------+-----------------------------------
120
121bool Rw11VirtDiskRam::Write(size_t lba, size_t nblk, const uint8_t* data,
122 RerrMsg& /*emsg*/)
123{
125 fStats.Inc(kStatNVDWriteBlk, double(nblk));
126
127 for (size_t i=0; i<nblk; i++) {
128 auto it = fBlkMap.find(lba+i);
129 if (it == fBlkMap.end()) {
130 auto rc = fBlkMap.emplace(lba+i, Rw11VirtDiskBuffer(fBlkSize));
131 it = rc.first;
132 } else {
133 fStats.Inc(kStatNVDWriteOver, double(nblk));
134 }
135
136 (it->second).Write(data+i*fBlkSize);
137 }
138
139 return true;
140}
141
142//------------------------------------------+-----------------------------------
144
145void Rw11VirtDiskRam::List(std::ostream& os) const
146{
147 if (fBlkMap.empty()) return;
148
149 uint32_t lbabeg = fBlkMap.begin()->first; // first lba
150 uint32_t nwrite = 0;
151 for (auto it=fBlkMap.begin(); it!=fBlkMap.end(); ) {
152 nwrite += (it->second).NWrite();
153 auto itnext = next(it);
154 if (itnext == fBlkMap.end() || itnext->first != (it->first)+1) {
155 os << RosPrintf(lbabeg,"d",8)
156 << " .. " << RosPrintf(it->first,"d",8)
157 << " : nb=" << RosPrintf(it->first-lbabeg+1,"d",8)
158 << " nw=" << RosPrintf(nwrite,"d",8) << endl;
159 if (itnext != fBlkMap.end()) lbabeg = itnext->first;
160 nwrite = 0;
161 }
162 it = itnext;
163 }
164 return;
165}
166
167//------------------------------------------+-----------------------------------
169
170void Rw11VirtDiskRam::Dump(std::ostream& os, int ind, const char* text,
171 int detail) const
172{
173 RosFill bl(ind);
174 os << bl << (text?text:"--") << "Rw11VirtDiskRam @ " << this << endl;
175
176 os << bl << " fNoBoot: " << fNoBoot << endl;
177 os << bl << " fPatTyp: " << fPatTyp << endl;
178 os << bl << " fBlkMap.size: " << fBlkMap.size() << endl;
179 Rw11VirtDisk::Dump(os, ind, " ^", detail);
180 return;
181}
182
183//------------------------------------------+-----------------------------------
185
186void Rw11VirtDiskRam::ReadPattern(size_t lba, uint8_t* data)
187{
188
189 if (lba == 0 && fNoBoot) { // block 0 with 'not bootable' msg
190 uint16_t bootcode[] = {
191 0012700, 0000026, // start: mov #text, r0
192 0105710, // 1$: tstb (r0)
193 0001406, // beq 3$
194 0105737, 0177564, // 2$: tstb @#to.csr
195 0100375, // bpl 2$
196 0112037, 0177566, // movb (r0)+,@#to.buf
197 0000770, // br 1$
198 0000000 // 3$: halt
199 // text: .ascii ....
200 };
201
202 uint16_t* pdata = reinterpret_cast<uint16_t*>(data);
203 for (uint16_t& o : bootcode) *pdata++ = o;
204
205 ostringstream boottext;
206 boottext << "\r\n";
207 boottext << "++======================================++\r\n";
208 boottext << "|| This is not a hardware bootable disk ||\r\n";
209 boottext << "++======================================++\r\n";
210 boottext << "\r\n";
211 boottext << "Virtual disk: CHS="
212 << fNCyl << "," << fNHead << "," << fNSect;
213 boottext << " blocks=" << fNBlock << "(" << fBlkSize << ")";
214 boottext << " name=" << fUrl.Path();
215 boottext << "\r\n";
216 boottext << "CPU WILL HALT\r\n";
217 boottext << "\r\n";
218
219 char* pchar = reinterpret_cast<char*>(pdata);
220 char* pend = reinterpret_cast<char*>(data+fBlkSize);
221 for (char& o : boottext.str()) { // append boot text
222 *pchar++ = o;
223 if (pchar >= pend) break; // ensure block isn't overrrun
224 }
225 while (pchar < pend) { *pchar++ = '\0'; } // zero fill rest
226 pend[-1] = '\0'; // ensure text 0 terminated
227
228 return;
229 }
230
231 uint16_t* p = reinterpret_cast<uint16_t*>(data);
232 uint16_t* pend = reinterpret_cast<uint16_t*>(data+fBlkSize);
233 size_t addr = lba*fBlkSize;
234
235 switch (fPatTyp) {
236 case kPatZero:
237 while (p < pend) { *p++ = 0x0000; }
238 break;
239 case kPatOnes:
240 while (p < pend) { *p++ = 0xffff; }
241 break;
242 case kPatDead:
243 while (p < pend) { *p++ = 0xdead; *p++ = 0xbeaf; }
244 break;
245 case kPatTest:
246 while(p < pend) {
247 *p++ = addr & 0xffff; // byte address, LSB
248 *p++ = (addr>>16) & 0xffff; // byte address, MSB
249 *p++ = lba / (fNSect*fNHead); // current cylinder
250 *p++ = (lba/fNSect) % fNHead; // current head
251 *p++ = lba % fNSect; // current sector
252 *p++ = fNCyl; // total number of cylinders
253 *p++ = fNHead; // total number of heads
254 *p++ = fNSect; // total number of sectors
255 addr += 16;
256 }
257 break;
258 default:
259 break;
260 }
261
262 return;
263}
264
265} // end namespace Retro
FIXME_docs.
Definition: RerrMsg.hpp:25
void Init(const std::string &meth, const std::string &text)
FIXME_docs.
Definition: RerrMsg.cpp:74
I/O appicator to generate fill characters.
Definition: RosFill.hpp:24
bool FindOpt(const std::string &name) const
FIXME_docs.
Definition: RparseUrl.cpp:196
bool Set(const std::string &url, const std::string &optlist, RerrMsg &emsg)
FIXME_docs.
Definition: RparseUrl.cpp:55
const std::string & Path() const
FIXME_docs.
Definition: RparseUrl.ipp:45
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
FIXME_docs.
Definition: Rw11Unit.hpp:39
virtual bool Read(size_t lba, size_t nblk, uint8_t *data, RerrMsg &emsg)
FIXME_docs.
virtual bool Open(const std::string &url, RerrMsg &emsg)
FIXME_docs.
virtual bool Write(size_t lba, size_t nblk, const uint8_t *data, RerrMsg &emsg)
FIXME_docs.
virtual void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
void ReadPattern(size_t lba, uint8_t *data)
FIXME_doc.
Rw11VirtDiskRam(Rw11Unit *punit)
Default constructor.
void List(std::ostream &os) const
FIXME_docs.
pattyp fPatTyp
pattern type
virtual void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
size_t fNBlock
disk size in blocks
size_t fBlkSize
block size in byte
RparseUrl fUrl
Definition: Rw11Virt.hpp:66
Rstats fStats
statistics
Definition: Rw11Virt.hpp:68
bool fWProt
write protected
Definition: Rw11Virt.hpp:67
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