OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.61/] [tools/] [src/] [librw11/] [Rw11CntlRK11.cpp] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 20 wfjm
// $Id: Rw11CntlRK11.cpp 509 2013-04-21 20:46:20Z mueller $
2
//
3
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4
// Other credits: 
5
//   the boot code from the simh project and Copyright Robert M Supnik
6
// 
7
// This program is free software; you may redistribute and/or modify it under
8
// the terms of the GNU General Public License as published by the Free
9
// Software Foundation, either version 2, or at your option any later version.
10
//
11
// This program is distributed in the hope that it will be useful, but
12
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
13
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
// for complete details.
15
// 
16
// Revision History: 
17
// Date         Rev Version  Comment
18
// 2013-04-20   508   1.0    Initial version
19
// 2013-02-10   485   0.1    First draft
20
// ---------------------------------------------------------------------------
21
 
22
/*!
23
  \file
24
  \version $Id: Rw11CntlRK11.cpp 509 2013-04-21 20:46:20Z mueller $
25
  \brief   Implemenation of Rw11CntlRK11.
26
*/
27
 
28
#include "boost/bind.hpp"
29
#include "boost/foreach.hpp"
30
#define foreach_ BOOST_FOREACH
31
 
32
#include "librtools/RosFill.hpp"
33
#include "librtools/RosPrintBvi.hpp"
34
#include "librtools/RosPrintf.hpp"
35
#include "librtools/Rexception.hpp"
36
#include "librtools/RlogMsg.hpp"
37
 
38
#include "Rw11CntlRK11.hpp"
39
 
40
using namespace std;
41
 
42
/*!
43
  \class Retro::Rw11CntlRK11
44
  \brief FIXME_docs
45
*/
46
 
