|
@@ -283,3 +283,42 @@ struct xfer_buffer_operations xferbuf_umalloc_operations = {
|
283
|
283
|
.write = xferbuf_umalloc_write,
|
284
|
284
|
.read = xferbuf_umalloc_read,
|
285
|
285
|
};
|
|
286
|
+
|
|
287
|
+/**
|
|
288
|
+ * Get underlying data transfer buffer
|
|
289
|
+ *
|
|
290
|
+ * @v interface Data transfer interface
|
|
291
|
+ * @ret xferbuf Data transfer buffer, or NULL on error
|
|
292
|
+ *
|
|
293
|
+ * This call will check that the xfer_buffer() handler belongs to the
|
|
294
|
+ * destination interface which also provides xfer_deliver() for this
|
|
295
|
+ * interface.
|
|
296
|
+ *
|
|
297
|
+ * This is done to prevent accidental accesses to a data transfer
|
|
298
|
+ * buffer which may be located behind a non-transparent datapath via a
|
|
299
|
+ * series of pass-through interfaces.
|
|
300
|
+ */
|
|
301
|
+struct xfer_buffer * xfer_buffer ( struct interface *intf ) {
|
|
302
|
+ struct interface *dest;
|
|
303
|
+ xfer_buffer_TYPE ( void * ) *op =
|
|
304
|
+ intf_get_dest_op ( intf, xfer_buffer, &dest );
|
|
305
|
+ void *object = intf_object ( dest );
|
|
306
|
+ struct interface *xfer_deliver_dest;
|
|
307
|
+ struct xfer_buffer *xferbuf;
|
|
308
|
+
|
|
309
|
+ /* Check that this operation is provided by the same interface
|
|
310
|
+ * which handles xfer_deliver().
|
|
311
|
+ */
|
|
312
|
+ intf_get_dest_op ( intf, xfer_deliver, &xfer_deliver_dest );
|
|
313
|
+
|
|
314
|
+ if ( op && ( dest == xfer_deliver_dest ) ) {
|
|
315
|
+ xferbuf = op ( object );
|
|
316
|
+ } else {
|
|
317
|
+ /* Default is to not have a data transfer buffer */
|
|
318
|
+ xferbuf = NULL;
|
|
319
|
+ }
|
|
320
|
+
|
|
321
|
+ intf_put ( xfer_deliver_dest );
|
|
322
|
+ intf_put ( dest );
|
|
323
|
+ return xferbuf;
|
|
324
|
+}
|