static int _aligned_io(struct device_area *where, void *buffer, int should_write) { void *bounce; unsigned int block_size = 0; uintptr_t mask; struct device_area widened; if (!(where->dev->flags & DEV_REGULAR) && !_get_block_size(where->dev, &block_size)) return_0; if (!block_size) block_size = lvm_getpagesize(); _widen_region(block_size, where, &widened); /* Do we need to use a bounce buffer? */ mask = block_size - 1; if (!memcmp(where, &widened, sizeof(widened)) && !((uintptr_t) buffer & mask)) return _io(where, buffer, should_write); /* Allocate a bounce buffer with an extra block */ if (!(bounce = alloca((size_t) widened.size + block_size))) { log_error("Bounce buffer alloca failed"); return 0; } /* * Realign start of bounce buffer (using the extra sector) */ if (((uintptr_t) bounce) & mask) bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask); /* channel the io through the bounce buffer */ if (!_io(&widened, bounce, 0)) { if (!should_write) return_0; /* FIXME pre-extend the file */ memset(bounce, '\n', widened.size); } if (should_write) { memcpy(bounce + (where->start - widened.start), buffer, (size_t) where->size); /* ... then we write */ return _io(&widened, bounce, 1); } memcpy(buffer, bounce + (where->start - widened.start), (size_t) where->size); return 1; }
void vpins_io(char port) {Serial.print("OK!");_io(port);}