/* * Read COUNT 8-bit bytes from port PORT into memory starting at * SRC.
*/ void insb (unsignedlong port, void *dst, unsignedlong count)
{ unsignedchar *p;
p = (unsignedchar *)dst;
while (((unsignedlong)p) & 0x3) { if (!count) return;
count--;
*p = inb(port);
p++;
}
while (count >= 4) { unsignedint w;
count -= 4;
w = inb(port) << 24;
w |= inb(port) << 16;
w |= inb(port) << 8;
w |= inb(port);
*(unsignedint *) p = w;
p += 4;
}
while (count) {
--count;
*p = inb(port);
p++;
}
}
/* * Read COUNT 16-bit words from port PORT into memory starting at * SRC. SRC must be at least short aligned. This is used by the * IDE driver to read disk sectors. Performance is important, but * the interfaces seems to be slow: just using the inlined version * of the inw() breaks things.
*/ void insw (unsignedlong port, void *dst, unsignedlong count)
{ unsignedint l = 0, l2; unsignedchar *p;
p = (unsignedchar *)dst;
if (!count) return;
switch (((unsignedlong)p) & 0x3)
{ case 0x00: /* Buffer 32-bit aligned */ while (count>=2) {
count -= 2;
l = cpu_to_le16(inw(port)) << 16;
l |= cpu_to_le16(inw(port));
*(unsignedint *)p = l;
p += 4;
} if (count) {
*(unsignedshort *)p = cpu_to_le16(inw(port));
} break;
case 0x02: /* Buffer 16-bit aligned */
*(unsignedshort *)p = cpu_to_le16(inw(port));
p += 2;
count--; while (count>=2) {
count -= 2;
l = cpu_to_le16(inw(port)) << 16;
l |= cpu_to_le16(inw(port));
*(unsignedint *)p = l;
p += 4;
} if (count) {
*(unsignedshort *)p = cpu_to_le16(inw(port));
} break;
case 0x01: /* Buffer 8-bit aligned */ case 0x03: /* I don't bother with 32bit transfers
* in this case, 16bit will have to do -- DE */
--count;
l = cpu_to_le16(inw(port));
*p = l >> 8;
p++; while (count--)
{
l2 = cpu_to_le16(inw(port));
*(unsignedshort *)p = (l & 0xff) << 8 | (l2 >> 8);
p += 2;
l = l2;
}
*p = l & 0xff; break;
}
}
/* * Read COUNT 32-bit words from port PORT into memory starting at * SRC. Now works with any alignment in SRC. Performance is important, * but the interfaces seems to be slow: just using the inlined version * of the inl() breaks things.
*/ void insl (unsignedlong port, void *dst, unsignedlong count)
{ unsignedint l = 0, l2; unsignedchar *p;
p = (unsignedchar *)dst;
if (!count) return;
switch (((unsignedlong) dst) & 0x3)
{ case 0x00: /* Buffer 32-bit aligned */ while (count--)
{
*(unsignedint *)p = cpu_to_le32(inl(port));
p += 4;
} break;
case 0x02: /* Buffer 16-bit aligned */
--count;
l = cpu_to_le32(inl(port));
*(unsignedshort *)p = l >> 16;
p += 2;
while (count--)
{
l2 = cpu_to_le32(inl(port));
*(unsignedint *)p = (l & 0xffff) << 16 | (l2 >> 16);
p += 4;
l = l2;
}
*(unsignedshort *)p = l & 0xffff; break; case 0x01: /* Buffer 8-bit aligned */
--count;
l = cpu_to_le32(inl(port));
*(unsignedchar *)p = l >> 24;
p++;
*(unsignedshort *)p = (l >> 8) & 0xffff;
p += 2; while (count--)
{
l2 = cpu_to_le32(inl(port));
*(unsignedint *)p = (l & 0xff) << 24 | (l2 >> 8);
p += 4;
l = l2;
}
*p = l & 0xff; break; case 0x03: /* Buffer 8-bit aligned */
--count;
l = cpu_to_le32(inl(port));
*p = l >> 24;
p++; while (count--)
{
l2 = cpu_to_le32(inl(port));
*(unsignedint *)p = (l & 0xffffff) << 8 | l2 >> 24;
p += 4;
l = l2;
}
*(unsignedshort *)p = (l >> 8) & 0xffff;
p += 2;
*p = l & 0xff; break;
}
}
/* * Like insb but in the opposite direction. * Don't worry as much about doing aligned memory transfers: * doing byte reads the "slow" way isn't nearly as slow as * doing byte writes the slow way (no r-m-w cycle).
*/ void outsb(unsignedlong port, constvoid * src, unsignedlong count)
{ constunsignedchar *p;
p = (constunsignedchar *)src; while (count) {
count--;
outb(*p, port);
p++;
}
}
/* * Like insw but in the opposite direction. This is used by the IDE * driver to write disk sectors. Performance is important, but the * interfaces seems to be slow: just using the inlined version of the * outw() breaks things.
*/ void outsw (unsignedlong port, constvoid *src, unsignedlong count)
{ unsignedint l = 0, l2; constunsignedchar *p;
p = (constunsignedchar *)src;
if (!count) return;
switch (((unsignedlong)p) & 0x3)
{ case 0x00: /* Buffer 32-bit aligned */ while (count>=2) {
count -= 2;
l = *(unsignedint *)p;
p += 4;
outw(le16_to_cpu(l >> 16), port);
outw(le16_to_cpu(l & 0xffff), port);
} if (count) {
outw(le16_to_cpu(*(unsignedshort*)p), port);
} break;
case 0x02: /* Buffer 16-bit aligned */
outw(le16_to_cpu(*(unsignedshort*)p), port);
p += 2;
count--;
while (count>=2) {
count -= 2;
l = *(unsignedint *)p;
p += 4;
outw(le16_to_cpu(l >> 16), port);
outw(le16_to_cpu(l & 0xffff), port);
} if (count) {
outw(le16_to_cpu(*(unsignedshort *)p), port);
} break;
case 0x01: /* Buffer 8-bit aligned */ /* I don't bother with 32bit transfers
* in this case, 16bit will have to do -- DE */
l = *p << 8;
p++;
count--; while (count)
{
count--;
l2 = *(unsignedshort *)p;
p += 2;
outw(le16_to_cpu(l | l2 >> 8), port);
l = l2 << 8;
}
l2 = *(unsignedchar *)p;
outw (le16_to_cpu(l | l2>>8), port); break;
}
}
/* * Like insl but in the opposite direction. This is used by the IDE * driver to write disk sectors. Works with any alignment in SRC. * Performance is important, but the interfaces seems to be slow: * just using the inlined version of the outl() breaks things.
*/ void outsl (unsignedlong port, constvoid *src, unsignedlong count)
{ unsignedint l = 0, l2; constunsignedchar *p;
p = (constunsignedchar *)src;
if (!count) return;
switch (((unsignedlong)p) & 0x3)
{ case 0x00: /* Buffer 32-bit aligned */ while (count--)
{
outl(le32_to_cpu(*(unsignedint *)p), port);
p += 4;
} break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.