in bridges/vme_tsi148.c [1173:1256]
static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
size_t count, loff_t offset)
{
int retval, enabled;
unsigned long long vme_base, size;
u32 aspace, cycle, dwidth;
struct vme_error_handler *handler = NULL;
struct vme_bridge *tsi148_bridge;
void __iomem *addr = image->kern_base + offset;
unsigned int done = 0;
unsigned int count32;
tsi148_bridge = image->parent;
spin_lock(&image->lock);
if (err_chk) {
__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace,
&cycle, &dwidth);
handler = vme_register_error_handler(tsi148_bridge, aspace,
vme_base + offset, count);
if (!handler) {
spin_unlock(&image->lock);
return -ENOMEM;
}
}
/* The following code handles VME address alignment. We cannot use
* memcpy_xxx here because it may cut data transfers in to 8-bit
* cycles when D16 or D32 cycles are required on the VME bus.
* On the other hand, the bridge itself assures that the maximum data
* cycle configured for the transfer is used and splits it
* automatically for non-aligned addresses, so we don't want the
* overhead of needlessly forcing small transfers for the entire cycle.
*/
if ((uintptr_t)addr & 0x1) {
*(u8 *)buf = ioread8(addr);
done += 1;
if (done == count)
goto out;
}
if ((uintptr_t)(addr + done) & 0x2) {
if ((count - done) < 2) {
*(u8 *)(buf + done) = ioread8(addr + done);
done += 1;
goto out;
} else {
*(u16 *)(buf + done) = ioread16(addr + done);
done += 2;
}
}
count32 = (count - done) & ~0x3;
while (done < count32) {
*(u32 *)(buf + done) = ioread32(addr + done);
done += 4;
}
if ((count - done) & 0x2) {
*(u16 *)(buf + done) = ioread16(addr + done);
done += 2;
}
if ((count - done) & 0x1) {
*(u8 *)(buf + done) = ioread8(addr + done);
done += 1;
}
out:
retval = count;
if (err_chk) {
if (handler->num_errors) {
dev_err(image->parent->parent,
"First VME read error detected an at address 0x%llx\n",
handler->first_error);
retval = handler->first_error - (vme_base + offset);
}
vme_unregister_error_handler(handler);
}
spin_unlock(&image->lock);
return retval;
}