Beispiel #1
0
static void hfc_sys_chan_rx_work(void *data)
{
	struct hfc_sys_chan *chan = data;
	struct hfc_card *card = chan->port->card;
	struct hfc_fifo *fifo = &chan->rx_fifo;
	int frame_size;
	struct sk_buff *skb;
	struct { u8 crc[2], stat; } __attribute((packed)) stat;

	hfc_card_lock(card);

	// FIFO selection has to be done for each frame to clear
	// internal buffer (see specs 4.4.4).
	hfc_fifo_select(fifo);

	if (!hfc_fifo_has_frames(fifo))
		goto no_frames;

	// frame_size includes CRC+CRC+STAT
	frame_size = hfc_fifo_get_frame_size(fifo);

	if (frame_size < 3) {
		hfc_debug_sys_chan(chan, 3,
			"invalid frame received, just %d bytes\n",
			frame_size);

		visdn_leg_rx_error(&chan->visdn_chan.leg_b,
				VISDN_RX_ERROR_LENGTH);

		goto err_invalid_frame;
	} else if(frame_size == 3) {
		hfc_debug_sys_chan(chan, 3,
			"empty frame received\n");

		visdn_leg_rx_error(&chan->visdn_chan.leg_b,
				VISDN_RX_ERROR_LENGTH);

		goto err_empty_frame;
	}

	skb = visdn_alloc_skb(frame_size - 3);

	if (!skb) {
		hfc_msg_sys_chan(chan, KERN_ERR,
			"cannot allocate skb: frame dropped\n");

		visdn_leg_rx_error(&chan->visdn_chan.leg_b,
				VISDN_RX_ERROR_DROPPED);

		goto err_alloc_skb;
	}

	hfc_fifo_mem_read(fifo, skb_put(skb, frame_size - 3), frame_size - 3);

	hfc_fifo_mem_read(fifo, &stat, sizeof(stat));

#ifdef DEBUG_CODE
	if(debug_level == 3) {
		hfc_debug_sys_chan(chan, 3, "RX len %2d: ", frame_size);
	} else if(debug_level >= 4) {
		hfc_debug_sys_chan(chan, 4,
			"RX (f1=%02x, f2=%02x, z1(f1)=%04x, z2(f1)=%04x)"
			" len %2d: ",
			fifo->f1, fifo->f2, fifo->z1, fifo->z2,
			frame_size);
	}

	if (debug_level >= 3) {
		int i;
		for (i=0; i<frame_size - 3; i++)
			printk("%02x", ((u8 *)skb->data)[i]);

		printk("%02x%02x %02x\n", stat.crc[0], stat.crc[1], stat.stat);
	}
#endif

	if (stat.stat == 0xff) {
		// Frame abort detected

		hfc_debug_sys_chan(chan, 3, "Frame abort detected\n");

		visdn_leg_rx_error(&chan->visdn_chan.leg_b,
				VISDN_RX_ERROR_FR_ABORT);

		goto err_frame_abort;

	} else if (stat.stat != 0x00) {
		// CRC not ok, frame broken, skipping
		hfc_debug_sys_chan(chan, 2, "Received frame with wrong CRC\n");

		visdn_leg_rx_error(&chan->visdn_chan.leg_b,
				VISDN_RX_ERROR_CRC);

		goto err_crc_error;
	}

	hfc_fifo_next_frame(fifo);

	visdn_leg_frame_xmit(
		&chan->visdn_chan.leg_b,
		skb);

#if 0
	if (chan->connected_e1_chan) {
		struct hfc_led *led =
			&card->leds[chan->connected_e1_chan->port->id];

		led->alt_color = HFC_LED_OFF;
		led->flashing_freq = HZ / 10;
		led->flashes = 1;
		hfc_led_update(led);
	}
#endif

	goto all_went_well;

err_crc_error:
err_frame_abort:
	kfree_skb(skb);
err_alloc_skb:
err_empty_frame:
err_invalid_frame:
	hfc_fifo_drop_frame(fifo);
no_frames:
all_went_well:

	hfc_fifo_refresh_fz_cache(fifo);

	if (hfc_fifo_has_frames(fifo))
		schedule_work(&chan->rx_work);

	hfc_card_unlock(card);
}
Beispiel #2
0
int hfc_fifo_get_frame(struct hfc_chan_simplex *chan, void *data, int max_size)
{
	int frame_size;
	u16 newz2 ;

	if (*chan->f1 == *chan->f2) {
		/*
		 * nothing received, strange uh?
		 */
		printk(KERN_WARNING hfc_DRIVER_PREFIX
			"card %d: "
			"chan %s: "
			"get_frame called with no frame in FIFO.\n",
			chan->chan->card->cardnum,
			chan->chan->name);

		return -1;
	}

	/*
	 * frame_size includes CRC+CRC+STAT
	 */
	frame_size = hfc_fifo_get_frame_size(chan);

#ifdef DEBUG
	if (debug_level == 3) {
		printk(KERN_DEBUG hfc_DRIVER_PREFIX
			"card %d: "
			"chan %s: "
			"RX len %2d: ",
			chan->chan->card->cardnum,
			chan->chan->name,
			frame_size);
	} else if (debug_level >= 4) {
		printk(KERN_DEBUG hfc_DRIVER_PREFIX
			"card %d: "
			"chan %s: "
			"RX (f1=%02x, f2=%02x, z1=%04x, z2=%04x) len %2d: ",
			chan->chan->card->cardnum,
			chan->chan->name,
			*chan->f1, *chan->f2, *Z1_F2(chan), *Z2_F2(chan),
			frame_size);
	}

	if (debug_level >= 3) {
		int i;
		for (i = 0; i < frame_size; i++) {
			printk("%02x", hfc_fifo_u8(chan,
				Z_inc(chan, *Z2_F2(chan), i)));
		}

		printk("\n");
	}
#endif

	if (frame_size <= 0) {
#ifdef DEBUG
		if (debug_level >= 2) {
			printk(KERN_DEBUG hfc_DRIVER_PREFIX
				"card %d: "
				"chan %s: "
				"invalid (empty) frame received.\n",
				chan->chan->card->cardnum,
				chan->chan->name);
		}
#endif

		hfc_fifo_drop_frame(chan);
		return -1;
	}

	/*
	 * STAT is not really received
	 */
	chan->bytes += frame_size - 1;

	/*
	 * Calculate beginning of the next frame
	 */
	newz2 = Z_inc(chan, *Z2_F2(chan), frame_size);

	/*
	 * We cannot use hfc_fifo_get because of different semantic of
	 * "available bytes" and to avoid useless increment of Z2
	 */
	hfc_fifo_mem_read(chan, *Z2_F2(chan), data,
		frame_size < max_size ? frame_size : max_size);

	if (hfc_fifo_u8(chan, Z_inc(chan, *Z2_F2(chan),
		frame_size - 1)) != 0x00) {
		/*
		 * CRC not ok, frame broken, skipping
		 */
#ifdef DEBUG
		if (debug_level >= 2) {
			printk(KERN_WARNING hfc_DRIVER_PREFIX
				"card %d: "
				"chan %s: "
				"Received frame with wrong CRC\n",
				chan->chan->card->cardnum,
				chan->chan->name);
		}
#endif

		chan->crc++;

		hfc_fifo_drop_frame(chan);
		return -1;
	}

	chan->frames++;

	*chan->f2 = F_inc(chan, *chan->f2, 1);

	/*
	 * Set Z2 for the next frame we're going to receive
	 */
	*Z2_F2(chan) = newz2;

	return frame_size;
}