removed it from its map.
return OK;
}
+#define NR_DMA 16
+
+PRIVATE struct dmatab
+{
+ int dt_flags;
+ endpoint_t dt_proc;
+ phys_bytes dt_base;
+ phys_bytes dt_size;
+ phys_clicks dt_seg_base;
+ phys_clicks dt_seg_size;
+} dmatab[NR_DMA];
+
+#define DTF_INUSE 1
+#define DTF_RELEASE_DMA 2
+#define DTF_RELEASE_SEG 4
+
+PRIVATE endpoint_t iommu_proc_e= ANY;
+
+/*===========================================================================*
+ * do_adddma *
+ *===========================================================================*/
+PUBLIC int do_adddma()
+{
+ endpoint_t req_proc_e, target_proc_e;
+ int i, proc_n;
+ phys_bytes base, size;
+ struct mproc *rmp;
+
+ if (mp->mp_effuid != SUPER_USER)
+ return EPERM;
+
+ req_proc_e= m_in.m_source;
+ target_proc_e= m_in.m2_i1;
+ base= m_in.m2_l1;
+ size= m_in.m2_l2;
+
+ iommu_proc_e= req_proc_e;
+
+ /* Find empty slot */
+ for (i= 0; i<NR_DMA; i++)
+ {
+ if (!(dmatab[i].dt_flags & DTF_INUSE))
+ break;
+ }
+ if (i >= NR_DMA)
+ {
+ printf("pm:do_adddma: dma table full\n");
+ for (i= 0; i<NR_DMA; i++)
+ {
+ printf("%d: flags 0x%x proc %d base 0x%x size 0x%x\n",
+ i, dmatab[i].dt_flags,
+ dmatab[i].dt_proc,
+ dmatab[i].dt_base,
+ dmatab[i].dt_size);
+ }
+ panic(__FILE__, "adddma: table full", NO_NUM);
+ return ENOSPC;
+ }
+
+ /* Find target process */
+ if (pm_isokendpt(target_proc_e, &proc_n) != OK)
+ {
+ printf("pm:do_adddma: endpoint %d not found\n", target_proc_e);
+ return EINVAL;
+ }
+ rmp= &mproc[proc_n];
+ rmp->mp_flags |= HAS_DMA;
+
+ dmatab[i].dt_flags= DTF_INUSE;
+ dmatab[i].dt_proc= target_proc_e;
+ dmatab[i].dt_base= base;
+ dmatab[i].dt_size= size;
+
+ return OK;
+}
+
+/*===========================================================================*
+ * do_deldma *
+ *===========================================================================*/
+PUBLIC int do_deldma()
+{
+ endpoint_t req_proc_e, target_proc_e;
+ int i, j, proc_n;
+ phys_bytes base, size;
+ struct mproc *rmp;
+
+ if (mp->mp_effuid != SUPER_USER)
+ return EPERM;
+
+ req_proc_e= m_in.m_source;
+ target_proc_e= m_in.m2_i1;
+ base= m_in.m2_l1;
+ size= m_in.m2_l2;
+
+ iommu_proc_e= req_proc_e;
+
+ /* Find slot */
+ for (i= 0; i<NR_DMA; i++)
+ {
+ if (!(dmatab[i].dt_flags & DTF_INUSE))
+ continue;
+ if (dmatab[i].dt_proc == target_proc_e &&
+ dmatab[i].dt_base == base &&
+ dmatab[i].dt_size == size)
+ {
+ break;
+ }
+ }
+ if (i >= NR_DMA)
+ {
+ printf("pm:do_deldma: slot not found\n");
+ return ESRCH;
+ }
+
+ if (dmatab[i].dt_flags & DTF_RELEASE_SEG)
+ {
+ /* Check if we have to release the segment */
+ for (j= 0; j<NR_DMA; j++)
+ {
+ if (j == i)
+ continue;
+ if (!(dmatab[j].dt_flags & DTF_INUSE))
+ continue;
+ if (!(dmatab[j].dt_flags & DTF_RELEASE_SEG))
+ continue;
+ if (dmatab[i].dt_proc == target_proc_e)
+ break;
+ }
+ if (j >= NR_DMA)
+ {
+ /* Last segment */
+ free_mem(dmatab[i].dt_seg_base,
+ dmatab[i].dt_seg_size);
+ }
+ }
+
+ dmatab[i].dt_flags &= ~DTF_INUSE;
+
+ return OK;
+}
+
+/*===========================================================================*
+ * do_getdma *
+ *===========================================================================*/
+PUBLIC int do_getdma()
+{
+ endpoint_t req_proc_e, target_proc_e;
+ int i, proc_n;
+ phys_bytes base, size;
+ struct mproc *rmp;
+
+ if (mp->mp_effuid != SUPER_USER)
+ return EPERM;
+
+ req_proc_e= m_in.m_source;
+ iommu_proc_e= req_proc_e;
+
+ /* Find slot to report */
+ for (i= 0; i<NR_DMA; i++)
+ {
+ if (!(dmatab[i].dt_flags & DTF_INUSE))
+ continue;
+ if (!(dmatab[i].dt_flags & DTF_RELEASE_DMA))
+ continue;
+
+ printf("do_getdma: setting reply to 0x%x@0x%x proc %d\n",
+ dmatab[i].dt_size, dmatab[i].dt_base,
+ dmatab[i].dt_proc);
+ mp->mp_reply.m2_i1= dmatab[i].dt_proc;
+ mp->mp_reply.m2_l1= dmatab[i].dt_base;
+ mp->mp_reply.m2_l2= dmatab[i].dt_size;
+
+ return OK;
+ }
+
+ /* Nothing */
+ return EAGAIN;
+}
+
+
+
+/*===========================================================================*
+ * release_dma *
+ *===========================================================================*/
+PUBLIC void release_dma(proc_e, base, size)
+endpoint_t proc_e;
+phys_clicks base;
+phys_clicks size;
+{
+ int i, found_one;;
+
+ found_one= FALSE;
+ for (i= 0; i<NR_DMA; i++)
+ {
+ if (!(dmatab[i].dt_flags & DTF_INUSE))
+ continue;
+ if (dmatab[i].dt_proc != proc_e)
+ continue;
+ dmatab[i].dt_flags |= DTF_RELEASE_DMA | DTF_RELEASE_SEG;
+ dmatab[i].dt_seg_base= base;
+ dmatab[i].dt_seg_size= size;
+ found_one= TRUE;
+ }
+ if (found_one)
+ notify(iommu_proc_e);
+ else
+ free_mem(base, size);
+}
+
#if ENABLE_SWAP
/*===========================================================================*
* swap_on *
if (parent_waiting && right_child) {
tell_parent(rmp); /* tell parent */
} else {
- rmp->mp_flags &= (IN_USE|PRIV_PROC);
+ rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
rmp->mp_flags |= ZOMBIE; /* parent not waiting, zombify child */
sig_proc(p_mp, SIGCHLD); /* send parent a "child died" signal */
}
*/
if ((rmp->mp_flags & (REPLY | ONSWAP | IN_USE | ZOMBIE)) ==
(REPLY | IN_USE)) {
- if ((s=send(rmp->mp_endpoint, &rmp->mp_reply)) != OK) {
- printf("PM can't reply to %d (%s)\n",
- rmp->mp_endpoint, rmp->mp_name);
- panic(__FILE__, "PM can't reply", NO_NUM);
+ s=sendnb(rmp->mp_endpoint, &rmp->mp_reply);
+ if (s != OK) {
+ printf("PM can't reply to %d (%s): %d\n",
+ rmp->mp_endpoint, rmp->mp_name, s);
}
rmp->mp_flags &= ~REPLY;
}
{
int r, proc_e, proc_n;
struct mproc *rmp;
+ phys_clicks base, size;
switch(m_ptr->m_type)
{
free_mem(rmp->mp_seg[T].mem_phys,
rmp->mp_seg[T].mem_len);
}
- /* Free the data and stack segments. */
- free_mem(rmp->mp_seg[D].mem_phys, rmp->mp_seg[S].mem_vir +
- rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
+
+ base= rmp->mp_seg[D].mem_phys;
+ size= rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len -
+ rmp->mp_seg[D].mem_vir;
+
+ if (rmp->mp_flags & HAS_DMA)
+ {
+ /* Delay freeing the memory segmented until the
+ * DMA buffers have been released.
+ */
+ release_dma(rmp->mp_endpoint, base, size);
+ }
+ else
+ {
+ /* Free the data and stack segments. */
+ free_mem(base, size);
+ }
if (m_ptr->m_type == PM_EXIT_REPLY_TR &&
rmp->mp_parent != INIT_PROC_NR)
tell_parent(rmp); /* tell parent */
} else {
/* parent not waiting, zombify child */
- rmp->mp_flags &= (IN_USE|PRIV_PROC);
+ rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
rmp->mp_flags |= ZOMBIE;
/* send parent a "child died" signal */
sig_proc(p_mp, SIGCHLD);
free_mem(rmp->mp_seg[T].mem_phys,
rmp->mp_seg[T].mem_len);
}
- /* Free the data and stack segments. */
- free_mem(rmp->mp_seg[D].mem_phys, rmp->mp_seg[S].mem_vir +
- rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
+
+ base= rmp->mp_seg[D].mem_phys;
+ size= rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len -
+ rmp->mp_seg[D].mem_vir;
+
+ if (rmp->mp_flags & HAS_DMA)
+ {
+ /* Delay freeing the memory segmented until the
+ * DMA buffers have been released.
+ */
+ release_dma(rmp->mp_endpoint, base, size);
+ }
+ else
+ {
+ /* Free the data and stack segments. */
+ free_mem(base, size);
+ }
/* Clean up if the parent has collected the exit
* status
#define PM_SIG_PENDING 0x4000 /* process got a signal while waiting for FS */
#define PARTIAL_EXEC 0x8000 /* Process got a new map but no content */
#define TOLD_PARENT 0x10000 /* Parent wait() completed, ZOMBIE off */
+#define HAS_DMA 0x20000 /* Process directly or indirectly granted
+ * DMA buffers.
+ */
#define NIL_MPROC ((struct mproc *) 0)
_PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks) );
_PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks) );
_PROTOTYPE( void mem_init, (struct memory *chunks, phys_clicks *free) );
+_PROTOTYPE( int do_adddma, (void) );
+_PROTOTYPE( int do_deldma, (void) );
+_PROTOTYPE( int do_getdma, (void) );
+_PROTOTYPE( void release_dma, (endpoint_t proc_e, phys_clicks base,
+ phys_clicks size) );
#if ENABLE_SWAP
_PROTOTYPE( int swap_on, (char *file, u32_t offset, u32_t size) );
_PROTOTYPE( int swap_off, (void) );
/* Miscellaneous */
char core_name[] = "core"; /* file name where core images are produced */
-_PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
+_PROTOTYPE (int (*call_vec[]), (void) ) = {
no_sys, /* 0 = unused */
do_pm_exit, /* 1 = exit */
do_fork, /* 2 = fork */
do_getsysinfo_up,/* 97 = getsysinfo_up */
do_sprofile, /* 98 = sprofile */
do_cprofile, /* 99 = cprofile */
+ no_sys, /* 100 = unused */
+ no_sys, /* 101 = unused */
+ no_sys, /* 102 = unused */
+ no_sys, /* 103 = unused */
+ no_sys, /* 104 = unused */
+ no_sys, /* 105 = unused */
+ no_sys, /* 106 = unused */
+ no_sys, /* 107 = unused */
+ do_adddma, /* 108 = adddma */
+ do_deldma, /* 109 = deldma */
+ do_getdma, /* 110 = getdma */
};
/* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
if ((child=find_proc(m_in.pid))==NIL_MPROC)
return(ESRCH);
+ /* Should check for shared text */
+
+ /* Make sure the text segment is not used as a source for shared
+ * text.
+ */
+ child->mp_ino= 0;
+ child->mp_dev= 0;
+ child->mp_ctime= 0;
+
r= sys_trace(m_in.request,child->mp_endpoint,m_in.taddr,&m_in.data);
if (r != OK) return(r);