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

Subversion Repositories w11

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

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

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

powered by: WebSVN 2.1.0

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