|
|
1.1 ! root 1: /* wd.c: A WD80x3 ethernet driver for linux. */ ! 2: /* ! 3: Written 1993-94 by Donald Becker. ! 4: ! 5: Copyright 1993 United States Government as represented by the ! 6: Director, National Security Agency. ! 7: ! 8: This software may be used and distributed according to the terms ! 9: of the GNU Public License, incorporated herein by reference. ! 10: ! 11: The author may be reached as [email protected], or C/O ! 12: Center of Excellence in Space Data and Information Sciences ! 13: Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 ! 14: ! 15: This is a driver for WD8003 and WD8013 "compatible" ethercards. ! 16: ! 17: Thanks to Russ Nelson ([email protected]) for loaning me a WD8013. ! 18: ! 19: Changelog: ! 20: ! 21: Paul Gortmaker : multiple card support for module users, support ! 22: for non-standard memory sizes. ! 23: ! 24: ! 25: */ ! 26: ! 27: static const char *version = ! 28: "wd.c:v1.10 9/23/94 Donald Becker ([email protected])\n"; ! 29: ! 30: #include <linux/module.h> ! 31: ! 32: #include <linux/kernel.h> ! 33: #include <linux/sched.h> ! 34: #include <linux/errno.h> ! 35: #include <linux/string.h> ! 36: #include <asm/io.h> ! 37: #include <asm/system.h> ! 38: ! 39: #include <linux/netdevice.h> ! 40: #include <linux/etherdevice.h> ! 41: #include "8390.h" ! 42: ! 43: /* A zero-terminated list of I/O addresses to be probed. */ ! 44: static unsigned int wd_portlist[] = ! 45: {0x300, 0x280, 0x380, 0x240, 0}; ! 46: ! 47: int wd_probe(struct device *dev); ! 48: int wd_probe1(struct device *dev, int ioaddr); ! 49: ! 50: static int wd_open(struct device *dev); ! 51: static void wd_reset_8390(struct device *dev); ! 52: static void wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, ! 53: int ring_page); ! 54: static void wd_block_input(struct device *dev, int count, ! 55: struct sk_buff *skb, int ring_offset); ! 56: static void wd_block_output(struct device *dev, int count, ! 57: const unsigned char *buf, const int start_page); ! 58: static int wd_close_card(struct device *dev); ! 59: ! 60: ! 61: #define WD_START_PG 0x00 /* First page of TX buffer */ ! 62: #define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */ ! 63: #define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */ ! 64: ! 65: #define WD_CMDREG 0 /* Offset to ASIC command register. */ ! 66: #define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */ ! 67: #define WD_MEMENB 0x40 /* Enable the shared memory. */ ! 68: #define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */ ! 69: #define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */ ! 70: #define NIC16 0x40 /* Enable 16 bit access from the 8390. */ ! 71: #define WD_NIC_OFFSET 16 /* Offset to the 8390 from the base_addr. */ ! 72: #define WD_IO_EXTENT 32 ! 73: ! 74: ! 75: /* Probe for the WD8003 and WD8013. These cards have the station ! 76: address PROM at I/O ports <base>+8 to <base>+13, with a checksum ! 77: following. A Soundblaster can have the same checksum as an WDethercard, ! 78: so we have an extra exclusionary check for it. ! 79: ! 80: The wd_probe1() routine initializes the card and fills the ! 81: station address field. */ ! 82: ! 83: #ifdef HAVE_DEVLIST ! 84: struct netdev_entry wd_drv = ! 85: {"wd", wd_probe1, WD_IO_EXTENT, wd_portlist}; ! 86: #else ! 87: ! 88: int wd_probe(struct device *dev) ! 89: { ! 90: int i; ! 91: int base_addr = dev ? dev->base_addr : 0; ! 92: ! 93: if (base_addr > 0x1ff) /* Check a single specified location. */ ! 94: return wd_probe1(dev, base_addr); ! 95: else if (base_addr != 0) /* Don't probe at all. */ ! 96: return ENXIO; ! 97: ! 98: for (i = 0; wd_portlist[i]; i++) { ! 99: int ioaddr = wd_portlist[i]; ! 100: if (check_region(ioaddr, WD_IO_EXTENT)) ! 101: continue; ! 102: if (wd_probe1(dev, ioaddr) == 0) ! 103: return 0; ! 104: } ! 105: ! 106: return ENODEV; ! 107: } ! 108: #endif ! 109: ! 110: int wd_probe1(struct device *dev, int ioaddr) ! 111: { ! 112: int i; ! 113: int checksum = 0; ! 114: int ancient = 0; /* An old card without config registers. */ ! 115: int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */ ! 116: const char *model_name; ! 117: static unsigned version_printed = 0; ! 118: ! 119: for (i = 0; i < 8; i++) ! 120: checksum += inb(ioaddr + 8 + i); ! 121: if (inb(ioaddr + 8) == 0xff /* Extra check to avoid soundcard. */ ! 122: || inb(ioaddr + 9) == 0xff ! 123: || (checksum & 0xff) != 0xFF) ! 124: return ENODEV; ! 125: ! 126: /* We should have a "dev" from Space.c or the static module table. */ ! 127: if (dev == NULL) { ! 128: printk("wd.c: Passed a NULL device.\n"); ! 129: dev = init_etherdev(0, 0); ! 130: } ! 131: ! 132: /* Check for semi-valid mem_start/end values if supplied. */ ! 133: if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) { ! 134: printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n"); ! 135: dev->mem_start = 0; ! 136: dev->mem_end = 0; ! 137: } ! 138: ! 139: if (ei_debug && version_printed++ == 0) ! 140: printk(version); ! 141: ! 142: printk("%s: WD80x3 at %#3x, ", dev->name, ioaddr); ! 143: for (i = 0; i < 6; i++) ! 144: printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i)); ! 145: ! 146: /* The following PureData probe code was contributed by ! 147: Mike Jagdis <[email protected]>. Puredata does software ! 148: configuration differently from others so we have to check for them. ! 149: This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card. ! 150: */ ! 151: if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') { ! 152: unsigned char reg5 = inb(ioaddr+5); ! 153: ! 154: switch (inb(ioaddr+2)) { ! 155: case 0x03: word16 = 0; model_name = "PDI8023-8"; break; ! 156: case 0x05: word16 = 0; model_name = "PDUC8023"; break; ! 157: case 0x0a: word16 = 1; model_name = "PDI8023-16"; break; ! 158: /* Either 0x01 (dumb) or they've released a new version. */ ! 159: default: word16 = 0; model_name = "PDI8023"; break; ! 160: } ! 161: dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12; ! 162: dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1; ! 163: } else { /* End of PureData probe */ ! 164: /* This method of checking for a 16-bit board is borrowed from the ! 165: we.c driver. A simpler method is just to look in ASIC reg. 0x03. ! 166: I'm comparing the two method in alpha test to make certain they ! 167: return the same result. */ ! 168: /* Check for the old 8 bit board - it has register 0/8 aliasing. ! 169: Do NOT check i>=6 here -- it hangs the old 8003 boards! */ ! 170: for (i = 0; i < 6; i++) ! 171: if (inb(ioaddr+i) != inb(ioaddr+8+i)) ! 172: break; ! 173: if (i >= 6) { ! 174: ancient = 1; ! 175: model_name = "WD8003-old"; ! 176: word16 = 0; ! 177: } else { ! 178: int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */ ! 179: outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */ ! 180: if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */ ! 181: && (tmp & 0x01) == 0x01 ) { /* In a 16 slot. */ ! 182: int asic_reg5 = inb(ioaddr+WD_CMDREG5); ! 183: /* Magic to set ASIC to word-wide mode. */ ! 184: outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5); ! 185: outb(tmp, ioaddr+1); ! 186: model_name = "WD8013"; ! 187: word16 = 1; /* We have a 16bit board here! */ ! 188: } else { ! 189: model_name = "WD8003"; ! 190: word16 = 0; ! 191: } ! 192: outb(tmp, ioaddr+1); /* Restore original reg1 value. */ ! 193: } ! 194: #ifndef final_version ! 195: if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01)) ! 196: printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).", ! 197: word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8); ! 198: #endif ! 199: } ! 200: ! 201: #if defined(WD_SHMEM) && WD_SHMEM > 0x80000 ! 202: /* Allow a compile-time override. */ ! 203: dev->mem_start = WD_SHMEM; ! 204: #else ! 205: if (dev->mem_start == 0) { ! 206: /* Sanity and old 8003 check */ ! 207: int reg0 = inb(ioaddr); ! 208: if (reg0 == 0xff || reg0 == 0) { ! 209: /* Future plan: this could check a few likely locations first. */ ! 210: dev->mem_start = 0xd0000; ! 211: printk(" assigning address %#lx", dev->mem_start); ! 212: } else { ! 213: int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f; ! 214: /* Some boards don't have the register 5 -- it returns 0xff. */ ! 215: if (high_addr_bits == 0x1f || word16 == 0) ! 216: high_addr_bits = 0x01; ! 217: dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19); ! 218: } ! 219: } ! 220: #endif ! 221: ! 222: /* The 8390 isn't at the base address -- the ASIC regs are there! */ ! 223: dev->base_addr = ioaddr+WD_NIC_OFFSET; ! 224: ! 225: if (dev->irq < 2) { ! 226: int irqmap[] = {9,3,5,7,10,11,15,4}; ! 227: int reg1 = inb(ioaddr+1); ! 228: int reg4 = inb(ioaddr+4); ! 229: if (ancient || reg1 == 0xff) { /* Ack!! No way to read the IRQ! */ ! 230: short nic_addr = ioaddr+WD_NIC_OFFSET; ! 231: ! 232: /* We have an old-style ethercard that doesn't report its IRQ ! 233: line. Do autoirq to find the IRQ line. Note that this IS NOT ! 234: a reliable way to trigger an interrupt. */ ! 235: outb_p(E8390_NODMA + E8390_STOP, nic_addr); ! 236: outb(0x00, nic_addr+EN0_IMR); /* Disable all intrs. */ ! 237: autoirq_setup(0); ! 238: outb_p(0xff, nic_addr + EN0_IMR); /* Enable all interrupts. */ ! 239: outb_p(0x00, nic_addr + EN0_RCNTLO); ! 240: outb_p(0x00, nic_addr + EN0_RCNTHI); ! 241: outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */ ! 242: dev->irq = autoirq_report(2); ! 243: outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */ ! 244: ! 245: if (ei_debug > 2) ! 246: printk(" autoirq is %d", dev->irq); ! 247: if (dev->irq < 2) ! 248: dev->irq = word16 ? 10 : 5; ! 249: } else ! 250: dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)]; ! 251: } else if (dev->irq == 2) /* Fixup bogosity: IRQ2 is really IRQ9 */ ! 252: dev->irq = 9; ! 253: ! 254: /* Snarf the interrupt now. There's no point in waiting since we cannot ! 255: share and the board will usually be enabled. */ ! 256: if (request_irq(dev->irq, ei_interrupt, 0, model_name, NULL)) { ! 257: printk (" unable to get IRQ %d.\n", dev->irq); ! 258: return EAGAIN; ! 259: } ! 260: ! 261: /* Allocate dev->priv and fill in 8390 specific dev fields. */ ! 262: if (ethdev_init(dev)) { ! 263: printk (" unable to get memory for dev->priv.\n"); ! 264: free_irq(dev->irq, NULL); ! 265: return -ENOMEM; ! 266: } ! 267: ! 268: /* OK, were are certain this is going to work. Setup the device. */ ! 269: request_region(ioaddr, WD_IO_EXTENT, model_name); ! 270: ! 271: ei_status.name = model_name; ! 272: ei_status.word16 = word16; ! 273: ei_status.tx_start_page = WD_START_PG; ! 274: ei_status.rx_start_page = WD_START_PG + TX_PAGES; ! 275: ! 276: /* Don't map in the shared memory until the board is actually opened. */ ! 277: dev->rmem_start = dev->mem_start + TX_PAGES*256; ! 278: ! 279: /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */ ! 280: if (dev->mem_end != 0) { ! 281: ei_status.stop_page = (dev->mem_end - dev->mem_start)/256; ! 282: } else { ! 283: ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG; ! 284: dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256; ! 285: } ! 286: dev->rmem_end = dev->mem_end; ! 287: ! 288: printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n", ! 289: model_name, dev->irq, dev->mem_start, dev->mem_end-1); ! 290: ! 291: ei_status.reset_8390 = &wd_reset_8390; ! 292: ei_status.block_input = &wd_block_input; ! 293: ei_status.block_output = &wd_block_output; ! 294: ei_status.get_8390_hdr = &wd_get_8390_hdr; ! 295: dev->open = &wd_open; ! 296: dev->stop = &wd_close_card; ! 297: NS8390_init(dev, 0); ! 298: ! 299: #if 1 ! 300: /* Enable interrupt generation on softconfig cards -- M.U */ ! 301: /* .. but possibly potentially unsafe - Donald */ ! 302: if (inb(ioaddr+14) & 0x20) ! 303: outb(inb(ioaddr+4)|0x80, ioaddr+4); ! 304: #endif ! 305: ! 306: return 0; ! 307: } ! 308: ! 309: static int ! 310: wd_open(struct device *dev) ! 311: { ! 312: int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ ! 313: ! 314: /* Map in the shared memory. Always set register 0 last to remain ! 315: compatible with very old boards. */ ! 316: ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB; ! 317: ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16; ! 318: ! 319: if (ei_status.word16) ! 320: outb(ei_status.reg5, ioaddr+WD_CMDREG5); ! 321: outb(ei_status.reg0, ioaddr); /* WD_CMDREG */ ! 322: ! 323: ei_open(dev); ! 324: MOD_INC_USE_COUNT; ! 325: return 0; ! 326: } ! 327: ! 328: static void ! 329: wd_reset_8390(struct device *dev) ! 330: { ! 331: int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ ! 332: ! 333: outb(WD_RESET, wd_cmd_port); ! 334: if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies); ! 335: ei_status.txing = 0; ! 336: ! 337: /* Set up the ASIC registers, just in case something changed them. */ ! 338: outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port); ! 339: if (ei_status.word16) ! 340: outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5); ! 341: ! 342: if (ei_debug > 1) printk("reset done\n"); ! 343: return; ! 344: } ! 345: ! 346: /* Grab the 8390 specific header. Similar to the block_input routine, but ! 347: we don't need to be concerned with ring wrap as the header will be at ! 348: the start of a page, so we optimize accordingly. */ ! 349: ! 350: static void ! 351: wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) ! 352: { ! 353: ! 354: int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ ! 355: unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8); ! 356: ! 357: /* We'll always get a 4 byte header read followed by a packet read, so ! 358: we enable 16 bit mode before the header, and disable after the body. */ ! 359: if (ei_status.word16) ! 360: outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5); ! 361: ! 362: #ifdef notdef ! 363: /* Officially this is what we are doing, but the readl() is faster */ ! 364: memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); ! 365: #else ! 366: ((unsigned int*)hdr)[0] = readl(hdr_start); ! 367: #endif ! 368: } ! 369: ! 370: /* Block input and output are easy on shared memory ethercards, and trivial ! 371: on the Western digital card where there is no choice of how to do it. ! 372: The only complications are that the ring buffer wraps, and need to map ! 373: switch between 8- and 16-bit modes. */ ! 374: ! 375: static void ! 376: wd_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) ! 377: { ! 378: int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ ! 379: unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8); ! 380: ! 381: if (xfer_start + count > dev->rmem_end) { ! 382: /* We must wrap the input move. */ ! 383: int semi_count = dev->rmem_end - xfer_start; ! 384: memcpy_fromio(skb->data, xfer_start, semi_count); ! 385: count -= semi_count; ! 386: memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); ! 387: } else { ! 388: /* Packet is in one chunk -- we can copy + cksum. */ ! 389: eth_io_copy_and_sum(skb, xfer_start, count, 0); ! 390: } ! 391: ! 392: /* Turn off 16 bit access so that reboot works. ISA brain-damage */ ! 393: if (ei_status.word16) ! 394: outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5); ! 395: } ! 396: ! 397: static void ! 398: wd_block_output(struct device *dev, int count, const unsigned char *buf, ! 399: int start_page) ! 400: { ! 401: int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ ! 402: long shmem = dev->mem_start + ((start_page - WD_START_PG)<<8); ! 403: ! 404: ! 405: if (ei_status.word16) { ! 406: /* Turn on and off 16 bit access so that reboot works. */ ! 407: outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5); ! 408: memcpy_toio(shmem, buf, count); ! 409: outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5); ! 410: } else ! 411: memcpy_toio(shmem, buf, count); ! 412: } ! 413: ! 414: ! 415: static int ! 416: wd_close_card(struct device *dev) ! 417: { ! 418: int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ ! 419: ! 420: if (ei_debug > 1) ! 421: printk("%s: Shutting down ethercard.\n", dev->name); ! 422: ei_close(dev); ! 423: ! 424: /* Change from 16-bit to 8-bit shared memory so reboot works. */ ! 425: if (ei_status.word16) ! 426: outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 ); ! 427: ! 428: /* And disable the shared memory. */ ! 429: outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg); ! 430: ! 431: MOD_DEC_USE_COUNT; ! 432: ! 433: return 0; ! 434: } ! 435: ! 436: ! 437: #ifdef MODULE ! 438: #define MAX_WD_CARDS 4 /* Max number of wd cards per module */ ! 439: #define NAMELEN 8 /* # of chars for storing dev->name */ ! 440: static char namelist[NAMELEN * MAX_WD_CARDS] = { 0, }; ! 441: static struct device dev_wd[MAX_WD_CARDS] = { ! 442: { ! 443: NULL, /* assign a chunk of namelist[] below */ ! 444: 0, 0, 0, 0, ! 445: 0, 0, ! 446: 0, 0, 0, NULL, NULL ! 447: }, ! 448: }; ! 449: ! 450: static int io[MAX_WD_CARDS] = { 0, }; ! 451: static int irq[MAX_WD_CARDS] = { 0, }; ! 452: static int mem[MAX_WD_CARDS] = { 0, }; ! 453: static int mem_end[MAX_WD_CARDS] = { 0, }; /* for non std. mem size */ ! 454: ! 455: /* This is set up so that only a single autoprobe takes place per call. ! 456: ISA device autoprobes on a running machine are not recommended. */ ! 457: int ! 458: init_module(void) ! 459: { ! 460: int this_dev, found = 0; ! 461: ! 462: for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { ! 463: struct device *dev = &dev_wd[this_dev]; ! 464: dev->name = namelist+(NAMELEN*this_dev); ! 465: dev->irq = irq[this_dev]; ! 466: dev->base_addr = io[this_dev]; ! 467: dev->mem_start = mem[this_dev]; ! 468: dev->mem_end = mem_end[this_dev]; ! 469: dev->init = wd_probe; ! 470: if (io[this_dev] == 0) { ! 471: if (this_dev != 0) break; /* only autoprobe 1st one */ ! 472: printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n"); ! 473: } ! 474: if (register_netdev(dev) != 0) { ! 475: printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]); ! 476: if (found != 0) return 0; /* Got at least one. */ ! 477: return -ENXIO; ! 478: } ! 479: found++; ! 480: } ! 481: ! 482: return 0; ! 483: } ! 484: ! 485: void ! 486: cleanup_module(void) ! 487: { ! 488: int this_dev; ! 489: ! 490: for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { ! 491: struct device *dev = &dev_wd[this_dev]; ! 492: if (dev->priv != NULL) { ! 493: int ioaddr = dev->base_addr - WD_NIC_OFFSET; ! 494: kfree(dev->priv); ! 495: dev->priv = NULL; ! 496: free_irq(dev->irq, NULL); ! 497: irq2dev_map[dev->irq] = NULL; ! 498: release_region(ioaddr, WD_IO_EXTENT); ! 499: unregister_netdev(dev); ! 500: } ! 501: } ! 502: } ! 503: #endif /* MODULE */ ! 504: ! 505: ! 506: /* ! 507: * Local variables: ! 508: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c wd.c" ! 509: * version-control: t ! 510: * tab-width: 4 ! 511: * kept-new-versions: 5 ! 512: * End: ! 513: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.