30 static const unsigned MAX_DEV = 8;
32 static const byte REG_OWN_ID = 0x00;
33 static const byte REG_CONTROL = 0x01;
34 static const byte REG_TIMEO = 0x02;
35 static const byte REG_TSECS = 0x03;
36 static const byte REG_THEADS = 0x04;
37 static const byte REG_TCYL_HI = 0x05;
38 static const byte REG_TCYL_LO = 0x06;
39 static const byte REG_ADDR_HI = 0x07;
40 static const byte REG_ADDR_2 = 0x08;
41 static const byte REG_ADDR_3 = 0x09;
42 static const byte REG_ADDR_LO = 0x0a;
43 static const byte REG_SECNO = 0x0b;
44 static const byte REG_HEADNO = 0x0c;
45 static const byte REG_CYLNO_HI = 0x0d;
46 static const byte REG_CYLNO_LO = 0x0e;
47 static const byte REG_TLUN = 0x0f;
48 static const byte REG_CMD_PHASE = 0x10;
49 static const byte REG_SYN = 0x11;
50 static const byte REG_TCH = 0x12;
51 static const byte REG_TCM = 0x13;
52 static const byte REG_TCL = 0x14;
53 static const byte REG_DST_ID = 0x15;
54 static const byte REG_SRC_ID = 0x16;
55 static const byte REG_SCSI_STATUS = 0x17;
56 static const byte REG_CMD = 0x18;
57 static const byte REG_DATA = 0x19;
58 static const byte REG_QUEUE_TAG = 0x1a;
59 static const byte REG_AUX_STATUS = 0x1f;
61 static const byte REG_CDBSIZE = 0x00;
62 static const byte REG_CDB1 = 0x03;
63 static const byte REG_CDB2 = 0x04;
64 static const byte REG_CDB3 = 0x05;
65 static const byte REG_CDB4 = 0x06;
66 static const byte REG_CDB5 = 0x07;
67 static const byte REG_CDB6 = 0x08;
68 static const byte REG_CDB7 = 0x09;
69 static const byte REG_CDB8 = 0x0a;
70 static const byte REG_CDB9 = 0x0b;
71 static const byte REG_CDB10 = 0x0c;
72 static const byte REG_CDB11 = 0x0d;
73 static const byte REG_CDB12 = 0x0e;
75 static const byte OWN_EAF = 0x08;
78 static const byte SS_RESET = 0x00;
79 static const byte SS_RESET_ADV = 0x01;
80 static const byte SS_XFER_END = 0x16;
81 static const byte SS_SEL_TIMEOUT = 0x42;
82 static const byte SS_DISCONNECT = 0x85;
85 static const byte AS_DBR = 0x01;
86 static const byte AS_CIP = 0x10;
87 static const byte AS_BSY = 0x20;
88 static const byte AS_LCI = 0x40;
89 static const byte AS_INT = 0x80;
113 unsigned id = t->getAttributeAsInt(
"id");
116 "Invalid SCSI id: " <<
id <<
117 " (should be 0.." << MAX_DEV - 1 <<
')');
121 "Duplicate SCSI id: " <<
id);
125 const std::string& type = typeElem.
getData();
126 if (type ==
"SCSIHD") {
127 dev[id] = make_unique<SCSIHD>(conf, buffer.
data(),
130 }
else if (type ==
"SCSILS120") {
131 dev[id] = make_unique<SCSILS120>(conf, buffer.
data(),
139 for (
unsigned i = 0; i < MAX_DEV; ++i) {
141 dev[i] = make_unique<DummySCSIDevice>();
157 void WD33C93::disconnect()
160 assert(targetId < MAX_DEV);
161 dev[targetId]->disconnect();
162 if (regs[REG_SCSI_STATUS] != SS_XFER_END) {
163 regs[REG_SCSI_STATUS] = SS_DISCONNECT;
165 regs[REG_AUX_STATUS] = AS_INT;
173 void WD33C93::execCmd(
byte value)
175 if (regs[REG_AUX_STATUS] & AS_CIP) {
180 regs[REG_CMD] = value;
185 PRT_DEBUG(
"wd33c93 [CMD] Reset controller");
186 memset(regs + 1, 0, 0x1a);
189 regs[REG_SCSI_STATUS] =
190 (regs[REG_OWN_ID] & OWN_EAF) ? SS_RESET_ADV : SS_RESET;
206 PRT_DEBUG(
"wd33c93 [CMD] Select (ATN " << atn <<
')');
207 targetId = regs[REG_DST_ID] & 7;
208 regs[REG_SCSI_STATUS] = SS_SEL_TIMEOUT;
210 regs[REG_AUX_STATUS] = AS_INT;
217 PRT_DEBUG(
"wd33c93 [CMD] Select and transfer (ATN " << atn <<
')');
218 targetId = regs[REG_DST_ID] & 7;
220 if (!devBusy && targetId < MAX_DEV &&
221 dev[targetId]->isSelected()) {
223 dev[targetId]->msgOut(regs[REG_TLUN] | 0x80);
226 counter = dev[targetId]->executeCmd(
227 ®s[REG_CDB1], phase, blockCounter);
232 regs[REG_TLUN] = dev[targetId]->getStatusCode();
233 dev[targetId]->msgIn();
234 regs[REG_SCSI_STATUS] = SS_XFER_END;
239 regs[REG_AUX_STATUS] = AS_CIP | AS_BSY;
245 regs[REG_AUX_STATUS] = AS_CIP | AS_BSY | AS_DBR;
250 PRT_DEBUG(
"wd33c93 timeout on target " <<
int(targetId));
252 regs[REG_SCSI_STATUS] = SS_SEL_TIMEOUT;
253 regs[REG_AUX_STATUS] = AS_INT;
259 PRT_DEBUG(
"wd33c93 [CMD] unsupport command " <<
int(value));
267 latch = value & 0x1f;
277 regs[REG_OWN_ID] = value;
279 PRT_DEBUG(
"wd33c93 myid = " <<
int(myId));
283 tc = (tc & 0x00ffff) + (value << 16);
287 tc = (tc & 0xff00ff) + (value << 8);
291 tc = (tc & 0xffff00) + (value << 0);
295 PRT_DEBUG(
"wd33c93 CMD_PHASE = " <<
int(value));
296 regs[REG_CMD_PHASE] = value;
304 regs[REG_DATA] = value;
306 buffer[bufIdx++] = value;
308 if (--counter == 0) {
309 counter = dev[targetId]->dataOut(blockCounter);
314 regs[REG_TLUN] = dev[targetId]->getStatusCode();
315 dev[targetId]->msgIn();
316 regs[REG_SCSI_STATUS] = SS_XFER_END;
326 if (latch <= REG_SRC_ID) {
331 latch = (latch + 1) & 0x1f;
336 byte rv = regs[REG_AUX_STATUS];
339 counter = dev[targetId]->executingCmd(phase, blockCounter);
343 regs[REG_TLUN] = dev[targetId]->getStatusCode();
344 dev[targetId]->msgIn();
345 regs[REG_SCSI_STATUS] = SS_XFER_END;
353 regs[REG_AUX_STATUS] |= AS_DBR;
368 case REG_SCSI_STATUS:
369 rv = regs[REG_SCSI_STATUS];
371 if (rv != SS_XFER_END) {
372 regs[REG_AUX_STATUS] &= ~AS_INT;
374 regs[REG_SCSI_STATUS] = SS_DISCONNECT;
375 regs[REG_AUX_STATUS] = AS_INT;
380 return regs[REG_CMD];
384 rv = buffer[bufIdx++];
387 if (--counter == 0) {
388 if (blockCounter > 0) {
389 counter = dev[targetId]->dataIn(blockCounter);
395 regs[REG_TLUN] = dev[targetId]->getStatusCode();
396 dev[targetId]->msgIn();
397 regs[REG_SCSI_STATUS] = SS_XFER_END;
406 rv = (tc >> 16) & 0xff;
410 rv = (tc >> 8) & 0xff;
414 rv = (tc >> 0) & 0xff;
426 latch = (latch + 1) & 0x1f;
432 return regs[REG_AUX_STATUS];
439 return (tc >> 16) & 0xff;
441 return (tc >> 8) & 0xff;
443 return (tc >> 0) & 0xff;
454 memset(regs, 0, 0x1b);
455 memset(regs + 0x1b, 0xff, 4);
456 regs[REG_AUX_STATUS] = AS_INT;
463 for (
unsigned i = 0; i < MAX_DEV; ++i) {
486 template<
typename Archive>
489 ar.serialize_blob(
"buffer", buffer.
data(), buffer.
size());
490 char tag[8] = {
'd',
'e',
'v',
'i',
'c',
'e',
'X', 0 };
491 for (
unsigned i = 0; i < MAX_DEV; ++i) {
492 tag[6] = char(
'0' + i);
493 ar.serializePolymorphic(tag, *dev[i]);
495 ar.serialize(
"bufIdx", bufIdx);
496 ar.serialize(
"counter", counter);
497 ar.serialize(
"blockCounter", blockCounter);
498 ar.serialize(
"tc", tc);
499 ar.serialize(
"phase", phase);
500 ar.serialize(
"myId", myId);
501 ar.serialize(
"targetId", targetId);
502 ar.serialize_blob(
"registers", regs,
sizeof(regs));
503 ar.serialize(
"latch", latch);
504 ar.serialize(
"devBusy", devBusy);