8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.
Maintained by Jeff Garzik <jgarzik@pobox.com> Copyright 2000-2002 Jeff Garzik
Much code comes from Donald Becker's rtl8139.c driver, versions 1.13 and older. This driver was originally based on rtl8139.c version 1.07. Header of rtl8139.c version 1.13:
-----<snip>-----
Written 1997-2001 by Donald Becker. This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. Drivers based on or derived from this code fall under the GPL and must retain the authorship, copyright and license notice. This file is not a complete program and may only be used when the entire operating system is licensed under the GPL.
This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet chips.
The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 Annapolis MD 21403
/* Whether to use MMIO or PIO. Default to MMIO. */ #ifdef CONFIG_8139TOO_PIO staticbool use_io = true; #else staticbool use_io = false; #endif
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */ staticint multicast_filter_limit = 32;
/* bitmapped message enable number */ staticint debug = -1;
/* * Receive ring size * Warning: 64K ring has hardware issues and may lock up.
*/ #ifdefined(CONFIG_SH_DREAMCAST) #define RX_BUF_IDX 0 /* 8K ring */ #else #define RX_BUF_IDX 2 /* 32K ring */ #endif #define RX_BUF_LEN (8192 << RX_BUF_IDX) #define RX_BUF_PAD 16 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
/* Size of the Tx bounce buffers -- must be at least (dev->mtu+18+4). */ #define TX_BUF_SIZE MAX_ETH_FRAME_SIZE #define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)
/* PCI Tuning Parameters
Threshold is bytes transferred to chip before transmission starts. */ #define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ #define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */
/* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (6*HZ)
#define RTL_NUM_STATS 4 /* number of ETHTOOL_GSTATS u64's */ #define RTL_REGS_VER 1 /* version of reg. data in ETHTOOL_GREGS */ #define RTL_MIN_IO_SIZE 0x80 #define RTL8139B_IO_SIZE 256
/* some crazy cards report invalid vendor ids like * 0x0001 here. The other ids are valid and constant, * so we simply don't match on the main vendor id.
*/
{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },
{PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 },
{PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 },
if (tp->mmio_addr)
pci_iounmap (pdev, tp->mmio_addr);
/* it's ok to call this even if we have no regions to free */
pci_release_regions (pdev);
free_netdev(dev);
}
staticvoid rtl8139_chip_reset (void __iomem *ioaddr)
{ int i;
/* Soft reset the chip. */
RTL_W8 (ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) {
barrier(); if ((RTL_R8 (ChipCmd) & CmdReset) == 0) break;
udelay (10);
}
}
/* Bring old chips out of low-power mode. */
RTL_W8 (HltClk, 'R');
/* check for missing/broken hardware */ if (RTL_R32 (TxConfig) == 0xFFFFFFFF) {
dev_err(&pdev->dev, "Chip not responding, ignoring board\n");
rc = -EIO; goto err_out;
}
/* identify chip attached to board */
version = RTL_R32 (TxConfig) & HW_REVID_MASK; for (i = 0; i < ARRAY_SIZE (rtl_chip_info); i++) if (version == rtl_chip_info[i].version) {
tp->chipset = i; goto match;
}
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
i = 0;
dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
dev_dbg(&pdev->dev, "TxConfig = 0x%x\n", RTL_R32 (TxConfig));
tp->chipset = 0;
match:
pr_debug("chipset id (%d) == index %d, '%s'\n",
version, i, rtl_chip_info[i].name);
/* when we're built into the kernel, the driver version message * is only printed if at least one 8139 board has been found
*/ #ifndef MODULE
{ staticint printed_version; if (!printed_version++)
pr_info(RTL8139_DRIVER_NAME "\n");
} #endif
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) {
dev_info(&pdev->dev, "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip, use 8139cp\n",
pdev->vendor, pdev->device, pdev->revision); return -ENODEV;
}
addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++)
addr[i] = cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len));
eth_hw_addr_set(dev, (u8 *)addr);
/* The Rtl8139-specific entries in the device structure. */
dev->netdev_ops = &rtl8139_netdev_ops;
dev->ethtool_ops = &rtl8139_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
netif_napi_add(dev, &tp->napi, rtl8139_poll);
/* note: the hardware is not capable of sg/csum/highdma, however * through the use of skb_copy_and_csum_dev we enable these * features
*/
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
dev->vlan_features = dev->features;
/* dev is fully set up and ready to use now */
pr_debug("about to register device named %s (%p)...\n",
dev->name, dev);
i = register_netdev (dev); if (i) goto err_out;
netdev_dbg(dev, "Identified 8139 chip type '%s'\n",
rtl_chip_info[tp->chipset].name);
/* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but
takes too much time. */ #ifdef CONFIG_8139TOO_8129 if (tp->drv_flags & HAS_MII_XCVR) { int phy, phy_idx = 0; for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { int mii_status = mdio_read(dev, phy, 1); if (mii_status != 0xffff && mii_status != 0x0000) {
u16 advertising = mdio_read(dev, phy, 4);
tp->phys[phy_idx++] = phy;
netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n",
phy, mii_status, advertising);
}
} if (phy_idx == 0) {
netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n");
tp->phys[0] = 32;
}
} else #endif
tp->phys[0] = 32;
tp->mii.phy_id = tp->phys[0];
/* The lower four bits are the media type. */
option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; if (option > 0) {
tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
tp->default_port = option & 0xFF; if (tp->default_port)
tp->mii.force_media = 1;
} if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0)
tp->mii.full_duplex = full_duplex[board_idx]; if (tp->mii.full_duplex) {
netdev_info(dev, "Media type forced to Full Duplex\n"); /* Changing the MII-advertised media because might prevent
re-connection. */
tp->mii.force_media = 1;
} if (tp->default_port) {
netdev_info(dev, " Forcing %dMbps %s-duplex operation\n",
(option & 0x20 ? 100 : 10),
(option & 0x10 ? "full" : "half"));
mdio_write(dev, tp->phys[0], 0,
((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */
((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
}
/* Put the chip into low-power mode. */ if (rtl_chip_info[tp->chipset].flags & HasHltClk)
RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
/* Terminate the EEPROM access. */
RTL_W8(Cfg9346, 0);
eeprom_delay ();
return retval;
}
/* MII serial management: mostly bogus for now. */ /* Read and write the MII management registers using software-generated serial MDIO protocol. The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back PCI I/O cycles, but we insert a delay to avoid
"overclocking" issues. */ #define MDIO_DIR 0x80 #define MDIO_DATA_OUT 0x04 #define MDIO_DATA_IN 0x02 #define MDIO_CLK 0x01 #define MDIO_WRITE0 (MDIO_DIR) #define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
#ifdef CONFIG_8139TOO_8129 /* Syncronize the MII management interface by shifting 32 one bits out. */ staticvoid mdio_sync (void __iomem *ioaddr)
{ int i;
for (i = 32; i >= 0; i--) {
RTL_W8 (Config4, MDIO_WRITE1);
mdio_delay ();
RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK);
mdio_delay ();
}
} #endif
staticint mdio_read (struct net_device *dev, int phy_id, int location)
{ struct rtl8139_private *tp = netdev_priv(dev); int retval = 0; #ifdef CONFIG_8139TOO_8129 void __iomem *ioaddr = tp->mmio_addr; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int i; #endif
if (phy_id > 31) { /* Really a 8139. Use internal registers. */ void __iomem *ioaddr = tp->mmio_addr; return location < 8 && mii_2_8139_map[location] ?
RTL_R16 (mii_2_8139_map[location]) : 0;
}
#ifdef CONFIG_8139TOO_8129
mdio_sync (ioaddr); /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
if (tp->chipset >= CH_8139B) { /* Disable magic packet scanning, which is enabled * when PM is enabled in Config1. It can be reenabled
* via ETHTOOL_SWOL if desired. */
RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic);
}
/* make sure RxTx has started */
tmp = RTL_R8 (ChipCmd); if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb)))
RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16 (IntrMask, rtl8139_intr_mask);
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ staticvoid rtl8139_init_ring (struct net_device *dev)
{ struct rtl8139_private *tp = netdev_priv(dev); int i;
tp->cur_rx = 0;
tp->cur_tx = 0;
tp->dirty_tx = 0;
for (i = 0; i < NUM_TX_DESC; i++)
tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
}
/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ staticint next_tick = 3 * HZ;
/* This is a complicated state machine to configure the "twister" for impedance/echos based on the cable length. All of this is magic and undocumented.
*/ switch (tp->twistie) { case 1: if (RTL_R16 (CSCR) & CSCR_LinkOKBit) { /* We have link beat, let us tune the twister. */
RTL_W16 (CSCR, CSCR_LinkDownOffCmd);
tp->twistie = 2; /* Change to state 2. */
next_tick = HZ / 10;
} else { /* Just put in some reasonable defaults for when beat returns. */
RTL_W16 (CSCR, CSCR_LinkDownCmd);
RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */
RTL_W32 (PARA78, PARA78_default);
RTL_W32 (PARA7c, PARA7c_default);
tp->twistie = 0; /* Bail from future actions. */
} break; case 2: /* Read how long it took to hear the echo. */
linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits; if (linkcase == 0x7000)
tp->twist_row = 3; elseif (linkcase == 0x3000)
tp->twist_row = 2; elseif (linkcase == 0x1000)
tp->twist_row = 1; else
tp->twist_row = 0;
tp->twist_col = 0;
tp->twistie = 3; /* Change to state 2. */
next_tick = HZ / 10; break; case 3: /* Put out four tuning parameters, one per 100msec. */ if (tp->twist_col == 0)
RTL_W16 (FIFOTMS, 0);
RTL_W32 (PARA7c, param[(int) tp->twist_row]
[(int) tp->twist_col]);
next_tick = HZ / 10; if (++tp->twist_col >= 4) { /* For short cables we are done.
For long cables (row == 3) check for mistune. */
tp->twistie =
(tp->twist_row == 3) ? 4 : 0;
} break; case 4: /* Special case for long cables: check for mistune. */ if ((RTL_R16 (CSCR) &
CSCR_LinkStatusBits) == 0x7000) {
tp->twistie = 0; break;
} else {
RTL_W32 (PARA7c, 0xfb38de03);
tp->twistie = 5;
next_tick = HZ / 10;
} break; case 5: /* Retune for shorter cable (column 2). */
RTL_W32 (FIFOTMS, 0x20);
RTL_W32 (PARA78, PARA78_default);
RTL_W32 (PARA7c, PARA7c_default);
RTL_W32 (FIFOTMS, 0x00);
tp->twist_row = 2;
tp->twist_col = 0;
tp->twistie = 3;
next_tick = HZ / 10; break;
netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n",
RTL_R8(ChipCmd), RTL_R16(IntrStatus),
RTL_R16(IntrMask), RTL_R8(MediaStatus)); /* Emit info to figure out what went wrong. */
netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n",
tp->cur_tx, tp->dirty_tx); for (i = 0; i < NUM_TX_DESC; i++)
netdev_dbg(dev, "Tx descriptor %d is %08x%s\n",
i, RTL_R32(TxStatus0 + (i * 4)),
i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
tp->xstats.tx_timeouts++;
/* disable Tx ASAP, if not already */
tmp8 = RTL_R8 (ChipCmd); if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, CmdRxEnb);
netdev_lock(dev);
spin_lock_bh(&tp->rx_lock); /* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */
spin_lock_irq(&tp->lock);
rtl8139_tx_clear (tp);
spin_unlock_irq(&tp->lock);
/* Calculate the next Tx descriptor entry. */
entry = tp->cur_tx % NUM_TX_DESC;
/* Note: the chip doesn't have auto-pad! */ if (likely(len < TX_BUF_SIZE)) { if (len < ETH_ZLEN)
memset(tp->tx_buf[entry], 0, ETH_ZLEN);
skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
dev_kfree_skb_any(skb);
} else {
dev_kfree_skb_any(skb);
dev->stats.tx_dropped++; return NETDEV_TX_OK;
}
spin_lock_irqsave(&tp->lock, flags); /* * Writing to TxStatus triggers a DMA transfer of the data * copied to tp->tx_buf[entry] above. Use a memory barrier * to make sure that the device sees the updated data.
*/
wmb();
RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
tp->tx_flag | max(len, (unsignedint)ETH_ZLEN));
tp->cur_tx++;
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
spin_unlock_irqrestore(&tp->lock, flags);
/* only wake the queue if we did work, and the queue is stopped */ if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
mb();
netif_wake_queue (dev);
}
}
/* TODO: clean this up! Rx reset need not be this intensive */ staticvoid rtl8139_rx_err (u32 rx_status, struct net_device *dev, struct rtl8139_private *tp, void __iomem *ioaddr)
{
u8 tmp8; #ifdef CONFIG_8139_OLD_RX_RESET int tmp_work; #endif
netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n",
rx_status);
dev->stats.rx_errors++; if (!(rx_status & RxStatusOK)) { if (rx_status & RxTooLong) {
netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n",
rx_status); /* A.C.: The chip hangs here. */
} if (rx_status & (RxBadSymbol | RxBadAlign))
dev->stats.rx_frame_errors++; if (rx_status & (RxRunt | RxTooLong))
dev->stats.rx_length_errors++; if (rx_status & RxCRCErr)
dev->stats.rx_crc_errors++;
} else {
tp->xstats.rx_lost_in_ring++;
}
/* disable receive */
RTL_W8_F (ChipCmd, CmdTxEnb);
tmp_work = 200; while (--tmp_work > 0) {
udelay(1);
tmp8 = RTL_R8 (ChipCmd); if (!(tmp8 & CmdRxEnb)) break;
} if (tmp_work <= 0)
netdev_warn(dev, "rx stop wait too long\n"); /* restart receive */
tmp_work = 200; while (--tmp_work > 0) {
RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);
udelay(1);
tmp8 = RTL_R8 (ChipCmd); if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) break;
} if (tmp_work <= 0)
netdev_warn(dev, "tx/rx enable wait too long\n");
/* and reinitialize all rx related registers */
RTL_W8_F (Cfg9346, Cfg9346_Unlock); /* Must enable Tx/Rx before setting transfer thresholds! */
RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
/* Packet copy from FIFO still in progress. * Theoretically, this should never happen * since EarlyRx is disabled.
*/ if (unlikely(rx_size == 0xfff0)) { if (!tp->fifo_copy_timeout)
tp->fifo_copy_timeout = jiffies + 2; elseif (time_after(jiffies, tp->fifo_copy_timeout)) {
netdev_dbg(dev, "hung FIFO. Reset\n");
rx_size = 0; goto no_early_rx;
}
netif_dbg(tp, intr, dev, "fifo copy in progress\n");
tp->xstats.early_rx++; break;
}
no_early_rx:
tp->fifo_copy_timeout = 0;
/* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), * Rx process gets reset, so we abort any further * Rx processing.
*/ if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
(rx_size < 8) ||
(!(rx_status & RxStatusOK)))) { if ((dev->features & NETIF_F_RXALL) &&
(rx_size <= (MAX_ETH_FRAME_SIZE + 4)) &&
(rx_size >= 8) &&
(!(rx_status & RxStatusOK))) { /* Length is at least mostly OK, but pkt has * error. I'm hoping we can handle some of these * errors without resetting the chip. --Ben
*/
dev->stats.rx_errors++; if (rx_status & RxCRCErr) {
dev->stats.rx_crc_errors++; goto keep_pkt;
} if (rx_status & RxRunt) {
dev->stats.rx_length_errors++; goto keep_pkt;
}
}
rtl8139_rx_err (rx_status, dev, tp, ioaddr);
received = -1; goto out;
}
keep_pkt: /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */
/* h/w no longer present (hotplug?) or major error, bail */ if (unlikely(status == 0xFFFF)) goto out;
/* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) {
RTL_W16 (IntrMask, 0); goto out;
}
/* Acknowledge all of the current interrupt sources ASAP, but
an first get an additional status bit from CSCR. */ if (unlikely(status & RxUnderrun))
link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
ackstat = status & ~(RxAckBits | TxErr); if (ackstat)
RTL_W16 (IntrStatus, ackstat);
/* Receive packets are processed by poll routine.
If not running start it now. */ if (status & RxAckBits){ if (napi_schedule_prep(&tp->napi)) {
RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
__napi_schedule(&tp->napi);
}
}
/* Check uncommon events with one test. */ if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr)))
rtl8139_weird_interrupt (dev, tp, ioaddr,
status, link_changed);
/* Green! Put the chip in low-power mode. */
RTL_W8 (Cfg9346, Cfg9346_Unlock);
if (rtl_chip_info[tp->chipset].flags & HasHltClk)
RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
return 0;
}
/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and
other threads or interrupts aren't messing with the 8139. */ staticvoid rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{ struct rtl8139_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr;
wol->wolopts = 0; if (cfg3 & Cfg3_LinkUp)
wol->wolopts |= WAKE_PHY; if (cfg3 & Cfg3_Magic)
wol->wolopts |= WAKE_MAGIC; /* (KON)FIXME: See how netdev_set_wol() handles the
following constants. */ if (cfg5 & Cfg5_UWF)
wol->wolopts |= WAKE_UCAST; if (cfg5 & Cfg5_MWF)
wol->wolopts |= WAKE_MCAST; if (cfg5 & Cfg5_BWF)
wol->wolopts |= WAKE_BCAST;
}
spin_unlock_irq(&tp->lock);
}
/* Set the ethtool Wake-on-LAN settings. Return 0 or -errno. Assumes that wol points to kernel memory and other threads or interrupts
aren't messing with the 8139. */ staticint rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{ struct rtl8139_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr;
u32 support;
u8 cfg3, cfg5;
cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF); /* (KON)FIXME: These are untested. We may have to set the CRC0, Wakeup0 and LSBCRC0 registers too, but I have no
documentation. */ if (wol->wolopts & WAKE_UCAST)
cfg5 |= Cfg5_UWF; if (wol->wolopts & WAKE_MCAST)
cfg5 |= Cfg5_MWF; if (wol->wolopts & WAKE_BCAST)
cfg5 |= Cfg5_BWF;
RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */
spin_unlock_irq(&tp->lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.