diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-02-29 20:47:15 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-03-13 19:56:59 -0400 |
commit | 11bf20ad028880a56689f086bfbabfd88b2af38b (patch) | |
tree | e09c2597d61ef8aa989dd2833889004c76d6a058 /drivers | |
parent | ea8d006b91ac58ec5a0862d09e0b629db399517f (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/fw-ohci.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 182be8672dfd..eaa213e21592 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -179,6 +179,7 @@ struct fw_ohci { | |||
179 | int generation; | 179 | int generation; |
180 | int request_generation; | 180 | int request_generation; |
181 | u32 bus_seconds; | 181 | u32 bus_seconds; |
182 | bool old_uninorth; | ||
182 | 183 | ||
183 | /* | 184 | /* |
184 | * Spinlock for accessing fw_ohci data. Never call out of | 185 | * Spinlock for accessing fw_ohci data. Never call out of |
@@ -315,15 +316,22 @@ static int ar_context_add_page(struct ar_context *ctx) | |||
315 | return 0; | 316 | return 0; |
316 | } | 317 | } |
317 | 318 | ||
319 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) | ||
320 | #define cond_le32_to_cpu(v) \ | ||
321 | (ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v)) | ||
322 | #else | ||
323 | #define cond_le32_to_cpu(v) le32_to_cpu(v) | ||
324 | #endif | ||
325 | |||
318 | static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) | 326 | static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) |
319 | { | 327 | { |
320 | struct fw_ohci *ohci = ctx->ohci; | 328 | struct fw_ohci *ohci = ctx->ohci; |
321 | struct fw_packet p; | 329 | struct fw_packet p; |
322 | u32 status, length, tcode; | 330 | u32 status, length, tcode; |
323 | 331 | ||
324 | p.header[0] = le32_to_cpu(buffer[0]); | 332 | p.header[0] = cond_le32_to_cpu(buffer[0]); |
325 | p.header[1] = le32_to_cpu(buffer[1]); | 333 | p.header[1] = cond_le32_to_cpu(buffer[1]); |
326 | p.header[2] = le32_to_cpu(buffer[2]); | 334 | p.header[2] = cond_le32_to_cpu(buffer[2]); |
327 | 335 | ||
328 | tcode = (p.header[0] >> 4) & 0x0f; | 336 | tcode = (p.header[0] >> 4) & 0x0f; |
329 | switch (tcode) { | 337 | switch (tcode) { |
@@ -335,7 +343,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) | |||
335 | break; | 343 | break; |
336 | 344 | ||
337 | case TCODE_READ_BLOCK_REQUEST : | 345 | case TCODE_READ_BLOCK_REQUEST : |
338 | p.header[3] = le32_to_cpu(buffer[3]); | 346 | p.header[3] = cond_le32_to_cpu(buffer[3]); |
339 | p.header_length = 16; | 347 | p.header_length = 16; |
340 | p.payload_length = 0; | 348 | p.payload_length = 0; |
341 | break; | 349 | break; |
@@ -344,7 +352,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) | |||
344 | case TCODE_READ_BLOCK_RESPONSE: | 352 | case TCODE_READ_BLOCK_RESPONSE: |
345 | case TCODE_LOCK_REQUEST: | 353 | case TCODE_LOCK_REQUEST: |
346 | case TCODE_LOCK_RESPONSE: | 354 | case TCODE_LOCK_RESPONSE: |
347 | p.header[3] = le32_to_cpu(buffer[3]); | 355 | p.header[3] = cond_le32_to_cpu(buffer[3]); |
348 | p.header_length = 16; | 356 | p.header_length = 16; |
349 | p.payload_length = p.header[3] >> 16; | 357 | p.payload_length = p.header[3] >> 16; |
350 | break; | 358 | break; |
@@ -361,7 +369,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) | |||
361 | 369 | ||
362 | /* FIXME: What to do about evt_* errors? */ | 370 | /* FIXME: What to do about evt_* errors? */ |
363 | length = (p.header_length + p.payload_length + 3) / 4; | 371 | length = (p.header_length + p.payload_length + 3) / 4; |
364 | status = le32_to_cpu(buffer[length]); | 372 | status = cond_le32_to_cpu(buffer[length]); |
365 | 373 | ||
366 | p.ack = ((status >> 16) & 0x1f) - 16; | 374 | p.ack = ((status >> 16) & 0x1f) - 16; |
367 | p.speed = (status >> 21) & 0x7; | 375 | p.speed = (status >> 21) & 0x7; |
@@ -1026,13 +1034,14 @@ static void bus_reset_tasklet(unsigned long data) | |||
1026 | */ | 1034 | */ |
1027 | 1035 | ||
1028 | self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff; | 1036 | self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff; |
1029 | generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; | 1037 | generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; |
1030 | rmb(); | 1038 | rmb(); |
1031 | 1039 | ||
1032 | for (i = 1, j = 0; j < self_id_count; i += 2, j++) { | 1040 | for (i = 1, j = 0; j < self_id_count; i += 2, j++) { |
1033 | if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) | 1041 | if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) |
1034 | fw_error("inconsistent self IDs\n"); | 1042 | fw_error("inconsistent self IDs\n"); |
1035 | ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]); | 1043 | ohci->self_id_buffer[j] = |
1044 | cond_le32_to_cpu(ohci->self_id_cpu[i]); | ||
1036 | } | 1045 | } |
1037 | rmb(); | 1046 | rmb(); |
1038 | 1047 | ||
@@ -2082,6 +2091,10 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
2082 | pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); | 2091 | pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); |
2083 | pci_set_drvdata(dev, ohci); | 2092 | pci_set_drvdata(dev, ohci); |
2084 | 2093 | ||
2094 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) | ||
2095 | ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE && | ||
2096 | dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW; | ||
2097 | #endif | ||
2085 | spin_lock_init(&ohci->lock); | 2098 | spin_lock_init(&ohci->lock); |
2086 | 2099 | ||
2087 | tasklet_init(&ohci->bus_reset_tasklet, | 2100 | tasklet_init(&ohci->bus_reset_tasklet, |