47
// all method definitions in namespace Retro
48
namespace Retro {
49
 
50
//------------------------------------------+-----------------------------------
51
// constants definitions
52
 
53
const uint16_t Rw11CntlRK11::kIbaddr;
54
const int      Rw11CntlRK11::kLam;
55
 
56
const uint16_t Rw11CntlRK11::kRKDS;
57
const uint16_t Rw11CntlRK11::kRKER;
58
const uint16_t Rw11CntlRK11::kRKCS;
59
const uint16_t Rw11CntlRK11::kRKWC;
60
const uint16_t Rw11CntlRK11::kRKBA;
61
const uint16_t Rw11CntlRK11::kRKDA;
62
const uint16_t Rw11CntlRK11::kRKMR;
63
 
64
const uint16_t Rw11CntlRK11::kProbeOff;
65
const bool     Rw11CntlRK11::kProbeInt;
66
const bool     Rw11CntlRK11::kProbeRem;
67
 
68
const uint16_t Rw11CntlRK11::kRKDS_M_ID;
69
const uint16_t Rw11CntlRK11::kRKDS_V_ID;
70
const uint16_t Rw11CntlRK11::kRKDS_B_ID;
71
const uint16_t Rw11CntlRK11::kRKDS_M_HDEN;
72
const uint16_t Rw11CntlRK11::kRKDS_M_DRU;
73
const uint16_t Rw11CntlRK11::kRKDS_M_SIN;
74
const uint16_t Rw11CntlRK11::kRKDS_M_SOK;
75
const uint16_t Rw11CntlRK11::kRKDS_M_DRY;
76
const uint16_t Rw11CntlRK11::kRKDS_M_ADRY;
77
const uint16_t Rw11CntlRK11::kRKDS_M_WPS;
78
const uint16_t Rw11CntlRK11::kRKDS_B_SC;
79
 
80
const uint16_t Rw11CntlRK11::kRKER_M_DRE;
81
const uint16_t Rw11CntlRK11::kRKER_M_OVR;
82
const uint16_t Rw11CntlRK11::kRKER_M_WLO;
83
const uint16_t Rw11CntlRK11::kRKER_M_PGE;
84
const uint16_t Rw11CntlRK11::kRKER_M_NXM;
85
const uint16_t Rw11CntlRK11::kRKER_M_NXD;
86
const uint16_t Rw11CntlRK11::kRKER_M_NXC;
87
const uint16_t Rw11CntlRK11::kRKER_M_NXS;
88
const uint16_t Rw11CntlRK11::kRKER_M_CSE;
89
const uint16_t Rw11CntlRK11::kRKER_M_WCE;
90
 
91
const uint16_t Rw11CntlRK11::kRKCS_M_MAINT;
92
const uint16_t Rw11CntlRK11::kRKCS_M_IBA;
93
const uint16_t Rw11CntlRK11::kRKCS_M_FMT;
94
const uint16_t Rw11CntlRK11::kRKCS_M_RWA;
95
const uint16_t Rw11CntlRK11::kRKCS_M_SSE;
96
const uint16_t Rw11CntlRK11::kRKCS_M_MEX;
97
const uint16_t Rw11CntlRK11::kRKCS_V_MEX;
98
const uint16_t Rw11CntlRK11::kRKCS_B_MEX;
99
const uint16_t Rw11CntlRK11::kRKCS_V_FUNC;
100
const uint16_t Rw11CntlRK11::kRKCS_B_FUNC;
101
const uint16_t Rw11CntlRK11::kRKCS_CRESET;
102
const uint16_t Rw11CntlRK11::kRKCS_WRITE;
103
const uint16_t Rw11CntlRK11::kRKCS_READ;
104
const uint16_t Rw11CntlRK11::kRKCS_WCHK;
105
const uint16_t Rw11CntlRK11::kRKCS_SEEK;
106
const uint16_t Rw11CntlRK11::kRKCS_RCHK;
107
const uint16_t Rw11CntlRK11::kRKCS_DRESET;
108
const uint16_t Rw11CntlRK11::kRKCS_WLOCK;
109
const uint16_t Rw11CntlRK11::kRKCS_M_GO;
110
 
111
const uint16_t Rw11CntlRK11::kRKDA_M_DRSEL;
112
const uint16_t Rw11CntlRK11::kRKDA_V_DRSEL;
113
const uint16_t Rw11CntlRK11::kRKDA_B_DRSEL;
114
const uint16_t Rw11CntlRK11::kRKDA_M_CYL;
115
const uint16_t Rw11CntlRK11::kRKDA_V_CYL;
116
const uint16_t Rw11CntlRK11::kRKDA_B_CYL;
117
const uint16_t Rw11CntlRK11::kRKDA_M_SUR;
118
const uint16_t Rw11CntlRK11::kRKDA_V_SUR;
119
const uint16_t Rw11CntlRK11::kRKDA_B_SUR;
120
const uint16_t Rw11CntlRK11::kRKDA_B_SC;
121
 
122
const uint16_t Rw11CntlRK11::kRKMR_M_RID;
123
const uint16_t Rw11CntlRK11::kRKMR_V_RID;
124
const uint16_t Rw11CntlRK11::kRKMR_M_CRDONE;
125
const uint16_t Rw11CntlRK11::kRKMR_M_SBCLR;
126
const uint16_t Rw11CntlRK11::kRKMR_M_CRESET;
127
const uint16_t Rw11CntlRK11::kRKMR_M_FDONE;
128
 
129
//------------------------------------------+-----------------------------------
130
//! Default constructor
131
 
132
Rw11CntlRK11::Rw11CntlRK11()
133
  : Rw11CntlBase<Rw11UnitRK11,8>("rk11"),
134
    fPC_rkwc(0),
135
    fPC_rkba(0),
136
    fPC_rkda(0),
137
    fPC_rkmr(0),
138
    fPC_rkcs(0),
139
    fRd_busy(false),
140
    fRd_rkcs(0),
141
    fRd_rkda(0),
142
    fRd_addr(0),
143
    fRd_lba(0),
144
    fRd_nwrd(0),
145
    fRd_ovr(false)
146
{
147
  // must here because Unit have a back-pointer (not available at Rw11CntlBase)
148
  for (size_t i=0; i<NUnit(); i++) {
149
    fspUnit[i].reset(new Rw11UnitRK11(this, i));
150
  }
151
}
152
 
153
//------------------------------------------+-----------------------------------
154
//! Destructor
155
 
156
Rw11CntlRK11::~Rw11CntlRK11()
157
{}
158
 
159
//------------------------------------------+-----------------------------------
160
//! FIXME_docs
161
 
162
void Rw11CntlRK11::Config(const std::string& name, uint16_t base, int lam)
163
{
164
  ConfigCntl(name, base, lam, kProbeOff, kProbeInt, kProbeRem);
165
  return;
166
}
167
 
168
//------------------------------------------+-----------------------------------
169
//! FIXME_docs
170
 
171
void Rw11CntlRK11::Start()
172
{
173
  if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
174
    throw Rexception("Rw11CntlDL11::Start",
175
                     "Bad state: started, no lam, not enable, not found");
176
 
177
  // setup primary info clist
178
  fPrimClist.Clear();
179
  Cpu().AddIbrb(fPrimClist, fBase);
180
  fPC_rkwc = Cpu().AddRibr(fPrimClist, fBase+kRKWC);
181
  fPC_rkba = Cpu().AddRibr(fPrimClist, fBase+kRKBA);
182
  fPC_rkda = Cpu().AddRibr(fPrimClist, fBase+kRKDA);
183
  fPC_rkmr = Cpu().AddRibr(fPrimClist, fBase+kRKMR); // read to monitor CRDONE
184
  fPC_rkcs = Cpu().AddRibr(fPrimClist, fBase+kRKCS);
185
 
186
  // add attn handler
187
  Server().AddAttnHandler(boost::bind(&Rw11CntlRK11::AttnHandler, this, _1),
188
                          uint16_t(1)<<fLam, (void*)this);
189
 
190
  fStarted = true;
191
  return;
192
}
193
 
194
//------------------------------------------+-----------------------------------
195
//! FIXME_docs
196
 
197
void Rw11CntlRK11::UnitSetup(size_t ind)
198
{
199
  Rw11UnitRK11& unit = *fspUnit[ind];
200
  Rw11Cpu& cpu  = Cpu();
201
  RlinkCommandList clist;
202
 
203
  uint16_t rkds = ind<<kRKDS_V_ID;
204
  if (unit.Virt()) {                        // file attached
205
    rkds |= kRKDS_M_HDEN;                   // always high density
206
    rkds |= kRKDS_M_SOK;                    // always sector counter OK ?FIXME?
207
    rkds |= kRKDS_M_DRY;                    // drive available
208
    rkds |= kRKDS_M_ADRY;                   // access available
209
    if (unit.WProt())                       // in case write protected
210
      rkds |= kRKDS_M_WPS;
211
  }
212
  unit.SetRkds(rkds);
213
  cpu.AddIbrb(clist, fBase);
214
  cpu.AddWibr(clist, fBase+kRKDS, rkds);
215
  Server().Exec(clist);
216
 
217
  return;
218
}
219
 
220
//------------------------------------------+-----------------------------------
221
//! FIXME_docs
222
 
223
bool Rw11CntlRK11::BootCode(size_t unit, std::vector<uint16_t>& code,
224
                            uint16_t& aload, uint16_t& astart)
225
{
226
  uint16_t kBOOT_START = 02000;
227
  uint16_t bootcode[] = { // rk05 boot loader - from simh pdp11_rk.c 
228
    0042113,                   //  "KD"
229
    0012706, kBOOT_START,      //  MOV #boot_start, SP
230
    0012700, uint16_t(unit),   //  MOV #unit, R0        ; unit number
231
    0010003,                   // #  MOV R0, R3
232
    0000303,                   // #  SWAB R3
233
    0006303,                   // #  ASL R3
234
    0006303,                   // #  ASL R3
235
    0006303,                   // #  ASL R3
236
    0006303,                   // #  ASL R3
237
    0006303,                   // #  ASL R3
238
    0012701, 0177412,          // #  MOV #RKDA, R1        ; rkda
239
    0010311,                   // #  MOV R3, (R1)         ; load da
240
    0005041,                   // #  CLR -(R1)            ; clear ba
241
    0012741, 0177000,          // #  MOV #-256.*2, -(R1)  ; load wc
242
    0012741, 0000005,          // #  MOV #READ+GO, -(R1)  ; read & go
243
    0005002,                   // #  CLR R2
244
    0005003,                   // #  CLR R3
245
    0012704, uint16_t(kBOOT_START+020),  // #  MOV #START+20, R4
246
    0005005,                   // #  CLR R5
247
    0105711,                   // #  TSTB (R1)
248
    0100376,                   // #  BPL .-4
249
    0105011,                   // #  CLRB (R1)
250
    0005007                    // #  CLR PC     (5007)
251
  };
252
 
253
  code.clear();
254
  foreach_ (uint16_t& w, bootcode) code.push_back(w);
255
  aload  = kBOOT_START;
256
  astart = kBOOT_START+2;
257
  return true;
258
}
259
 
260
//------------------------------------------+-----------------------------------
261
//! FIXME_docs
262
 
263
void Rw11CntlRK11::Dump(std::ostream& os, int ind, const char* text) const
264
{
265
  RosFill bl(ind);
266
  os << bl << (text?text:"--") << "Rw11CntlRK11 @ " << this << endl;
267
  os << bl << "  fPC_rkwc:        " << fPC_rkwc << endl;
268
  os << bl << "  fPC_rkba:        " << fPC_rkba << endl;
269
  os << bl << "  fPC_rkda:        " << fPC_rkda << endl;
270
  os << bl << "  fPC_rkmr:        " << fPC_rkmr << endl;
271
  os << bl << "  fPC_rkcs:        " << fPC_rkcs << endl;
272
  os << bl << "  fRd_busy:        " << fRd_busy << endl;
273
  os << bl << "  fRd_rkcs:        " << fRd_rkcs << endl;
274
  os << bl << "  fRd_rkda:        " << fRd_rkda << endl;
275
  os << bl << "  fRd_addr:        " << fRd_addr << endl;
276
  os << bl << "  fRd_lba:         " << fRd_lba  << endl;
277
  os << bl << "  fRd_nwrd:        " << fRd_nwrd << endl;
278
  os << bl << "  fRd_ovr:         " << fRd_ovr  << endl;
279
 
280
  Rw11CntlBase<Rw11UnitRK11,8>::Dump(os, ind, " ^");
281
  return;
282
}
283
 
284
//------------------------------------------+-----------------------------------
285
//! FIXME_docs
286
 
287
int Rw11CntlRK11::AttnHandler(const RlinkServer::AttnArgs& args)
288
{
289
  RlinkCommandList* pclist;
290
  size_t off;
291
 
292
  GetPrimInfo(args, pclist, off);
293
 
294
  uint16_t rkwc = (*pclist)[off+fPC_rkwc].Data();
295
  uint16_t rkba = (*pclist)[off+fPC_rkba].Data();
296
  uint16_t rkda = (*pclist)[off+fPC_rkda].Data();
297
  //uint16_t rkmr = (*pclist)[off+fPC_rkmr].Data();
298
  uint16_t rkcs = (*pclist)[off+fPC_rkcs].Data();
299
 
300
  uint16_t se   =  rkda                 & kRKDA_B_SC;
301
  uint16_t hd   = (rkda>>kRKDA_V_SUR)   & kRKDA_B_SUR;
302
  uint16_t cy   = (rkda>>kRKDA_V_CYL)   & kRKDA_B_CYL;
303
  uint16_t dr   = (rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
304
 
305
  bool go       =  rkcs & kRKCS_M_GO;
306
  uint16_t fu   = (rkcs>>kRKCS_V_FUNC)  & kRKCS_B_FUNC;
307
  uint16_t mex  = (rkcs>>kRKCS_V_MEX)   & kRKCS_B_MEX;
308
  uint32_t addr = uint32_t(mex)<<16 | uint32_t(rkba);
309
 
310
  // Note: apparently are operands first promoted to 32 bit -> mask after ~ !
311
  uint32_t nwrd = (~uint32_t(rkwc)&0xffff) + 1; // transfer size in words
312
 
313
  if (!go) {
314
    RlogMsg lmsg(LogFile());
315
    lmsg << "-I RK11 cs=" << RosPrintBvi(rkcs,8)
316
         << "  go=0, spurious attn, dropped";
317
    return 0;
318
  }
319
 
320
  // all 8 units are always available, but check anyway
321
  if (dr > NUnit())
322
    throw Rexception("Rw11CntlRK11::AttnHandler","Bad state: dr > NUnit()");
323
 
324
  Rw11UnitRK11& unit = *fspUnit[dr];
325
  Rw11Cpu& cpu = Cpu();
326
  RlinkCommandList clist;
327
 
328
  uint32_t lba  = unit.Chs2Lba(cy,hd,se);
329
  uint32_t nblk = (2*nwrd+unit.BlockSize()-1)/unit.BlockSize();
330
 
331
  uint16_t rker = 0;
332
  uint16_t rkds = unit.Rkds();
333
 
334
  if (fTraceLevel>0) {
335
    RlogMsg lmsg(LogFile());
336
    lmsg << "-I RK11 cs=" << RosPrintBvi(rkcs,8)
337
         << " da=" << RosPrintBvi(rkda,8)
338
         << " ad=" << RosPrintBvi(addr,8,18)
339
         << " fu=" << fu
340
         << " dchs=" << dr
341
         << "," << RosPrintf(cy,"d",3)
342
         << "," << hd
343
         << "," << RosPrintf(se,"d",2)
344
         << " lba,nw=" << RosPrintf(lba,"d",4)
345
         << "," << RosPrintf(nwrd,"d",5);
346
  }
347
 
348
  // check for general abort conditions
349
  if (fu != kRKCS_CRESET &&                 // function not control reset
350
      (!unit.Virt())) {                     //   and drive not attached
351
    rker = kRKER_M_NXD;                     //   --> abort with NXD error
352
 
353
  } else if (fu != kRKCS_WRITE &&           // function neither write
354
             fu != kRKCS_READ &&            //   nor read
355
             (rkcs & (kRKCS_M_FMT|kRKCS_M_RWA))) { // and FMT or RWA set 
356
    rker = kRKER_M_PGE;                     //   --> abort with PGE error
357
  } else if (rkcs & kRKCS_M_RWA) {          // RWA not supported
358
    rker = kRKER_M_DRE;                     //   --> abort with DRE error
359
  }
360
 
361
  if (rker) {
362
    cpu.AddWibr(clist, fBase+kRKER, rker);
363
    if (fu == kRKCS_SEEK || fu == kRKCS_DRESET)
364
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
365
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
366
    LogRker(rker);
367
    Server().Exec(clist);
368
    return 0;
369
  }
370
 
371
  // check for overrun (read/write beyond cylinder 203
372
  // if found, truncate request length
373
  bool ovr = lba + nblk > unit.NBlock();
374
  if (ovr) nwrd = (unit.NBlock()-lba) * (unit.BlockSize()/2);
375
  bool queue = false;
376
 
377
  // now handle the functions
378
  if (fu == kRKCS_CRESET) {                 // Control reset -----------------
379
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
380
    fRd_busy  = false;
381
 
382
  } else if (fu == kRKCS_WRITE) {           // Write -------------------------
383
                                            //   Note: WRITE+FMT is just WRITE
384
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
385
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
386
    if (unit.WProt())           rker |= kRKER_M_WLO;
387
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // not yet supported FIXME
388
    queue = true;
389
 
390
  } else if (fu == kRKCS_READ) {            // Read --------------------------
391
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
392
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
393
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // not yet supported FIXME
394
    queue = true;
395
 
396
  } else if (fu == kRKCS_WCHK) {            // Write Check -------------------
397
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
398
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
399
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // not yet supported FIXME
400
    queue = true;
401
 
402
  } else if (fu == kRKCS_SEEK) {            // Seek --------------------------
403
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
404
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
405
    if (rker) {
406
      cpu.AddWibr(clist, fBase+kRKER, rker);
407
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
408
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
409
      LogRker(rker);
410
    } else {
411
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
412
      rkds &= ~kRKDS_B_SC;                  // replace current sector number
413
      rkds |= se;
414
      unit.SetRkds(rkds);
415
      cpu.AddWibr(clist, fBase+kRKDS, rkds);
416
      cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr); // issue seek done
417
    }
418
 
419
  } else if (fu == kRKCS_RCHK) {            // Read Check --------------------
420
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
421
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
422
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // not yet supported FIXME
423
    queue = true;
424
 
425
  } else if (fu == kRKCS_DRESET) {          // Drive Reset -------------------
426
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
427
    cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr);   // issue seek done
428
 
429
  } else if (fu == kRKCS_WLOCK) {           // Write Lock --------------------
430
    rkds |= kRKDS_M_WPS;                    // set RKDS write protect flag
431
    unit.SetRkds(rkds);
432
    unit.SetWProt(true);
433
    cpu.AddWibr(clist, fBase+kRKDS, rkds);
434
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
435
  }
436
 
437
  if (queue) {                             // to be handled in RdmaHandlder
438
    if (rker) {                              // abort on case of errors
439
      cpu.AddWibr(clist, fBase+kRKER, rker);
440
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
441
      LogRker(rker);
442
    } else {                                 // or queue action 
443
      fRd_busy  = true;
444
      fRd_rkcs  = rkcs;
445
      fRd_rkda  = rkda;
446
      fRd_addr  = addr;
447
      fRd_lba   = lba;
448
      fRd_nwrd  = nwrd;
449
      fRd_ovr   = ovr;
450
      Server().QueueAction(boost::bind(&Rw11CntlRK11::RdmaHandler, this));
451
    }
452
 
453
  } else {                                  // handled here
454
    Server().Exec(clist);
455
  }
456
 
457
  return 0;
458
}
459
 
