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 31

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

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

powered by: WebSVN 2.1.0

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