in bridges/vme_tsi148.c [1259:1354]
static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
size_t count, loff_t offset)
{
int retval = 0, enabled;
unsigned long long vme_base, size;
u32 aspace, cycle, dwidth;
void __iomem *addr = image->kern_base + offset;
unsigned int done = 0;
unsigned int count32;
struct vme_error_handler *handler = NULL;
struct vme_bridge *tsi148_bridge;
struct tsi148_driver *bridge;
tsi148_bridge = image->parent;
bridge = tsi148_bridge->driver_priv;
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;
}
}
/* Here we apply for the same strategy we do in master_read
* function in order to assure the correct cycles.
*/
if ((uintptr_t)addr & 0x1) {
iowrite8(*(u8 *)buf, addr);
done += 1;
if (done == count)
goto out;
}
if ((uintptr_t)(addr + done) & 0x2) {
if ((count - done) < 2) {
iowrite8(*(u8 *)(buf + done), addr + done);
done += 1;
goto out;
} else {
iowrite16(*(u16 *)(buf + done), addr + done);
done += 2;
}
}
count32 = (count - done) & ~0x3;
while (done < count32) {
iowrite32(*(u32 *)(buf + done), addr + done);
done += 4;
}
if ((count - done) & 0x2) {
iowrite16(*(u16 *)(buf + done), addr + done);
done += 2;
}
if ((count - done) & 0x1) {
iowrite8(*(u8 *)(buf + done), addr + done);
done += 1;
}
out:
retval = count;
/*
* Writes are posted. We need to do a read on the VME bus to flush out
* all of the writes before we check for errors. We can't guarantee
* that reading the data we have just written is safe. It is believed
* that there isn't any read, write re-ordering, so we can read any
* location in VME space, so lets read the Device ID from the tsi148's
* own registers as mapped into CR/CSR space.
*
* We check for saved errors in the written address range/space.
*/
if (err_chk) {
ioread16(bridge->flush_image->kern_base + 0x7F000);
if (handler->num_errors) {
dev_warn(tsi148_bridge->parent,
"First VME write 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;
}