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 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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