460
//------------------------------------------+-----------------------------------
461
//! FIXME_docs
462
 
463
int Rw11CntlRK11::RdmaHandler()
464
{
465
  uint16_t rker = 0;
466
  uint16_t fu   = (fRd_rkcs>>kRKCS_V_FUNC)  & kRKCS_B_FUNC;
467
  uint16_t dr   = (fRd_rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
468
  Rw11UnitRK11& unit = *fspUnit[dr];
469
  Rw11Cpu& cpu = Cpu();
470
 
471
  uint8_t buf[512];
472
 
473
  if (fu == kRKCS_WRITE) {                  // Write -------------------------
474
                                            //   Note: WRITE+FMT is like WRITE
475
    RlinkCommandList clist;
476
    size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
477
    cpu.AddRMem(clist, fRd_addr, (uint16_t*) buf, bsize,
478
                Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
479
    Server().Exec(clist);
480
    // FIXME_code: handle rdma I/O error
481
    RerrMsg emsg;
482
    bool rc = unit.VirtWrite(fRd_lba, 1, buf, emsg);
483
    if (!rc) {
484
      RlogMsg lmsg(LogFile());
485
      lmsg << emsg;
486
      rker |= kRKER_M_CSE;              // forward disk I/O error
487
    }
488
    if (rker == 0) {
489
      fRd_nwrd -= bsize;
490
      fRd_addr += 2*bsize;
491
      fRd_lba  += 1;
492
    }
493
    if (rker==0 && fRd_nwrd>0)            // not error and not yet done
494
      return 1;                           // requeue
495
 
496
  } else if (fu == kRKCS_READ) {
497
    if ((fRd_rkcs&kRKCS_M_FMT) == 0) {      // Read --------------------------
498
      RerrMsg emsg;
499
      bool rc = unit.VirtRead(fRd_lba, 1, buf, emsg);
500
      if (!rc) {
501
        RlogMsg lmsg(LogFile());
502
        lmsg << emsg;
503
        rker |= kRKER_M_CSE;              // forward disk I/O error
504
      }
505
 
506
      if (rker == 0) {
507
        RlinkCommandList clist;
508
        size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
509
        cpu.AddWMem(clist, fRd_addr, (uint16_t*) buf, bsize,
510
                    Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
511
        Server().Exec(clist);
512
        // FIXME_code: handle rdma I/O error
513
        fRd_nwrd -= bsize;
514
        fRd_addr += 2*bsize;
515
        fRd_lba  += 1;
516
      }
517
      if (rker==0 && fRd_nwrd>0)            // not error and not yet done
518
        return 1;                           // requeue
519
 
520
    } else {                                // Read Format -------------------
521
      uint16_t cy = fRd_lba / (unit.NHead()*unit.NSector());
522
      uint16_t da = cy<<kRKDA_V_CYL;
523
      RlinkCommandList clist;
524
      cpu.AddWMem(clist, fRd_addr, &da, 1,
525
                  Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
526
      Server().Exec(clist);
527
      // FIXME_code: handle rdma I/O error
528
      fRd_nwrd -= 1;
529
      fRd_addr += 2;
530
      fRd_lba  += 1;
531
      if (rker==0 && fRd_nwrd>0)            // not error and not yet done
532
        return 1;                           // requeue
533
    }
534
 
535
  } else if (fu == kRKCS_WCHK) {            // Write Check -------------------
536
    uint16_t bufmem[256];
537
    RlinkCommandList clist;
538
    size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
539
    cpu.AddRMem(clist, fRd_addr, bufmem, bsize,
540
                Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
541
    Server().Exec(clist);
542
    // FIXME_code: handle rdma I/O error
543
    RerrMsg emsg;
544
    bool rc = unit.VirtRead(fRd_lba, 1, buf, emsg);
545
    if (!rc) {
546
      RlogMsg lmsg(LogFile());
547
      lmsg << emsg;
548
      rker |= kRKER_M_CSE;              // forward disk I/O error
549
    }
550
    if (rker == 0) {
551
      uint16_t* pmem = bufmem;
552
      uint16_t* pdsk = (uint16_t*) &buf;
553
      for (size_t i=0; i<bsize; i++) {
554
        if (*pmem++ != *pdsk++) rker |= kRKER_M_WCE;
555
      }
556
      fRd_nwrd -= bsize;
557
      fRd_addr += 2*bsize;
558
      fRd_lba  += 1;
559
    }
560
    // determine abort criterion
561
    bool stop = (rker & ~kRKER_M_WCE) != 0 ||
562
                ((rker & kRKER_M_WCE) && (fRd_rkcs & kRKCS_M_SSE));
563
    if (!stop && fRd_nwrd>0)                // not error and not yet done
564
      return 1;                             // requeue
565
 
566
  } else if (fu == kRKCS_RCHK) {            // Read Check --------------------
567
    // Note: no DMA transfer done; done here to keep logic similar to read
568
    size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
569
    fRd_nwrd -= bsize;
570
    fRd_addr += 2*bsize;
571
    fRd_lba  += 1;
572
    if (rker==0 && fRd_nwrd>0)            // not error and not yet done
573
      return 1;                           // requeue
574
 
575
  } else {
576
    throw Rexception("Rw11CntlDL11::RdmaHandler",
577
                     "Bad state: bad function code");
578
  }
579
 
580
  // common handling for dma transfer completion
581
  if (fRd_ovr) rker |= kRKER_M_OVR;
582
 
583
  RlinkCommandList clist;
584
 
585
  uint16_t ba   = fRd_addr & 0177776;       // get lower 16 bits
586
  uint16_t mex  = (fRd_addr>>16) & 03;      // get upper  2 bits
587
  uint16_t cs   = (fRd_rkcs & ~kRKCS_M_MEX) | (mex << kRKCS_V_MEX);
588
  uint16_t se;
589
  uint16_t hd;
590
  uint16_t cy;
591
  unit.Lba2Chs(fRd_lba, cy,hd,se);
592
  uint16_t da   = (fRd_rkda & kRKDA_M_DRSEL) | (cy<<kRKDA_V_CYL) |
593
                  (hd<<kRKDA_V_SUR) | se;
594
 
595
  cpu.AddIbrb(clist, fBase);
596
  if (rker) {
597
    cpu.AddWibr(clist, fBase+kRKER, rker);
598
    LogRker(rker);
599
  }
600
  cpu.AddWibr(clist, fBase+kRKWC, uint16_t((-fRd_nwrd)&0177777));
601
  cpu.AddWibr(clist, fBase+kRKBA, ba);
602
  cpu.AddWibr(clist, fBase+kRKDA, da);
603
  if (cs != fRd_rkcs)
604
    cpu.AddWibr(clist, fBase+kRKCS, cs);
605
  cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
606
 
607
  Server().Exec(clist);
608
 
609
  fRd_busy  = false;
610
 
611
  return 0;
612
}
613
 
614
//------------------------------------------+-----------------------------------
615
//! FIXME_docs
616
 
617
void Rw11CntlRK11::LogRker(uint16_t rker)
618
{
619
  RlogMsg lmsg(LogFile());
620
  lmsg << "-E RK11 er=" << RosPrintBvi(rker,8) << "  ERROR ABORT";
621
}
622
 
623
} // end namespace Retro

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.