static int ow_send_command(device_t ndev, device_t pdev, struct ow_cmd *cmd) { int present, i, bit, tries; device_t lldev; struct ow_timing *t; lldev = device_get_parent(ndev); /* * Retry the reset a couple of times before giving up. */ tries = 4; do { OWLL_RESET_AND_PRESENCE(lldev, &timing_regular, &present); if (present == 1) device_printf(ndev, "Reset said no device on bus?.\n"); } while (present == 1 && tries-- > 0); if (present == 1) { device_printf(ndev, "Reset said the device wasn't there.\n"); return ENOENT; /* No devices acked the RESET */ } if (present == -1) { device_printf(ndev, "Reset discovered bus wired wrong.\n"); return ENOENT; } for (i = 0; i < cmd->rom_len; i++) ow_send_byte(lldev, &timing_regular, cmd->rom_cmd[i]); for (i = 0; i < cmd->rom_read_len; i++) ow_read_byte(lldev, &timing_regular, cmd->rom_read + i); if (cmd->xpt_len) { /* * Per AN937, the reset pulse and ROM level are always * done with the regular timings. Certain ROM commands * put the device into overdrive mode for the remainder * of the data transfer, which is why we have to pass the * timings here. Commands that need to be handled like this * are expected to be flagged by the client. */ t = (cmd->flags & OW_FLAG_OVERDRIVE) ? &timing_overdrive : &timing_regular; for (i = 0; i < cmd->xpt_len; i++) ow_send_byte(lldev, t, cmd->xpt_cmd[i]); if (cmd->flags & OW_FLAG_READ_BIT) { memset(cmd->xpt_read, 0, (cmd->xpt_read_len + 7) / 8); for (i = 0; i < cmd->xpt_read_len; i++) { OWLL_READ_DATA(lldev, t, &bit); cmd->xpt_read[i / 8] |= bit << (i % 8); } } else { for (i = 0; i < cmd->xpt_read_len; i++) ow_read_byte(lldev, t, cmd->xpt_read + i); } } return 0; }
void ow_match_rom(uint8_t *rom_value, uint8_t pin) { uint8_t bytes_left = 8; ow_send_byte(OW_ROM_MATCH, pin); while(bytes_left-- > 0) { ow_send_byte(*rom_value++, pin); } }
uint8_t ow_search_rom(uint8_t *bit_pattern, uint8_t last_deviation, uint8_t pin) { uint8_t current_bit = 1; uint8_t new_deviation = 0; uint8_t bit_mask = 0x01; uint8_t bit_a; uint8_t bit_b; ow_send_byte(OW_ROM_SEARCH, pin); while(current_bit <= 64) { bit_a = ow_read_bit(pin); bit_b = ow_read_bit(pin); if(bit_a && bit_b) { return SEARCH_ERROR; } else if(bit_a ^ bit_b) { if(bit_a) { (*bit_pattern) |= bit_mask; } else { (*bit_pattern) &= ~bit_mask; } } else { if(current_bit == last_deviation) { (*bit_pattern) |= bit_mask; } else if(current_bit > last_deviation) { (*bit_pattern) &= ~bit_mask; new_deviation = current_bit; } else if(!(*bit_pattern & bit_mask)) { new_deviation = current_bit; } else { } } if((*bit_pattern) & bit_mask) { ow_write_bit1(pin); } else { ow_write_bit0(pin); } current_bit++; bit_mask <<= 1; if(!bit_mask) { bit_mask = 0x01; bit_pattern++; } } return new_deviation; }