static int frescan_hook_frame_sent(const struct can_chip_t *chip);
+static int frescan_hook_frame_aborted(const struct can_chip_t *chip);
+
/**
* frescan_init - initializes the network and the internal structures
*
return -1;
}
- DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set tx and rx hooks\n");
+ DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set tx, rx, abort hooks\n");
ret = ioctl(fd, CAN_IOCTL_SET_TX_HOOK, frescan_hook_frame_sent);
if (ret == -1) {
return -1;
}
+ ret = ioctl(fd, CAN_IOCTL_SET_AB_HOOK, frescan_hook_frame_aborted);
+ if (ret == -1) {
+ ERROR ("ioctl CAN_IOCTL_SET_AB_HOOK failed /dev/can%u\n",
+ params->net);
+ return -1;
+ }
+
DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "init the rest of modules\n");
ret = frescan_data_init(fd, params);
return 0;
};
-
/**
* frescan_hook_frame_sent - frame sent hook
*
packet = the_networks[chip->minor].last_packet;
+ id = frescan_id_get_field(packet->frame->id,
+ FRESCAN_FIELD_FRAG_ID);
+
DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
- "frame sent, minor:%u flags:0x%X\n",
- chip->minor, packet->flags);
+ "frame sent, minor:%u flags:0x%X frag_id:0x%X\n",
+ chip->minor, packet->flags, id);
if (packet->flags & FRESCAN_SS) {
- id = frescan_id_get_field(packet->frame->id,
- FRESCAN_FIELD_FRAG_ID);
-
DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
"calling frame_sent + program repl for id:%u\n", id);
return ret;
}
- // TODO: signal semaphores, server consume budget...
+ // TODO: signal semaphore for send_sync
}
the_networks[chip->minor].last_packet = NULL;
return 0;
};
+
+/**
+ * frescan_hook_frame_aborted - frame frame aborted hook
+ *
+ * This function will be called by the CAN driver's IRQ handler when a frame
+ * is aborted (because another frame with higher priority is waiting). We
+ * have to requeue the frame and update the buffer.
+ */
+
+static int frescan_hook_frame_aborted(const struct can_chip_t *chip)
+{
+ int ret;
+ frescan_packet_t *packet;
+ frescan_prio_queue_t *pqueue;
+ frescan_prio_t prio;
+ frescan_ss_t id;
+
+ packet = the_networks[chip->minor].last_packet;
+
+ id = frescan_id_get_field(packet->frame->id,
+ FRESCAN_FIELD_FRAG_ID);
+
+ DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
+ "frame aborted, minor:%u flags:0x%X frag_id:0x%X\n",
+ chip->minor, packet->flags, id);
+
+ if (packet->flags & FRESCAN_FP) {
+ prio = frescan_id_get_field(packet->frame->id,
+ FRESCAN_FIELD_PRIO);
+
+ DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
+ "requeue fp packet, prio:%u\n", prio);
+
+ pqueue = the_networks[chip->minor].queues.tx_fp_queue;
+ ret = frescan_pqueue_requeue(pqueue, packet, prio);
+ if (ret != 0) {
+ ERROR("could not requeue the packet\n");
+ return -1;
+ }
+ } else if (packet->flags & FRESCAN_SS) {
+ DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
+ "requeue server %u packet\n", id);
+
+ ret = frescan_servers_requeue(chip->minor, id, packet);
+ if (ret != 0) {
+ ERROR("could not requeue the packet\n");
+ return -1;
+ }
+ } else {
+ ERROR("flags are not correct\n");
+ return -1;
+ }
+
+ the_networks[chip->minor].last_packet = NULL;
+
+ ret = frescan_hw_buffer_update(chip->minor);
+ if (ret != 0) {
+ ERROR("could not update hw buffer\n");
+ return -1;
+ }
+
+ return 0;
+}
* buffer of the chip. It is useful to prevent priority inversion when there
* is another packet with highest priority waiting in the frescan queues.
*
- * TODO: implement it
+ * NOTE: if the frame is already being transmitted it won't abort it. In both
+ * cases a IRQ will be raised and either 'frescan_hook_frame_sent' or
+ * 'frescan_hook_frame_aborted' will be called.
*/
int frescan_hw_buffer_abort(frescan_network_t net)
{
-// int ret;
-//
-// ret = ioctl(the_networks[net].fd,
-// CAN_IOCTL_ABORT_FRAME, NULL);
-// if (ret == -1) {
-// ERROR ("could not abort the frame\n");
-// return -1;
-// }
- ERROR ("NOT IMPLEMENTED\n");
- return -1;
+ int ret;
+
+ ret = ioctl(the_networks[net].fd, CAN_IOCTL_ABORT_FRAME, NULL);
+ if (ret == -1) {
+ ERROR ("could not abort the frame\n");
+ return -1;
+ }
+
+ return 0;
}
/**