Ejemplo n.º 1
0
void BaseWedgeI2CBus::moduleRead(unsigned int module, uint8_t address,
                             int offset, int len, uint8_t *buf) {
  CHECK_LE(offset, 255);

  selectQsfp(module);
  CHECK_NE(selectedPort_, NO_PORT);

  // CP2112 uses addresses in the on-the-wire format, while we generally
  // pass them around in Linux standard format.
  address <<= 1;

  // Note that we don't use the writeRead() command, since this
  // locks up the CP2112 chip if it times out.  We perform a separate write,
  // followed by a read.  This releases the I2C bus between operations, but
  // that's okay since there aren't any other master devices on the bus.

  // Also note that we can't read more than 128 bytes at a time.
  dev_.writeByte(address, offset);
  if (len > 128) {
    dev_.read(address, MutableByteRange(buf, 128));
    dev_.writeByte(address, offset + 128);
    dev_.read(address, MutableByteRange(buf + 128, len - 128));
  } else {
    dev_.read(address, MutableByteRange(buf, len));
  }

  unselectQsfp();
}
Ejemplo n.º 2
0
void WedgeI2CBus::verifyBus(bool autoReset) {
  // Make sure the I2C bus is functioning, and reset the CP2112 device if not.
  //
  // Immediately after wedge is powered on, the CP2112 device appears to be in
  // a state where all I2C operations time out.  (It doesn't actually signal
  // anything on the I2C bus.)  Resetting the chip fixes it.
  //
  // We have an AT24C64B EEPROM attached at address 0xa2 which we should always
  // be able to read from successfully.
  uint8_t tmpBuf[8];
  try {
    dev_->read(ADDR_EEPROM, MutableByteRange(tmpBuf, sizeof(tmpBuf)));
  } catch (const UsbError& ex) {
    // The read failed.
    // Reset the device, and then confirm that we can read this time.
    //
    // Note: This can be slightly dangerous for other reasons.  We have seen
    // some 3M QSFP optics that can lock up and hold SDA low forever.  If we
    // reset the CP2112 chip with SDA held low it can't reset successfully,
    // and disappears from the USB bus completely.  (It never re-enumerates.)
    // If the bus is in this state resetting the chip will make it completely
    // inaccessible.
    if (autoReset) {
      try {
        dev_->resetDevice();
      } catch (const UsbDeviceResetError& ex2) {
      }
    } else {
      VLOG(1) << "initial read from CP2112 failed; I2C bus appears hung";
      throw;
    }
  }
}
Ejemplo n.º 3
0
void BaseWedgeI2CBus::moduleWrite(unsigned int module, uint8_t address,
                              int offset, int len, uint8_t *buf) {
  selectQsfp(module);
  CHECK_NE(selectedPort_, NO_PORT);

  // CP2112 uses addresses in the on-the-wire format, while we generally
  // pass them around in Linux standard format.
  address <<= 1;

  // The CP2112 can only write 61 bytes at a time, and we burn one for
  // the offset
  CHECK_LE(len, 60);

  // XXX:  surely there's an easier way to do this?
  uint8_t output[61]; // USB buffer size;
  output[0] = offset;
  memcpy(output + 1, buf, len);
  dev_.write(address, MutableByteRange(output, len + 1));

  unselectQsfp();
}