|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // メインバス (LUNA)
9: //
10:
11: // IODevice
12: // +-- MainbusBaseDevice (InitMainbus() と FC アクセスを持つ)
13: // | +-- MainbusDevice (これがメインバス、システムに1つ)
14: // | | +-- Mainbus24Device (上位8ビットがテーブルで表せるメインバス)
15: // | | | | +-------------+
16: // | | | +--| LunaMainbus | (LUNA 共通部)
17: // | | | | +-------------+
18: // | | | | | +--------------+
19: // | | | | +--| Luna1Mainbus | (LUNA-I)
20: // | | | | | +--------------+
21: // | | | | | +----------------+
22: // | | | | +--| Luna88kMainbus | (LUNA-88K)
23: // | | | | +----------------+
24: // | | | |
25: // | | | +-- NewsMainbus
26: // | | | +-- Virt68kMainbus
27: // | | +-- X68kMainbus
28: // | +-- X68kIODevice
29: // +-- XPbusDevice
30:
31: #include "mainbus_luna.h"
32: #include "bt45x.h"
33: #include "busio.h"
34: #include "cmmu.h"
35: #include "config.h"
36: #include "crtc2.h"
37: #include "fuserom.h"
38: #include "interrupt.h"
39: #include "lance.h"
40: #include "lunafb.h"
41: #include "mainapp.h"
42: #include "mainram.h"
43: #include "mk48t02.h"
44: #include "msxdos.h"
45: #include "partialram.h"
46: #include "pio.h"
47: #include "prom.h"
48: #include "romemu_luna1.h"
49: #include "romemu_luna88k.h"
50: #include "sio.h"
51: #include "spc.h"
52: #include "subram.h"
53: #include "sysclk.h"
54: #include "sysctlr.h"
55: #include "tas.h"
56:
57: //
58: // LUNA 共通部
59: //
60:
61: // デバイスマップ用の識別子
62: enum {
63: NONE,
64: BUSERR,
65: PROM,
66: MK48,
67: PIO0,
68: PIO1,
69: SIO,
70: TAS,
71: SYSCLK,
72: SUBRAM,
73: MROM,
74: LUNAFB,
75: BT45x,
76: CRTC2,
77: SCSI,
78: LANCE,
79: FUSE,
80: SYSCTL,
81: CMMU,
82: };
83:
84: // コンストラクタ
85: LunaMainbus::LunaMainbus()
86: {
87: NEWDV(BusErr, new BusErrDevice());
88: NEWDV(NopIO, new NopIODevice());
89:
90: monitor_accstat.SetSize(80, 2 + 32);
91: }
92:
93: // デストラクタ
94: LunaMainbus::~LunaMainbus()
95: {
96: }
97:
98: // デバイスマップから devtable を作成 (ここは共通にできる)
99: void
100: LunaMainbus::MakeDevtable(const uint8 *maptable)
101: {
102: for (int i = 0; i < devtable.size(); i++) {
103: IODevice *d;
104: switch (maptable[i]) {
105: case NONE: d = pNopIO.get(); break;
106: case BUSERR: d = pBusErr.get(); break;
107: case PROM: d = pPROM.get(); break;
108: case MK48: d = pRTC.get(); break;
109: case PIO0: d = pPIO0.get(); break;
110: case PIO1: d = pPIO1.get(); break;
111: case SIO: d = pSIO.get(); break;
112: case TAS: d = pTAS.get(); break;
113: case SYSCLK: d = pSysClk.get(); break;
114: case SUBRAM: d = pSubRAM.get(); break;
115: case MROM: d = pNopIO.get(); break;
116: case LUNAFB: d = pPlaneVRAM.get(); break;
117: case BT45x: d = pBT45x.get(); break;
118: case CRTC2: d = pCRTC2.get(); break;
119: case SCSI: d = pSPC.get(); break;
120: case LANCE: d = pEthernet.get(); break;
121: case SYSCTL: d = pInterrupt.get(); break;
122: // これらはサブクラスが所有しているので Get で取得する必要がある。
123: case FUSE: d = GetFuseROMDevice(); break;
124: case CMMU: d = GetCMMUDevice(); break;
125: default:
1.1.1.2 ! root 126: PANIC("corrupted maptable[%u]=%d", i, maptable[i]);
1.1 root 127: }
128: devtable[i] = d;
129: }
130: }
131:
132: // メインバスの初期化
133: bool
134: LunaMainbus::InitMainbus()
135: {
136: auto mainram = dynamic_cast<MainRAMDevice *>(pMainRAM.get());
137: auto partial = dynamic_cast<PartialRAMDevice *>(pPartialRAM.get());
138:
139: // RAM は容量が確定した後のここで配置。
140: int ram_size_MB = mainram->GetSizeMB();
141: int i = 0;
142: while (ram_size_MB >= 16) {
143: // 16MB あれば RAM が直接担当
144: devtable[i++] = mainram;
145: ram_size_MB -= 16;
146: }
147: // 16MB 未満なら PartialRAM が担当
148: if (ram_size_MB > 0) {
149: devtable[i] = partial;
150: }
151:
152: // 先頭 (mainram or partial) をブートページ切り替え用に覚えておく。
153: ram0 = devtable[0];
154:
155: // アクセス状況用のマップを作成。
156: InitAccStat();
157:
158: return true;
159: }
160:
161: // ブートページを切り替える。
162: void
163: LunaMainbus::SwitchBootPage(bool isrom)
164: {
165: // 共通処理
166: inherited::SwitchBootPage(isrom);
167:
168: // ROM は 128KB しかないので 16MB まるごと切り替わったりはしないとは
169: // 思うけど、具体的にどの範囲が切り替わるのかを知る方法がないのと
170: // 大して副作用もないので、先頭の 1ブロックをまるごと切り替えておく。
171: if (isrom) {
172: auto prom0 = GetPROM0Device();
173: devtable[0x00] = prom0;
174: devtable[0x41] = prom0;
175: } else {
176: auto prom = GetPROMDevice();
177: devtable[0x00] = ram0;
178: devtable[0x41] = prom;
179: }
180: }
181:
182:
183: //
184: // LUNA-I
185: //
186:
187: // LUNA-I のデバイス割り当て表 (上位8ビット)
188: //
189: // 仕様 実際
190: // 00 00 メインメモリ
191: // -- 01..03 二重バスフォールトするようだ
192: // -- 04..0f 何かよく分からないものが読める
193: // -- 10..3f BUSERR
194: // 41 40..43 PROM (B、N=128KBでミラー)
195: // 45 44..47 mk48t02 (B、N=2048でミラー)
196: // 49 48..4b pio0 (B、N=4でミラー)
197: // 4d 4c..4f pio1 (B、N=4でミラー)
198: // 51 50..53 sio (BB、N=4でミラー)
199: // -- 54..5f 0xff が読めるようだ
200: // 61 60..61 TAS (B、N=1でミラー)
201: // 63 62..63 システムクロック (B、N=1でミラー)
202: // -- 以降TASとSysClkで2枠ずつ。また無効ビットの読み出しは
203: // -- 必ずしも Hi とは限らず不安定のようだ。
204: // 71 70..7f 3ポートRAM (B、N=128KBでミラー)
205: // 81 80.. BUSERR (オンボード拡張スロットA)
206: // 83 ..8f BUSERR (オンボード拡張スロットB)
207: // 91 90..9f 0xff が読めるようだ (PC-9000 拡張スロット)
208: //
209: // a1 マスクROM
210: // a0,a2,a4,... BUSERR
211: // a1,a3,a5,... マスクROM(なければ0xffが読める)
212: // b1 ビットマップ
213: // b0,b2,b4,... BUSERR
214: // b1,b3,b5,... ビットマップ (内訳は lunafb.cpp 参照)
215: // c1 パレット
216: // c0,c2,c4,... BUSERR
217: // c1,c3,c5,... パレット (B、N=4でミラー)
218: // d1 CRTC-II
219: // d0,d2,d4,... BUSERR
220: // d1,d3,d5,... CRTC-II (B、N=2でミラー)
221: //
222: // e1 e0..e3 SCSI (BBBB、N=16 でミラー)
223: // -- e4..ef 0xff が読めるようだが不安定。
224: // f1 f0..f3 LANCE (WW、N=2 でミラー)
225: // -- f4..ff 0xff が読めるようだ
226:
227: /*static*/ const uint8
228: Luna1Mainbus::maptable[256] = {
229: // (00,)01,02,03 は実際にはたぶんパリティチェックが入っていて(?)
230: // 非実装領域にアクセスすると二重バスフォールトになるがそれは未対応。
231: // RAM は Init() で動的に配置する。
232: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 00
233: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 08
234: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 10
235: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 18
236: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 20
237: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 28
238: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 30
239: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 38
240:
241: PROM, PROM, PROM, PROM, MK48, MK48, MK48, MK48, // 40
242: PIO0, PIO0, PIO0, PIO0, PIO1, PIO1, PIO1, PIO1, // 48
243: SIO, SIO, SIO, SIO, NONE, NONE, NONE, NONE, // 50
244: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 58
245: TAS, TAS, SYSCLK, SYSCLK, TAS, TAS, SYSCLK, SYSCLK, // 60
246: TAS, TAS, SYSCLK, SYSCLK, TAS, TAS, SYSCLK, SYSCLK, // 68
247: SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, // 70
248: SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, // 78
249:
250: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 80
251: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 88
252: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 90
253: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 98
254: BUSERR, MROM, BUSERR, MROM, BUSERR, MROM, BUSERR, MROM, // a0
255: BUSERR, MROM, BUSERR, MROM, BUSERR, MROM, BUSERR, MROM, // a8
256: BUSERR, LUNAFB, BUSERR, LUNAFB, BUSERR, LUNAFB, BUSERR, LUNAFB, // b0
257: BUSERR, LUNAFB, BUSERR, LUNAFB, BUSERR, LUNAFB, BUSERR, LUNAFB, // b8
258:
259: BUSERR, BT45x, BUSERR, BT45x, BUSERR, BT45x, BUSERR, BT45x, // c0
260: BUSERR, BT45x, BUSERR, BT45x, BUSERR, BT45x, BUSERR, BT45x, // c8
261: BUSERR, CRTC2, BUSERR, CRTC2, BUSERR, CRTC2, BUSERR, CRTC2, // d0
262: BUSERR, CRTC2, BUSERR, CRTC2, BUSERR, CRTC2, BUSERR, CRTC2, // d8
263: SCSI, SCSI, SCSI, SCSI, NONE, NONE, NONE, NONE, // e0
264: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // e8
265: LANCE, LANCE, LANCE, LANCE, NONE, NONE, NONE, NONE, // f0
266: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // f8
267: };
268:
269: // コンストラクタ
270: Luna1Mainbus::Luna1Mainbus()
271: {
272: // デバイス (順序に注意)
273: // BusErrDevice, NopIODevice は親コンストラクタで作成済み。
274:
275: NEWDV(Interrupt, new LunaInterrupt());
276: NEWDV(RTC, new BusIO_B<MK48T02Device>()); // required by SysClk
277: NEWDV(SysClk, new BusIO_B<SysClkDevice>()); // required by PROMEmu
278: if (gMainApp.msxdos_mode) {
279: NEWDV(PROM, new MSXDOSDevice());
280: } else if (gMainApp.exec_file ||
281: gConfig->Find("prom-image").AsString().empty()) {
282: NEWDV(PROM, new Luna1PROMEmuDevice());
283: } else {
284: NEWDV(PROM, new PROMDevice()); // required by RAM,BT45x
285: }
286: NEWDV(PROM0, new PROM0Device());
287: NEWDV(MainRAM, new MainRAMDevice()); // required by PartialRAM
288: NEWDV(PartialRAM, new PartialRAMDevice());
289: NEWDV(PIO0, new BusIO_B<PIO0Device>());
290: NEWDV(PIO1, new BusIO_B<PIO1Device>());
291: NEWDV(SIO, new BusIO_BB<SIODevice>());
292: NEWDV(TAS, new BusIO_B<TASDevice>());
293: NEWDV(SubRAM, new SubRAMDevice(128));
294: NEWDV(CRTC2, new BusIO_B<CRTC2Device>());
295: NEWDV(SPC, new BusIO_BBBB<SPCDevice>());
296: NEWDV(Ethernet, new BusIO_W<LanceDevice>());
297: }
298:
299: // デストラクタ
300: Luna1Mainbus::~Luna1Mainbus()
301: {
302: }
303:
1.1.1.2 ! root 304: // 動的なコンストラクション
! 305: bool
! 306: Luna1Mainbus::Create()
! 307: {
! 308: int nplane = BT45xDevice::GetConfigPlaneCount();
! 309: if (nplane < 0) {
! 310: return false;
! 311: }
! 312: if (nplane == 8) { // required by Lunafb
! 313: NEWDV(BT45x, new BusIO_BFFF<BT458Device>());
! 314: } else {
! 315: NEWDV(BT45x, new BusIO_B<BT454Device>());
! 316: }
! 317: NEWDV(PlaneVRAM, new LunafbDevice());
! 318:
! 319: // 全部揃ったここで、デバイスマップから devtable を作成。
! 320: MakeDevtable(maptable);
! 321: return true;
! 322: }
1.1 root 323:
324: //
325: // LUNA-88K
326: //
327:
328: // 00..03 RAM (64MB 実機の場合)
329: // 04..3f アドレスの残像? (64MB 実機の場合)
330: // 40,41 PROM (B、N=256KB でミラー)
331: // 42,43 FUSEROM (BFFF、N=256 でミラー)
332: // 44,45 NVRAM (BFFF、N=2048 でミラー)
333: // 46,47 アドレスの残像?
334: // 48,49 PIO0 (BFFF、N=4 でミラー)
335: // 4a,4b アドレスの残像?
336: // 4c,4d PIO1 (BFFF、N=4 でミラー)
337: // 4e,4f アドレスの残像?
338: // 50,51 SIO (BFFF、N=4 でミラー)
339: // 52..5f アドレスの残像?
340: // 60,61 TAS? (BFFF、N=1 ?)
341: // 62,63 SysClk (BFFF、N=1 ?)
342: // 64,65,66,67 SysCtlr? (BFFF、N=4 ?)
343: // 68,69,6a,6b SysCtlr? (L、N=4 ?)
344: // 6c,6d CPU リセット
345: // 6e,6f 68-6b と同じパターンの気がする
346: // 70-7f SubRAM
347: // 80-9f アドレスの残像?
348: // a0-af 偶数(a0,a2,..)は残像、奇数(a1,a3,..)は ff
349: // b0-bf 偶数(b0,b2,..)は残像、奇数(b1,b3,..)は LUNAFB
350: // c0-cf 偶数(c0,c2,..)は残像、奇数(c1,c3,..)は BT454(BFFF、N=4)
351: // d0-df 偶数(d0,d2,..)は残像、奇数(d1,d3,..)はたぶん CRTC2
352: // (CRTC2 は今の所 $ff しか観測できていないので詳細不明)
353: // e0,e1 SPC (BFFF、N=16 でミラー)
354: // e2-e7 繋がってない? 概ね $f4'00'c0'01 が読める。
355: // FUSEROM などの繋がってないところと同じパターンが読める。
356: // f0,f1 たぶん Lance (BFFF、N=2)
357: // f2-fd $ff
358: // fe $fe00'0000-$fef7'ffff まではアドレスの残像
359: // $fef8'0000-$feff'ffff までは $ff
360: // ff たぶん CMMU 以外はアドレスの残像
361: //
362: // アドレスの残像(?) は
363: // - バイトアクセスならアドレスの下位 8bit、
364: // - ワードアクセスならアドレスの下位 16bit、
365: // - ロングワードアクセスならアドレス 32bit
366: // が見え、時々 $ffffffff が混ざるようだ ($00..$ff までのうち2個程度)。
367: // 一方、デバイスに接続されていない下位24ビットあるいは28ビットに
368: // $f400c001 が見えるエリアも多いが、$f400c001 は jmp r1 命令なので、おそらく
369: // PROM モニターがこのダンプを表示する際のプログラムコードがデータバスバッファ
370: // を通過したのが見えている可能性がある。
371: // いずれも再現は難しいので見なかったことにする。
372:
373: /*static*/ const uint8
374: Luna88kMainbus::maptable[256] = {
375: // RAM は Init() で動的に配置する (64MB なら 00..03 の4枠)。
376: // RAM 未実装領域については要調査。少なくとも末尾に BUSERR がないと
377: // OpenBSD カーネルが起動しない。
378: // 先頭 64MB の空間 (00..03) だけは、PROM 1.20 ではメモリが無いときでも
379: // バスエラーにならないことを期待しているので NONE にしておく。
380: NONE, NONE, NONE, NONE, BUSERR, BUSERR, BUSERR, BUSERR, // 00
381: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 08
382: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 10
383: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 18
384: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 20
385: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 28
386: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 30
387: BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, BUSERR, // 38
388:
389: // LUNA-88K2 は 47 に(も?) NVRAM がいるようだ
390: // 69,6b,6d にも何かのコントローラ?
391: PROM, PROM, FUSE, FUSE, MK48, MK48, NONE, NONE, // 40
392: PIO0, PIO0, NONE, NONE, PIO1, PIO1, NONE, NONE, // 48
393: SIO, SIO, NONE, NONE, NONE, NONE, NONE, NONE, // 50
394: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 58
395: TAS, TAS, SYSCLK, SYSCLK, SYSCTL, SYSCTL, SYSCTL, SYSCTL, // 60
396: SYSCTL, SYSCTL, SYSCTL, SYSCTL, SYSCTL, SYSCTL, SYSCTL, SYSCTL, // 68
397: SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, // 70
398: SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, SUBRAM, // 78
399:
400: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 80
401: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 88
402: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 90
403: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // 98
404: NONE, MROM, NONE, MROM, NONE, MROM, NONE, MROM, // a0
405: NONE, MROM, NONE, MROM, NONE, MROM, NONE, MROM, // a8
406: NONE, LUNAFB, NONE, LUNAFB, NONE, LUNAFB, NONE, LUNAFB, // b0
407: NONE, LUNAFB, NONE, LUNAFB, NONE, LUNAFB, NONE, LUNAFB, // b8
408:
409: // d0 にボードチェックレジスタ?
410: NONE, BT45x, NONE, BT45x, NONE, BT45x, NONE, BT45x, // c0
411: NONE, BT45x, NONE, BT45x, NONE, BT45x, NONE, BT45x, // c8
412: NONE, CRTC2, NONE, CRTC2, NONE, CRTC2, NONE, CRTC2, // d0
413: NONE, CRTC2, NONE, CRTC2, NONE, CRTC2, NONE, CRTC2, // d8
414: SCSI, SCSI, NONE, NONE, NONE, NONE, NONE, NONE, // e0
415: NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, // e8
416: LANCE, LANCE, NONE, NONE, NONE, NONE, NONE, NONE, // f0
417: NONE, NONE, NONE, NONE, NONE, NONE, NONE, CMMU, // f8
418: };
419:
420: // コンストラクタ
421: Luna88kMainbus::Luna88kMainbus()
422: {
423: // デバイス (順序に注意)
424: // BusErrDevice, NopIODevice は親コンストラクタで作成済み。
425:
426: NEWDV(Interrupt, new SysCtlrDevice());
427: NEWDV(RTC, new BusIO_BFFF<MK48T02Device>()); // required by SysClk
428: NEWDV(SysClk, new BusIO_BFFF<SysClkDevice>()); // required by PROMEmu
429: if (gMainApp.exec_file || gConfig->Find("prom-image").AsString().empty()) {
430: NEWDV(PROM, new Luna88kPROMEmuDevice());
431: } else {
432: NEWDV(PROM, new PROMDevice()); // required by RAM
433: }
434: NEWDV(PROM0, new PROM0Device());
435: NEWDV(MainRAM, new MainRAMDevice()); // required by PartialRAM
436: NEWDV(PartialRAM, new PartialRAMDevice());
437: NEWDV(FuseROM, new BusIO_BFFF<FuseROMDevice>());
438: NEWDV(PIO0, new BusIO_BFFF<PIO0Device>());
439: NEWDV(PIO1, new BusIO_BFFF<PIO1Device>());
440: NEWDV(SIO, new BusIO_BFFF<SIODevice>());
441: NEWDV(TAS, new BusIO_BFFF<TASDevice>());
442: NEWDV(SubRAM, new SubRAMDevice(128));
443: NEWDV(CRTC2, new BusIO_BFFF<CRTC2Device>());
444: NEWDV(SPC, new BusIO_BFFF<SPCDevice>());
445: NEWDV(Ethernet, new BusIO_WF<LanceDevice>());
446: NEWDV(CMMU, new CMMUDevice());
447: }
448:
449: // デストラクタ
450: Luna88kMainbus::~Luna88kMainbus()
451: {
452: }
1.1.1.2 ! root 453:
! 454: // 動的なコンストラクション
! 455: bool
! 456: Luna88kMainbus::Create()
! 457: {
! 458: int nplane = BT45xDevice::GetConfigPlaneCount();
! 459: if (nplane < 0) {
! 460: return false;
! 461: }
! 462: if (nplane == 8) { // required by Lunafb
! 463: NEWDV(BT45x, new BusIO_BFFF<BT458Device>());
! 464: } else {
! 465: NEWDV(BT45x, new BusIO_B<BT454Device>());
! 466: }
! 467: NEWDV(PlaneVRAM, new LunafbDevice());
! 468:
! 469: // 全部揃ったここで、デバイスマップから devtable を作成。
! 470: MakeDevtable(maptable);
! 471: return true;
! 472: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.