static bool bdbuf_disk_ioctl_process (bdbuf_disk* bdd, rtems_blkdev_request* req) { bool result = true; int b; /* * Perform the requested action. */ switch (bdd->driver_action) { case BDBUF_DISK_NOOP: break; case BDBUF_DISK_WAIT: if (bdd->waiting) bdbuf_test_printf ("disk ioctl: bad waiter: %s:%08x\n", bdd->waiting_name, bdd->waiting); bdd->waiting_name = "bdd"; bdd->waiting = rtems_task_self (); if (bdbuf_disk_unlock (bdd)) result = bdbuf_wait (bdd->name, 0) == RTEMS_SUCCESSFUL; else result = false; /* * Ignore any error if one happens. */ bdbuf_disk_lock (bdd); break; case BDBUF_DISK_SLEEP: bdbuf_test_printf ("disk ioctl: sleeping: %d msecs\n", bdd->driver_sleep); result = bdbuf_sleep (bdd->driver_sleep); break; case BDBUF_DISK_BLOCKS_INORDER: bdbuf_test_printf ("disk ioctl: multi-block order check: count = %d\n", req->bufnum); for (b = 0; b < (req->bufnum - 1); b++) if (req->bufs[b].block >= req->bufs[b + 1].block) bdbuf_test_printf ("disk ioctl: out of order: index:%d (%d >= %d\n", b, req->bufs[b].block, req->bufs[b + 1].block); break; default: bdbuf_test_printf ("disk ioctl: invalid action: %d\n", bdd->driver_action); result = false; break; } return result; }
/** * Set the disk driver action. */ static void bdbuf_set_disk_driver_action (bdbuf_task_control* tc, bdbuf_disk_action action) { /* * Set up a disk action. */ bdbuf_disk_lock (&bdbuf_disks[tc->minor]); bdbuf_disks[tc->minor].driver_action = action; bdbuf_disk_unlock (&bdbuf_disks[tc->minor]); }
/** * Read the block 5 from the disk modify it then release it modified. */ static void bdbuf_tests_task_0_test_3 (bdbuf_task_control* tc) { rtems_status_code sc; bool passed; rtems_bdbuf_buffer* bd; dev_t device; /* * Set task control's passed to false to handle a timeout. */ tc->passed = false; passed = true; device = rtems_filesystem_make_dev_t (tc->major, tc->minor); bdbuf_disk_lock (&bdbuf_disks[tc->minor]); bdbuf_disks[tc->minor].driver_action = BDBUF_DISK_NOOP; bdbuf_disk_unlock (&bdbuf_disks[tc->minor]); /* * Read the buffer and then release it. */ bdbuf_test_printf ("%s: rtems_bdbuf_read[5]: ", tc->name); sc = rtems_bdbuf_read (device, 5, &bd); if ((passed = bdbuf_test_print_sc (sc, true))) { bdbuf_test_printf ("%s: rtems_bdbuf_release_modified[5]: ", tc->name); sc = rtems_bdbuf_release_modified (bd); passed = bdbuf_test_print_sc (sc, true); } /* * Read the buffer again and then just release. The buffer should * be maintained as modified. */ bdbuf_test_printf ("%s: rtems_bdbuf_read[5]: ", tc->name); sc = rtems_bdbuf_read (device, 5, &bd); if ((passed = bdbuf_test_print_sc (sc, true))) { bdbuf_test_printf ("%s: rtems_bdbuf_release[5]: ", tc->name); sc = rtems_bdbuf_release (bd); passed = bdbuf_test_print_sc (sc, true); } /* * Set up a disk watch and wait for the write to happen. */ bdbuf_set_disk_driver_watch (tc, 1); passed = bdbuf_disk_driver_watch_wait (tc, BDBUF_SECONDS (5)); tc->passed = passed; tc->test = 0; }
/** * Clear the disk driver watch. */ static void bdbuf_clear_disk_driver_watch (bdbuf_task_control* tc) { /* * Set up a disk watch and wait for the write to happen. */ bdbuf_disk_lock (&bdbuf_disks[tc->minor]); bdbuf_disks[tc->minor].watcher_name = 0; bdbuf_disks[tc->minor].watcher = 0; bdbuf_disks[tc->minor].watch_count = 0; bdbuf_disk_unlock (&bdbuf_disks[tc->minor]); }
/** * Set up a disk driver watch. */ static void bdbuf_set_disk_driver_watch (bdbuf_task_control* tc, int count) { /* * Set up a disk watch and wait for the write to happen. */ bdbuf_disk_lock (&bdbuf_disks[tc->minor]); bdbuf_disks[tc->minor].watcher_name = tc->name; bdbuf_disks[tc->minor].watcher = tc->task; bdbuf_disks[tc->minor].watch_count = count; bdbuf_disk_unlock (&bdbuf_disks[tc->minor]); }
/** * BDBuf disk IOCTL handler. * * @param dd Disk device. * @param req IOCTL request code. * @param argp IOCTL argument. * @retval The IOCTL return value */ static int bdbuf_disk_ioctl (rtems_disk_device *dd, uint32_t req, void* argp) { rtems_blkdev_request *r = argp; bdbuf_disk *bdd = rtems_disk_get_driver_data (dd); errno = 0; if (!bdbuf_disk_lock (bdd)) { errno = EIO; } else { switch (req) { case RTEMS_BLKIO_REQUEST: switch (r->req) { case RTEMS_BLKDEV_REQ_READ: if (!bdbuf_disk_ioctl_process (bdd, r)) rtems_blkdev_request_done(r, RTEMS_IO_ERROR); else { rtems_blkdev_sg_buffer* sg = r->bufs; uint32_t block = RTEMS_BLKDEV_START_BLOCK (r); uint32_t b; int32_t remains; remains = r->bufnum * bdd->block_size; for (b = 0; b < r->bufnum; b++, block++, sg++) { uint32_t length = sg->length; if (sg->length != bdd->block_size) if (length > bdd->block_size) length = bdd->block_size; memset (sg->buffer, block, length); remains -= length; } rtems_blkdev_request_done (r, RTEMS_SUCCESSFUL); } bdbuf_disk_ioctl_leave (bdd, r->bufnum); break; case RTEMS_BLKDEV_REQ_WRITE: if (!bdbuf_disk_ioctl_process (bdd, r)) rtems_blkdev_request_done(r, RTEMS_IO_ERROR); else rtems_blkdev_request_done(r, RTEMS_SUCCESSFUL); bdbuf_disk_ioctl_leave (bdd, r->bufnum); break; default: errno = EINVAL; break; } break; default: errno = EINVAL; break; } if (!bdbuf_disk_unlock (bdd)) errno = EIO; } return errno == 0 ? 0 : -1; }