+#include "../h/dk.h"
+
+#if VAX780
+char ubasr_bits[] = UBASR_BITS;
+#endif
+
+/*
+ * Do transfer on device argument. The controller
+ * and uba involved are implied by the device.
+ * We queue for resource wait in the uba code if necessary.
+ * We return 1 if the transfer was started, 0 if it was not.
+ * If you call this routine with the head of the queue for a
+ * UBA, it will automatically remove the device from the UBA
+ * queue before it returns. If some other device is given
+ * as argument, it will be added to the request queue if the
+ * request cannot be started immediately. This means that
+ * passing a device which is on the queue but not at the head
+ * of the request queue is likely to be a disaster.
+ */
+ubago(ui)
+ register struct uba_dinfo *ui;
+{
+ register struct uba_minfo *um = ui->ui_mi;
+ register struct uba_hd *uh;
+ register int s, unit;
+
+ uh = &uba_hd[um->um_ubanum];
+ s = spl6();
+ if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu)
+ goto rwait;
+ um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf,
+ UBA_NEEDBDP|UBA_CANTWAIT);
+ if (um->um_ubinfo == 0)
+ goto rwait;
+ uh->uh_users++;
+ if (um->um_driver->ud_xclu)
+ uh->uh_xclu = 1;
+ splx(s);
+ if (ui->ui_dk >= 0) {
+ unit = ui->ui_dk;
+ dk_busy |= 1<<unit;
+ }
+ if (uh->uh_actf == ui)
+ uh->uh_actf = ui->ui_forw;
+ (*um->um_driver->ud_dgo)(um);
+ if (ui->ui_dk >= 0) {
+ dk_xfer[unit]++;
+ dk_wds[unit] += um->um_tab.b_actf->b_bcount>>6;
+ }
+ return (1);
+rwait:
+ if (uh->uh_actf != ui) {
+ ui->ui_forw = NULL;
+ if (uh->uh_actf == NULL)
+ uh->uh_actf = ui;
+ else
+ uh->uh_actl->ui_forw = ui;
+ uh->uh_actl = ui;
+ }
+ splx(s);
+ return (0);
+}
+
+ubadone(um)
+ register struct uba_minfo *um;
+{
+ register struct uba_hd *uh = &uba_hd[um->um_ubanum];
+
+ if (um->um_driver->ud_xclu)
+ uh->uh_xclu = 0;
+ uh->uh_users--;
+ ubarelse(um->um_ubanum, &um->um_ubinfo);
+}