#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <asm/byteorder.h>
#include <asm/page.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/pmac_feature.h>
#endif
#include "core.h"
#include "ohci.h"
#include "packet-header-definitions.h"
#include "phy-packet-definitions.h"
#include <trace/events/firewire.h>
static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk);
#define CREATE_TRACE_POINTS
#include <trace/events/firewire_ohci.h>
#define ohci_info(ohci, f, args...) …
#define ohci_notice(ohci, f, args...) …
#define ohci_err(ohci, f, args...) …
#define DESCRIPTOR_OUTPUT_MORE …
#define DESCRIPTOR_OUTPUT_LAST …
#define DESCRIPTOR_INPUT_MORE …
#define DESCRIPTOR_INPUT_LAST …
#define DESCRIPTOR_STATUS …
#define DESCRIPTOR_KEY_IMMEDIATE …
#define DESCRIPTOR_PING …
#define DESCRIPTOR_YY …
#define DESCRIPTOR_NO_IRQ …
#define DESCRIPTOR_IRQ_ERROR …
#define DESCRIPTOR_IRQ_ALWAYS …
#define DESCRIPTOR_BRANCH_ALWAYS …
#define DESCRIPTOR_WAIT …
#define DESCRIPTOR_CMD …
struct descriptor { … } __attribute__((aligned …));
#define CONTROL_SET(regs) …
#define CONTROL_CLEAR(regs) …
#define COMMAND_PTR(regs) …
#define CONTEXT_MATCH(regs) …
#define AR_BUFFER_SIZE …
#define AR_BUFFERS_MIN …
#define AR_BUFFERS …
#define MAX_ASYNC_PAYLOAD …
#define MAX_AR_PACKET_SIZE …
#define AR_WRAPAROUND_PAGES …
struct ar_context { … };
struct context;
descriptor_callback_t;
struct descriptor_buffer { … };
struct context { … };
#define IT_HEADER_SY(v) …
#define IT_HEADER_TCODE(v) …
#define IT_HEADER_CHANNEL(v) …
#define IT_HEADER_TAG(v) …
#define IT_HEADER_SPEED(v) …
#define IT_HEADER_DATA_LENGTH(v) …
struct iso_context { … };
#define CONFIG_ROM_SIZE …
struct fw_ohci { … };
static struct workqueue_struct *selfid_workqueue;
static inline struct fw_ohci *fw_ohci(struct fw_card *card)
{ … }
#define IT_CONTEXT_CYCLE_MATCH_ENABLE …
#define IR_CONTEXT_BUFFER_FILL …
#define IR_CONTEXT_ISOCH_HEADER …
#define IR_CONTEXT_CYCLE_MATCH_ENABLE …
#define IR_CONTEXT_MULTI_CHANNEL_MODE …
#define IR_CONTEXT_DUAL_BUFFER_MODE …
#define CONTEXT_RUN …
#define CONTEXT_WAKE …
#define CONTEXT_DEAD …
#define CONTEXT_ACTIVE …
#define OHCI1394_MAX_AT_REQ_RETRIES …
#define OHCI1394_MAX_AT_RESP_RETRIES …
#define OHCI1394_MAX_PHYS_RESP_RETRIES …
#define OHCI1394_REGISTER_SIZE …
#define OHCI1394_PCI_HCI_Control …
#define SELF_ID_BUF_SIZE …
#define OHCI_TCODE_PHY_PACKET …
#define OHCI_VERSION_1_1 …
static char ohci_driver_name[] = …;
#define PCI_VENDOR_ID_PINNACLE_SYSTEMS …
#define PCI_DEVICE_ID_AGERE_FW643 …
#define PCI_DEVICE_ID_CREATIVE_SB1394 …
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW …
#define PCI_DEVICE_ID_TI_TSB12LV22 …
#define PCI_DEVICE_ID_TI_TSB12LV26 …
#define PCI_DEVICE_ID_TI_TSB82AA2 …
#define PCI_DEVICE_ID_VIA_VT630X …
#define PCI_REV_ID_VIA_VT6306 …
#define PCI_DEVICE_ID_VIA_VT6315 …
#define QUIRK_CYCLE_TIMER …
#define QUIRK_RESET_PACKET …
#define QUIRK_BE_HEADERS …
#define QUIRK_NO_1394A …
#define QUIRK_NO_MSI …
#define QUIRK_TI_SLLZ059 …
#define QUIRK_IR_WAKE …
#define QUIRK_REBOOT_BY_CYCLE_TIMER_READ …
#if IS_ENABLED(CONFIG_X86)
static bool has_reboot_by_cycle_timer_read_quirk(const struct fw_ohci *ohci)
{ … }
#define PCI_DEVICE_ID_ASMEDIA_ASM108X …
static bool detect_vt630x_with_asm1083_on_amd_ryzen_machine(const struct pci_dev *pdev)
{ … }
#else
#define has_reboot_by_cycle_timer_read_quirk …
#define detect_vt630x_with_asm1083_on_amd_ryzen_machine …
#endif
static const struct { … } ohci_quirks[] = …;
static int param_quirks;
module_param_named(quirks, param_quirks, int, 0644);
MODULE_PARM_DESC(…) …;
#define OHCI_PARAM_DEBUG_AT_AR …
#define OHCI_PARAM_DEBUG_SELFIDS …
#define OHCI_PARAM_DEBUG_IRQS …
static int param_debug;
module_param_named(debug, param_debug, int, 0644);
MODULE_PARM_DESC(…) …;
static bool param_remote_dma;
module_param_named(remote_dma, param_remote_dma, bool, 0444);
MODULE_PARM_DESC(…) …;
static void log_irqs(struct fw_ohci *ohci, u32 evt)
{ … }
static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count)
{ … }
static const char *evts[] = …;
static const char *tcodes[] = …;
static void log_ar_at_event(struct fw_ohci *ohci,
char dir, int speed, u32 *header, int evt)
{ … }
static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
{ … }
static inline u32 reg_read(const struct fw_ohci *ohci, int offset)
{ … }
static inline void flush_writes(const struct fw_ohci *ohci)
{ … }
static int read_phy_reg(struct fw_ohci *ohci, int addr)
{ … }
static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
{ … }
static int update_phy_reg(struct fw_ohci *ohci, int addr,
int clear_bits, int set_bits)
{ … }
static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr)
{ … }
static int ohci_read_phy_reg(struct fw_card *card, int addr)
{ … }
static int ohci_update_phy_reg(struct fw_card *card, int addr,
int clear_bits, int set_bits)
{ … }
static inline dma_addr_t ar_buffer_bus(struct ar_context *ctx, unsigned int i)
{ … }
static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
{ … }
static void ar_context_release(struct ar_context *ctx)
{ … }
static void ar_context_abort(struct ar_context *ctx, const char *error_msg)
{ … }
static inline unsigned int ar_next_buffer_index(unsigned int index)
{ … }
static inline unsigned int ar_first_buffer_index(struct ar_context *ctx)
{ … }
static unsigned int ar_search_last_active_buffer(struct ar_context *ctx,
unsigned int *buffer_offset)
{ … }
static void ar_sync_buffers_for_cpu(struct ar_context *ctx,
unsigned int end_buffer_index,
unsigned int end_buffer_offset)
{ … }
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk)
{
return has_be_header_quirk ? (__force __u32)value : le32_to_cpu(value);
}
static bool has_be_header_quirk(const struct fw_ohci *ohci)
{
return !!(ohci->quirks & QUIRK_BE_HEADERS);
}
#else
static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk __maybe_unused)
{ … }
static bool has_be_header_quirk(const struct fw_ohci *ohci)
{ … }
#endif
static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
{ … }
static void *handle_ar_packets(struct ar_context *ctx, void *p, void *end)
{ … }
static void ar_recycle_buffers(struct ar_context *ctx, unsigned int end_buffer)
{ … }
static void ar_context_tasklet(unsigned long data)
{ … }
static int ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci,
unsigned int descriptors_offset, u32 regs)
{ … }
static void ar_context_run(struct ar_context *ctx)
{ … }
static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
{ … }
static void context_tasklet(unsigned long data)
{ … }
static int context_add_buffer(struct context *ctx)
{ … }
static int context_init(struct context *ctx, struct fw_ohci *ohci,
u32 regs, descriptor_callback_t callback)
{ … }
static void context_release(struct context *ctx)
{ … }
static struct descriptor *context_get_descriptors(struct context *ctx,
int z, dma_addr_t *d_bus)
{ … }
static void context_run(struct context *ctx, u32 extra)
{ … }
static void context_append(struct context *ctx,
struct descriptor *d, int z, int extra)
{ … }
static void context_stop(struct context *ctx)
{ … }
struct driver_data { … };
static int at_context_queue_packet(struct context *ctx,
struct fw_packet *packet)
{ … }
static void at_context_flush(struct context *ctx)
{ … }
static int handle_at_packet(struct context *context,
struct descriptor *d,
struct descriptor *last)
{ … }
static u32 get_cycle_time(struct fw_ohci *ohci);
static void handle_local_rom(struct fw_ohci *ohci,
struct fw_packet *packet, u32 csr)
{ … }
static void handle_local_lock(struct fw_ohci *ohci,
struct fw_packet *packet, u32 csr)
{ … }
static void handle_local_request(struct context *ctx, struct fw_packet *packet)
{ … }
static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
{ … }
static void detect_dead_context(struct fw_ohci *ohci,
const char *name, unsigned int regs)
{ … }
static void handle_dead_contexts(struct fw_ohci *ohci)
{ … }
static u32 cycle_timer_ticks(u32 cycle_timer)
{ … }
static u32 get_cycle_time(struct fw_ohci *ohci)
{ … }
static u32 update_bus_time(struct fw_ohci *ohci)
{ … }
static int get_status_for_port(struct fw_ohci *ohci, int port_index,
enum phy_packet_self_id_port_status *status)
{ … }
static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
int self_id_count)
{ … }
static bool initiated_reset(struct fw_ohci *ohci)
{ … }
static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
{ … }
static void bus_reset_work(struct work_struct *work)
{ … }
static irqreturn_t irq_handler(int irq, void *data)
{ … }
static int software_reset(struct fw_ohci *ohci)
{ … }
static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length)
{ … }
static int configure_1394a_enhancements(struct fw_ohci *ohci)
{ … }
static int probe_tsb41ba3d(struct fw_ohci *ohci)
{ … }
static int ohci_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{ … }
static int ohci_set_config_rom(struct fw_card *card,
const __be32 *config_rom, size_t length)
{ … }
static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
{ … }
static void ohci_send_response(struct fw_card *card, struct fw_packet *packet)
{ … }
static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
{ … }
static int ohci_enable_phys_dma(struct fw_card *card,
int node_id, int generation)
{ … }
static u32 ohci_read_csr(struct fw_card *card, int csr_offset)
{ … }
static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value)
{ … }
static void flush_iso_completions(struct iso_context *ctx, enum fw_iso_context_completions_cause cause)
{ … }
static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr)
{ … }
static int handle_ir_packet_per_buffer(struct context *context,
struct descriptor *d,
struct descriptor *last)
{ … }
static int handle_ir_buffer_fill(struct context *context,
struct descriptor *d,
struct descriptor *last)
{ … }
static void flush_ir_buffer_fill(struct iso_context *ctx)
{ … }
static inline void sync_it_packet_for_cpu(struct context *context,
struct descriptor *pd)
{ … }
static int handle_it_packet(struct context *context,
struct descriptor *d,
struct descriptor *last)
{ … }
static void set_multichannel_mask(struct fw_ohci *ohci, u64 channels)
{ … }
static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
int type, int channel, size_t header_size)
{ … }
static int ohci_start_iso(struct fw_iso_context *base,
s32 cycle, u32 sync, u32 tags)
{ … }
static int ohci_stop_iso(struct fw_iso_context *base)
{ … }
static void ohci_free_iso_context(struct fw_iso_context *base)
{ … }
static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels)
{ … }
#ifdef CONFIG_PM
static void ohci_resume_iso_dma(struct fw_ohci *ohci)
{ … }
#endif
static int queue_iso_transmit(struct iso_context *ctx,
struct fw_iso_packet *packet,
struct fw_iso_buffer *buffer,
unsigned long payload)
{ … }
static int queue_iso_packet_per_buffer(struct iso_context *ctx,
struct fw_iso_packet *packet,
struct fw_iso_buffer *buffer,
unsigned long payload)
{ … }
static int queue_iso_buffer_fill(struct iso_context *ctx,
struct fw_iso_packet *packet,
struct fw_iso_buffer *buffer,
unsigned long payload)
{ … }
static int ohci_queue_iso(struct fw_iso_context *base,
struct fw_iso_packet *packet,
struct fw_iso_buffer *buffer,
unsigned long payload)
{ … }
static void ohci_flush_queue_iso(struct fw_iso_context *base)
{ … }
static int ohci_flush_iso_completions(struct fw_iso_context *base)
{ … }
static const struct fw_card_driver ohci_driver = …;
#ifdef CONFIG_PPC_PMAC
static void pmac_ohci_on(struct pci_dev *dev)
{
if (machine_is(powermac)) {
struct device_node *ofn = pci_device_to_OF_node(dev);
if (ofn) {
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
}
}
}
static void pmac_ohci_off(struct pci_dev *dev)
{
if (machine_is(powermac)) {
struct device_node *ofn = pci_device_to_OF_node(dev);
if (ofn) {
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
}
}
}
#else
static inline void pmac_ohci_on(struct pci_dev *dev) { … }
static inline void pmac_ohci_off(struct pci_dev *dev) { … }
#endif
static void release_ohci(struct device *dev, void *data)
{ … }
static int pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{ … }
static void pci_remove(struct pci_dev *dev)
{ … }
#ifdef CONFIG_PM
static int pci_suspend(struct pci_dev *dev, pm_message_t state)
{ … }
static int pci_resume(struct pci_dev *dev)
{ … }
#endif
static const struct pci_device_id pci_table[] = …;
MODULE_DEVICE_TABLE(pci, pci_table);
static struct pci_driver fw_ohci_pci_driver = …;
static int __init fw_ohci_init(void)
{ … }
static void __exit fw_ohci_cleanup(void)
{ … }
module_init(…) …;
module_exit(fw_ohci_cleanup);
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
MODULE_ALIAS(…) …;