Пример #1
0
/*
    At the card level there is no offset manipulation to get to the second port
    on each card. If you would like to pass in a register offset and get the
    appropriate address on a port basis use the fscc_port_* functions.
*/
void fscc_card_get_register_rep(struct fscc_card *card, unsigned bar,
                                unsigned offset, char *buf,
                                unsigned byte_count)
{
    void *address = 0;
    unsigned leftover_count = 0;
    UINT32 incoming_data = 0;
    unsigned chunks = 0;
    unsigned i = 0;

    return_if_untrue(card);
    return_if_untrue(bar <= 2);
    return_if_untrue(buf);
    return_if_untrue(byte_count > 0);

    address = fscc_card_get_BAR(card, bar);
    leftover_count = byte_count % 4;
    chunks = (byte_count - leftover_count) / 4;

    for (i = 0; i < chunks; i++) {
        UINT32 value = 0;

        value = io_read(card, bar, (ULONG *)((char *)address + offset));

        memcpy(&buf[i * 4], &value, sizeof(value));
    }

    if (leftover_count) {
        incoming_data = io_read(card, bar, (ULONG *)((char *)address + offset));

        memmove(buf + (byte_count - leftover_count),
                (char *)(&incoming_data), leftover_count);
    }

#ifdef __BIG_ENDIAN
    {
        unsigned i = 0;

        for (i = 0; i < (int)(byte_count / 2); i++) {
            char first, last;

            first = buf[i];
            last = buf[byte_count - i - 1];

            buf[i] = last;
            buf[byte_count - i - 1] = first;
        }
    }
#endif
}
Пример #2
0
/*
    At the card level there is no offset manipulation to get to the second port
    on each card. If you would like to pass in a register offset and get the
    appropriate address on a port basis use the fscc_port_* functions.
*/
void fscc_card_set_register_rep(struct fscc_card *card, unsigned bar,
                                unsigned offset, const char *data,
                                unsigned byte_count)
{
    void *address = 0;
    unsigned leftover_count = 0;
    unsigned chunks = 0;
    char *reversed_data = 0;
    const char *outgoing_data = 0;
    unsigned i = 0;

    return_if_untrue(card);
    return_if_untrue(bar <= 2);
    return_if_untrue(data);
    return_if_untrue(byte_count > 0);

    address = fscc_card_get_BAR(card, bar);
    leftover_count = byte_count % 4;
    chunks = (byte_count - leftover_count) / 4;

    outgoing_data = data;

#ifdef __BIG_ENDIAN
    {
        unsigned i = 0;

        reversed_data = (char *)ExAllocatePoolWithTag(NonPagedPool, byte_count,
                                                      'ataD');

        for (i = 0; i < byte_count; i++)
            reversed_data[i] = data[byte_count - i - 1];

        outgoing_data = reversed_data;
    }
#endif

    for (i = 0; i < chunks; i++)
        io_write(card, bar, (ULONG *)((char *)address + offset),
                 chars_to_u32(outgoing_data + (i * 4)));

    if (leftover_count)
        io_write(card, bar, (ULONG *)((char *)address + offset),
                 chars_to_u32(outgoing_data + (byte_count - leftover_count)));

    if (reversed_data)
        ExFreePoolWithTag (reversed_data, 'ataD');
}
Пример #3
0
void fscc_frame_delete(struct fscc_frame *frame)
{
    return_if_untrue(frame);

    fscc_frame_update_buffer_size(frame, 0);

    ExFreePoolWithTag(frame, 'marF');
}
Пример #4
0
void oframe_worker(unsigned long data)
{
	struct fscc_port *port = 0;
	int result;

	unsigned long board_flags = 0;
	unsigned long frame_flags = 0;
	unsigned long sent_flags = 0;
	unsigned long queued_flags = 0;

	port = (struct fscc_port *)data;

	return_if_untrue(port);

	spin_lock_irqsave(&port->board_tx_spinlock, board_flags);
	spin_lock_irqsave(&port->pending_oframe_spinlock, frame_flags);

	/* Check if exists and if so, grabs the frame to transmit. */
	if (!port->pending_oframe) {
		spin_lock_irqsave(&port->queued_oframes_spinlock, queued_flags);
		port->pending_oframe = fscc_flist_remove_frame(&port->queued_oframes);
		spin_unlock_irqrestore(&port->queued_oframes_spinlock, queued_flags);

		/* No frames in queue to transmit */
		if (!port->pending_oframe) {
			spin_unlock_irqrestore(&port->pending_oframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_tx_spinlock, board_flags);
			return;
		}
	}

	result = fscc_port_transmit_frame(port, port->pending_oframe);

	if (result == 2) {
		spin_lock_irqsave(&port->sent_oframes_spinlock, sent_flags);
		fscc_flist_add_frame(&port->sent_oframes, port->pending_oframe);
		spin_unlock_irqrestore(&port->sent_oframes_spinlock, sent_flags);

		port->pending_oframe = 0;
	}

	spin_unlock_irqrestore(&port->pending_oframe_spinlock, frame_flags);
	spin_unlock_irqrestore(&port->board_tx_spinlock, board_flags);

	if (result == 2)
		wake_up_interruptible(&port->output_queue);
}
Пример #5
0
void iframe_worker(unsigned long data)
{
	struct fscc_port *port = 0;
	int receive_length = 0; /* Needs to be signed */
	unsigned finished_frame = 0;
	unsigned long board_flags = 0;
	unsigned long frame_flags = 0;
	unsigned long queued_flags = 0;
	static int rejected_last_frame = 0;
	unsigned current_memory = 0;
	unsigned memory_cap = 0;
	unsigned rfcnt = 0;

	port = (struct fscc_port *)data;

	return_if_untrue(port);

	do {
		current_memory = fscc_port_get_input_memory_usage(port);
		memory_cap = fscc_port_get_input_memory_cap(port);

		spin_lock_irqsave(&port->board_rx_spinlock, board_flags);
		spin_lock_irqsave(&port->pending_iframe_spinlock, frame_flags);

		rfcnt = fscc_port_get_RFCNT(port);
		finished_frame = (rfcnt > 0) ? 1 : 0;

		if (finished_frame) {
			unsigned bc_fifo_l = 0;
			unsigned current_length = 0;

			bc_fifo_l = fscc_port_get_register(port, 0, BC_FIFO_L_OFFSET);

			if (port->pending_iframe)
				current_length = fscc_frame_get_length(port->pending_iframe);

			receive_length = bc_fifo_l - current_length;
		} else {
			unsigned rxcnt = 0;

			// Refresh rfcnt, if the frame is now complete, reloop through
			// This prevents the situation where the frame has finished being
			// received between the original rfcnt and now, causing a possible
			// read of a larger byte count than in the actual frame due to
			// another incoming frame
			rxcnt = fscc_port_get_RXCNT(port);
			rfcnt = fscc_port_get_RFCNT(port);

			if (rfcnt) {
				spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
				spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
				break;
			}

			/* We choose a safe amount to read due to more data coming in after we
			   get our values. The rest will be read on the next interrupt. */
			receive_length = max((int)(rxcnt - rxcnt % 4), (int)0);
		}

		if (receive_length <= 0) {
			spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
			return;
		}

		/* Make sure we don't go over the user's memory constraint. */
		if (current_memory + receive_length > memory_cap) {
			if (rejected_last_frame == 0) {
				dev_warn(port->device,
						 "Rejecting frames (memory constraint)\n");
				rejected_last_frame = 1; /* Track that we dropped a frame so we
								don't have to warn the user again. */
			}

			if (port->pending_iframe) {
				fscc_frame_delete(port->pending_iframe);
				port->pending_iframe = 0;
			}

			spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
			return;
		}

		if (!port->pending_iframe) {
			port->pending_iframe = fscc_frame_new(port);

			if (!port->pending_iframe) {
				spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
				spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
				return;
			}
		}

		fscc_frame_add_data_from_port(port->pending_iframe, port, receive_length);

	#ifdef __BIG_ENDIAN
		{
			char status[STATUS_LENGTH];

			/* Moves the status bytes to the end. */
			memmove(&status, port->pending_iframe->data, STATUS_LENGTH);
			memmove(port->pending_iframe->data, port->pending_iframe->data + STATUS_LENGTH, port->pending_iframe->current_length - STATUS_LENGTH);
			memmove(port->pending_iframe->data + port->pending_iframe->current_length - STATUS_LENGTH, &status, STATUS_LENGTH);
		}
	#endif

		dev_dbg(port->device, "F#%i <= %i byte%s (%sfinished)\n",
				port->pending_iframe->number, receive_length,
				(receive_length == 1) ? "" : "s",
				(finished_frame) ? "" : "un");

		if (!finished_frame) {
			spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
			return;
		}

		if (port->pending_iframe) {
#ifdef RELEASE_PREVIEW
			getnstimeofday(&port->pending_iframe->timestamp);
#else
			do_gettimeofday(&port->pending_iframe->timestamp);
#endif
			spin_lock_irqsave(&port->queued_iframes_spinlock, queued_flags);
			fscc_flist_add_frame(&port->queued_iframes, port->pending_iframe);
			spin_unlock_irqrestore(&port->queued_iframes_spinlock, queued_flags);
		}

		rejected_last_frame = 0; /* Track that we received a frame to reset the
									memory constraint warning print message. */

		port->pending_iframe = 0;

		spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
	    spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);

		wake_up_interruptible(&port->input_queue);
	}
	while (receive_length);
}
Пример #6
0
void istream_worker(unsigned long data)
{
	struct fscc_port *port = 0;
	int receive_length = 0; /* Needs to be signed */
	unsigned rxcnt = 0;
	unsigned long board_flags = 0;
	unsigned long stream_flags = 0;
	unsigned current_memory = 0;
	unsigned memory_cap = 0;
	static int rejected_last_stream = 0;
	unsigned status;

	port = (struct fscc_port *)data;

	return_if_untrue(port);

	current_memory = fscc_port_get_input_memory_usage(port);
	memory_cap = fscc_port_get_input_memory_cap(port);

	/* Leave the interrupt handler if we are at our memory cap. */
	if (current_memory >= memory_cap) {
		if (rejected_last_stream == 0) {
			dev_warn(port->device, "Rejecting stream (memory constraint)\n");

			rejected_last_stream = 1; /* Track that we dropped stream data so we
									 don't have to warn the user again. */
		}

		return;
	}

	spin_lock_irqsave(&port->board_rx_spinlock, board_flags);

	rxcnt = fscc_port_get_RXCNT(port);

	/* We choose a safe amount to read due to more data coming in after we
	   get our values. The rest will be read on the next interrupt. */
	receive_length = rxcnt - MAX_LEFTOVER_BYTES;
	receive_length -= receive_length % 4;

	/* Leave the interrupt handler if there is no data to read. */
	if (receive_length <= 0) {
		spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
		return;
	}

	/* Trim the amount to read if there isn't enough memory space to read all
	   of it. */
	if (receive_length + current_memory > memory_cap)
		receive_length = memory_cap - current_memory;

	spin_lock_irqsave(&port->istream_spinlock, stream_flags);
	status = fscc_frame_add_data_from_port(port->istream, port, receive_length);
	spin_unlock_irqrestore(&port->istream_spinlock, stream_flags);
	if (status == 0) {
		dev_err(port->device, "Error adding stream data");
		spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
		return;
	}

	spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);

	rejected_last_stream = 0; /* Track that we received stream data to reset
								 the memory constraint warning print message.
							  */

	dev_dbg(port->device, "Stream <= %i byte%s\n", receive_length,
			(receive_length == 1) ? "" : "s");

	wake_up_interruptible(&port->input_queue);
}