diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-01-09 03:57:00 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-01-09 03:57:00 +0000 |
commit | f9d080ddf936154f9b5ebc047645f4de77da8eb6 (patch) | |
tree | 9370c18b15c461a2fb40cd04a84acd05db4562c2 /sys/compat/ndis/subr_ndis.c | |
parent | ab0602c74b5aee253176583786f487da55d66907 (diff) | |
download | FreeBSD-src-f9d080ddf936154f9b5ebc047645f4de77da8eb6.zip FreeBSD-src-f9d080ddf936154f9b5ebc047645f4de77da8eb6.tar.gz |
Implement NdisOpenFile()/NdisCloseFile()/NdisMapFile()/NdisUnmapFile().
By default, we search for files in /compat/ndis. This can be changed with
a systcl. These routines are used by some drivers which need to download
firmware or microcode into their respective devices during initialization.
Also, remove extraneous newlines from the 'built-in' sysctl/registry
variables.
Diffstat (limited to 'sys/compat/ndis/subr_ndis.c')
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 127 |
1 files changed, 121 insertions, 6 deletions
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 73630a3..2b39b04 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -65,6 +65,10 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/queue.h> #include <sys/taskqueue.h> +#include <sys/proc.h> +#include <sys/namei.h> +#include <sys/fcntl.h> +#include <sys/vnode.h> #include <net/if.h> #include <net/if_arp.h> @@ -100,6 +104,10 @@ __FBSDID("$FreeBSD$"); #define FUNC void(*)(void) static struct mtx ndis_interlock; +static char ndis_filepath[MAXPATHLEN]; + +SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, + MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); __stdcall static void ndis_initwrap(ndis_handle, ndis_driver_object *, void *, void *); @@ -272,6 +280,7 @@ ndis_libinit() { mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE | MTX_DUPOK); + strcpy(ndis_filepath, "/compat/ndis"); return(0); } @@ -2323,12 +2332,50 @@ ndis_open_file(status, filehandle, filelength, filename, highestaddr) ndis_physaddr highestaddr; { char *afilename = NULL; - - ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename); - printf("ndis_open_file(\"%s\", %ju)\n", afilename, - highestaddr.np_quad); + struct thread *td = curthread; + struct nameidata nd; + int flags, error; + struct vattr vat; + struct vattr *vap = &vat; + ndis_fh *fh; + char path[MAXPATHLEN]; + + ndis_unicode_to_ascii(filename->nus_buf, + filename->nus_len, &afilename); + + sprintf(path, "%s/%s", ndis_filepath, afilename); free(afilename, M_DEVBUF); - *status = NDIS_STATUS_FILE_NOT_FOUND; + + fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT); + if (fh == NULL) { + *status = NDIS_STATUS_RESOURCES; + return; + } + + mtx_lock(&Giant); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); + + flags = FREAD; + error = vn_open(&nd, &flags, 0, -1); + if (error) { + mtx_unlock(&Giant); + *status = NDIS_STATUS_FILE_NOT_FOUND; + free(fh, M_TEMP); + return; + } + + NDFREE(&nd, NDF_ONLY_PNBUF); + + /* Get the file size. */ + VOP_GETATTR(nd.ni_vp, vap, NOCRED, td); + VOP_UNLOCK(nd.ni_vp, 0, td); + mtx_unlock(&Giant); + + fh->nf_vp = nd.ni_vp; + fh->nf_map = NULL; + *filehandle = fh; + *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF; + *status = NDIS_STATUS_SUCCESS; return; } @@ -2338,8 +2385,46 @@ ndis_map_file(status, mappedbuffer, filehandle) void **mappedbuffer; ndis_handle filehandle; { + ndis_fh *fh; + struct thread *td = curthread; + int error, resid; + + if (filehandle == NULL) { + *status = NDIS_STATUS_FAILURE; + return; + } + + fh = (ndis_fh *)filehandle; + + if (fh->nf_vp == NULL) { + *status = NDIS_STATUS_FAILURE; + return; + } + + if (fh->nf_map != NULL) { + *status = NDIS_STATUS_ALREADY_MAPPED; + return; + } + + fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT); + + if (fh->nf_map == NULL) { + *status = NDIS_STATUS_RESOURCES; + return; + } + + mtx_lock(&Giant); + error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0, + UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); + mtx_unlock(&Giant); + + if (error) + *status = NDIS_STATUS_FAILURE; + else { + *status = NDIS_STATUS_SUCCESS; + *mappedbuffer = fh->nf_map; + } - *status = NDIS_STATUS_ALREADY_MAPPED; return; } @@ -2347,6 +2432,14 @@ __stdcall static void ndis_unmap_file(filehandle) ndis_handle filehandle; { + ndis_fh *fh; + fh = (ndis_fh *)filehandle; + + if (fh->nf_map == NULL) + return; + free(fh->nf_map, M_DEVBUF); + fh->nf_map = NULL; + return; } @@ -2354,6 +2447,28 @@ __stdcall static void ndis_close_file(filehandle) ndis_handle filehandle; { + struct thread *td = curthread; + ndis_fh *fh; + + if (filehandle == NULL) + return; + + fh = (ndis_fh *)filehandle; + if (fh->nf_map != NULL) { + free(fh->nf_map, M_DEVBUF); + fh->nf_map = NULL; + } + + if (fh->nf_vp == NULL) + return; + + mtx_lock(&Giant); + vn_close(fh->nf_vp, FREAD, td->td_ucred, td); + mtx_unlock(&Giant); + + fh->nf_vp = NULL; + free(fh, M_DEVBUF); + return; } |