firewire: fw-ohci: Apple UniNorth 1st generation support
Mostly copied from ohci1394.c. Necessary for some older Macs, e.g. PowerBook G3 Pismo and early PowerBook G4 Titanium. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
ea8d006b91
commit
11bf20ad02
|
@ -179,6 +179,7 @@ struct fw_ohci {
|
||||||
int generation;
|
int generation;
|
||||||
int request_generation;
|
int request_generation;
|
||||||
u32 bus_seconds;
|
u32 bus_seconds;
|
||||||
|
bool old_uninorth;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Spinlock for accessing fw_ohci data. Never call out of
|
* Spinlock for accessing fw_ohci data. Never call out of
|
||||||
|
@ -315,15 +316,22 @@ static int ar_context_add_page(struct ar_context *ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
|
||||||
|
#define cond_le32_to_cpu(v) \
|
||||||
|
(ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v))
|
||||||
|
#else
|
||||||
|
#define cond_le32_to_cpu(v) le32_to_cpu(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
|
static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
|
||||||
{
|
{
|
||||||
struct fw_ohci *ohci = ctx->ohci;
|
struct fw_ohci *ohci = ctx->ohci;
|
||||||
struct fw_packet p;
|
struct fw_packet p;
|
||||||
u32 status, length, tcode;
|
u32 status, length, tcode;
|
||||||
|
|
||||||
p.header[0] = le32_to_cpu(buffer[0]);
|
p.header[0] = cond_le32_to_cpu(buffer[0]);
|
||||||
p.header[1] = le32_to_cpu(buffer[1]);
|
p.header[1] = cond_le32_to_cpu(buffer[1]);
|
||||||
p.header[2] = le32_to_cpu(buffer[2]);
|
p.header[2] = cond_le32_to_cpu(buffer[2]);
|
||||||
|
|
||||||
tcode = (p.header[0] >> 4) & 0x0f;
|
tcode = (p.header[0] >> 4) & 0x0f;
|
||||||
switch (tcode) {
|
switch (tcode) {
|
||||||
|
@ -335,7 +343,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCODE_READ_BLOCK_REQUEST :
|
case TCODE_READ_BLOCK_REQUEST :
|
||||||
p.header[3] = le32_to_cpu(buffer[3]);
|
p.header[3] = cond_le32_to_cpu(buffer[3]);
|
||||||
p.header_length = 16;
|
p.header_length = 16;
|
||||||
p.payload_length = 0;
|
p.payload_length = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -344,7 +352,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
|
||||||
case TCODE_READ_BLOCK_RESPONSE:
|
case TCODE_READ_BLOCK_RESPONSE:
|
||||||
case TCODE_LOCK_REQUEST:
|
case TCODE_LOCK_REQUEST:
|
||||||
case TCODE_LOCK_RESPONSE:
|
case TCODE_LOCK_RESPONSE:
|
||||||
p.header[3] = le32_to_cpu(buffer[3]);
|
p.header[3] = cond_le32_to_cpu(buffer[3]);
|
||||||
p.header_length = 16;
|
p.header_length = 16;
|
||||||
p.payload_length = p.header[3] >> 16;
|
p.payload_length = p.header[3] >> 16;
|
||||||
break;
|
break;
|
||||||
|
@ -361,7 +369,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
|
||||||
|
|
||||||
/* FIXME: What to do about evt_* errors? */
|
/* FIXME: What to do about evt_* errors? */
|
||||||
length = (p.header_length + p.payload_length + 3) / 4;
|
length = (p.header_length + p.payload_length + 3) / 4;
|
||||||
status = le32_to_cpu(buffer[length]);
|
status = cond_le32_to_cpu(buffer[length]);
|
||||||
|
|
||||||
p.ack = ((status >> 16) & 0x1f) - 16;
|
p.ack = ((status >> 16) & 0x1f) - 16;
|
||||||
p.speed = (status >> 21) & 0x7;
|
p.speed = (status >> 21) & 0x7;
|
||||||
|
@ -1026,13 +1034,14 @@ static void bus_reset_tasklet(unsigned long data)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
|
self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
|
||||||
generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
|
generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
|
||||||
rmb();
|
rmb();
|
||||||
|
|
||||||
for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
|
for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
|
||||||
if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
|
if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
|
||||||
fw_error("inconsistent self IDs\n");
|
fw_error("inconsistent self IDs\n");
|
||||||
ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]);
|
ohci->self_id_buffer[j] =
|
||||||
|
cond_le32_to_cpu(ohci->self_id_cpu[i]);
|
||||||
}
|
}
|
||||||
rmb();
|
rmb();
|
||||||
|
|
||||||
|
@ -2082,6 +2091,10 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||||
pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
|
pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
|
||||||
pci_set_drvdata(dev, ohci);
|
pci_set_drvdata(dev, ohci);
|
||||||
|
|
||||||
|
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
|
||||||
|
ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
|
||||||
|
dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
|
||||||
|
#endif
|
||||||
spin_lock_init(&ohci->lock);
|
spin_lock_init(&ohci->lock);
|
||||||
|
|
||||||
tasklet_init(&ohci->bus_reset_tasklet,
|
tasklet_init(&ohci->bus_reset_tasklet,
|
||||||
|
|
Loading…
Reference in a new issue