From: Lengyel <sle...@ch...> - 2006-05-24 11:51:57
|
Got it. Thank you. Id=C3=A9zet Vandervliet, Kristian 2006. m=C3=A1jus 24. 10.34 keltez=C3=A9s= =C5=B1 level=C3=A9b=C5=91l: > Lengyel S=C3=A1ndor wrote: > > Thank you for your patience. A few more question. (Using as > > reference serial.c) > > > > It seems that read and write into device has a fixed format: > > > > static int ser_read( void* pNode, void* pCookie, off_t > > nPosition, void* pBuffer, size_t nSize ) > > > > static int ser_write( void* pNode, void* pCookie, off_t > > nPosition, const void* pBuffer, size_t nSize ) > > > > The parameter pNode is clear. It provide a pointer to s > > structure which I registered at driver initialisation. > > pCookie is described, its use is not demonstrated, but I do > > not use it. > > I have the problem with the rest of the parameter. > > > > Receive buffer is allocated during the driver stricture > > (SerPort_s) creation or in some other drivers by the use > > of kmalloc. > > > > It is: > > psPort->sp_anReceiveBuffer > > The index to the next available place in it is also provided: > > psPort->sp_nRecvOutPos > > It's probably best if I describe things in a more general way > rather than talking specifically about the serial driver. It > happens to be one of the drivers I am least familiar with. > > As you note, read() & write() have a fixed form which is the same > for both block and character devices. For a stream device, the > nPosition argument is meaningless and can be ignored. > > The pBuffer argument points to a buffer provided by the caller. > The nSize argument gives the number of bytes the caller would like > to read or write. Depending on the type of I/O (blocking or non- > blocking) the device may or may not process all of nSize bytes. > > Device drivers will also (usually) have their own internal buffer. > This is used to store the data from the device before read() is > called. If you think about the way a generic device works, it > will raise an interrupt when it has recieved new data. The device > has to put this data someplace, so usually has an internal buffer > or the interrupt handler must copy the data in a buffer that has > been kmalloc()'d by the driver for this purpose. > > So, on a call to read() the device driver will usually copy nSize > bytes from it's internal buffer into pBuffer, update a few internal > pointers to help it keep track of it's internal buffer and return. > > > So what is the purpose of assigning: > > ((char*)pBuffer)[nBytesReceived++] =3D > > psPort->sp_anReceiveBuffer[psPort->sp_nRecvOutPos++ % RECV_BUF_SIZE ] > > This is the particular way that the serial driver performs a copy > from it's internal buffer (sp_anReceieveBuffer) to the callers > buffer (pBuffer) > > > What is the significance of "off_t nPosition" and "size_t > > nSize" as compared to psPort->sp_nRecvOutPos and > > psPort->sp_nRecvSize. > > None. nRecvOutPos and nRecvSize are internal house-keeping variables > used to keep track of the serial drivers internal buffer. > nPosition is meaningless (you can't seek on a character device because > it's a stream) and nSize is the amount of data the caller is requesting > in that call to read() > > > What also confuses me that in ser_write pBuffer is used as an already > > allocated buffer provided by the kernel: > > > > ser_out( psPort, UART_TX, ((char*)pBuffer)[i] ); > > and here nSize is the size of this buffer. > > Does this mean that the kernel allocates a fixed size small > > buffer pBuffer, and if you need a larger size, you have to > > allocate one yourself? > > Unless the call to the device driver is coming from inside the kernel, > no. The caller must always allocate a buffer at least nSize bytes > big and pass that buffer in their call to read() > > In psuedo-C, this is how a call to the standard C function read() > works, from the application down: > > [ Application ] > > size_t size =3D 4096; // 4k buffer > void *buffer =3D malloc( size ); > > read( file, buffer, size ); > > > V > [ C library ] > > SYSCALL( read, 3, file, buffer, size ); > > > V > [ VFS (kernel) ] > > File f =3D get_file_from_handle( file ); > void *node =3D f->node; > void *cookie =3D f->cookie; > off_t position =3D f->position; > device =3D node->device; > > device->read( node, cookie, position, buffer, size ); |