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

Subversion Repositories w11

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

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

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

powered by: WebSVN 2.1.0

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