Subversion Repositories shark

Rev

Rev 2 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Project: S.Ha.R.K.
 *
 * Coordinators:
 *   Giorgio Buttazzo    <giorgio@sssup.it>
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *
 * Authors     :
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
 *   Luca Abeni          <luca@gandalf.sssup.it>
 *   (see the web pages for full authors list)
 *
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
 *
 * http://www.sssup.it
 * http://retis.sssup.it
 * http://shark.sssup.it
 */



/***************************************

  CVS :        $Id: idereq.c,v 1.1.1.1 2002-03-29 14:12:49 pj Exp $
 
  Revision:    $Revision: 1.1.1.1 $

  Last update: $Date: 2002-03-29 14:12:49 $

  This module manage the ide request structure: it is implemented
  a policy for the queueing of the requests made by tasks.

***************************************/


/*
 * Copyright (C) 1999 Massimiliano Giorgi
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#include <fs/assert.h>

#include "glue.h"

#include "ide.h"
#include "idereq.h"

/*
 * if defined:
 * use trc_logevent with event TRC_USER0 to trace head movement
 */
 
#define TRACEMOVEMENT
#undef  TRACEMOVEMENT

#ifdef TRACEMOVEMENT
#include <trace/types.h>
#include <kernel/trace.h>
#endif

/*+ a mutex for the  +*/
//static __b_fastmutex_t mutex;

/*+ a mutex for the "free request" queue manipulation +*/
static __b_fastmutex_t mutexreq;

/*+ the "free request" queue +*/
static int freereq=NIL;

/*+ a pool for the ide request (actually all the ide request structure
  are statically allocated)
  +*/

idereq_t idereq[MAXIDEREQUEST];

/*+ is the queue not blocked? +*/
int notblockedqueue[MAXIDEINTERFACES];

/*++++++++++++++++++++++++++++++++++++++
 
  Initialize this module; must be called prior of other call.
 
  ++++++++++++++++++++++++++++++++++++++*/


void init_idereq(void)
{
  int i;
  //__b_fastmutex_init(&mutex);
  __b_fastmutex_init(&mutexreq);
  freereq=0;
  for (i=0;i<MAXIDEREQUEST;i++) {
    idereq[i].next=((i==MAXIDEREQUEST-1)?NIL:i+1);
    __b_sem_init(&idereq[i].wait,0);
  }
  for (i=0;i<MAXIDEINTERFACES;i++)
    notblockedqueue[i]=1;
}

/*++++++++++++++++++++++++++++++++++++++

  Find and return an ide request structure from the free queue if possible.

  int get_idereq
    return an index into idereq[] or NIL
  ++++++++++++++++++++++++++++++++++++++*/


int get_idereq(void)
{
  int ret;
  __b_fastmutex_lock(&mutexreq);
  if (freereq==NIL)
    ret=NIL;
  else {
    ret=freereq;
    freereq=idereq[ret].next;
  }
  __b_fastmutex_unlock(&mutexreq);
  return ret;
}

/*++++++++++++++++++++++++++++++++++++++

  Insert an ide request structure into the free queue.

  int req
    index into idereq[] to insert into the free queue
  ++++++++++++++++++++++++++++++++++++++*/


void free_idereq(int req)
{
  __b_fastmutex_lock(&mutexreq);
  idereq[req].next=freereq;
  freereq=req;
  __b_fastmutex_unlock(&mutexreq);
}

/*
 * The following functions can be modificated to implement other policy
 * of queueing of the request made by task.
 */


static __inline__ int other_request(int ideif)
{
  return bqueue_numelements(&ide[ideif].queue[0])+
    bqueue_numelements(&ide[ideif].queue[1])?1:0;
}

/*++++++++++++++++++++++++++++++++++++++
 
  Insert an ide request structure into an ide interface struct for
  processing a request.
  It is inserted into the tail.

  int insert_idereq
    return 1 if this is the first request of the queue, 0 if there are
    already other requests into the queue; if 1 is returned the calling
    thread should wake up the server

  int ideif
    interface queue to use (an index into ide[] structure)

  int req
    index into idereq[] of the request struct to insert
  ++++++++++++++++++++++++++++++++++++++*/


int insert_idereq(int ideif, int drive, int req)
{
  int ret;
  bqueue_insertrequest(&ide[ideif].queue[drive],
                       (request_prologue_t *)&idereq[req]
                       );
 
  ret=bqueue_numelements(&ide[ideif].queue[drive]);
  if (ret==1)
    /* means: wake up the server if the queue is not blocked */    
    ret=notblockedqueue[ideif];
  else
    /* means: not wake up the server (it is already running) */
    ret=0;

  return ret;
}

/*++++++++++++++++++++++++++++++++++++++
 
  Release a blocked queue.

  int releasequeue_idereq
    return 1 if there are request in queue, 0 if not

  int ideif
    interface queue to use (an index into ide[] structure)
  ++++++++++++++++++++++++++++++++++++++*/


int releasequeue_idereq(int ideif)
{
  notblockedqueue[ideif]=1;
  return other_request(ideif);
}

int first_idereq(int ideif)
{
  request_prologue_t *ptr;
 
  assertk(ide[ideif].actreq==-1);
 
  //__b_fastmutex_lock(&mutex);
  ptr=bqueue_getrequest(&ide[ideif].queue[0]);
 
  //cprintf("°%p,%p,%li°",ptr,idereq,((idereq_t*)ptr)-idereq);
     
  if (ptr==NULL) {
    ptr=bqueue_getrequest(&ide[ideif].queue[1]);
    if (ptr==NULL) {
      //__b_fastmutex_unlock(&mutex);
      return NIL;
    } else
      ide[ideif].actdrv=1;      
  } else
    ide[ideif].actdrv=0;
  ide[ideif].actreq=((idereq_t*)ptr)-idereq;
  //__b_fastmutex_unlock(&mutex);

#ifdef TRACEMOVEMENT
  {
    long cylinder;
    cylinder=ptr->cylinder;
    trc_logevent(TRC_USER0,&cylinder);
  }
#endif
 
  return ide[ideif].actreq;
}

int actual_idereq(ideif)
{
  assertk(ide[ideif].actreq!=-1);
  return ide[ideif].actreq;
}

/*++++++++++++++++++++++++++++++++++++++
 
  Remove the first request from the queue of an ide interface.

  int remove_idereq
    return 1 if there are other request in queue, 0 if not

  int ideif
    interface queue to use (an index into ide[] structure)

  int req
    index into idereq[] of the request struct to insert
  ++++++++++++++++++++++++++++++++++++++*/


int remove_idereq(int ideif)
{
  assertk(ide[ideif].actreq!=-1);
  bqueue_removerequest(&ide[ideif].queue[ide[ideif].actdrv]);
  ide[ideif].actreq=-1;
  return other_request(ideif)?1:0;
}

/*++++++++++++++++++++++++++++++++++++++
 
  Remove the first request from the queue of an ide interface
  blocking the queue.

  int remove_idereq
    return 1 if there are other request in queue, 0 if not

  int ideif
    interface queue to use (an index into ide[] structure)

  int req
    index into idereq[] of the request struct to insert
  ++++++++++++++++++++++++++++++++++++++*/


int remove_idereq_blocking(int ideif)
{
  assertk(ide[ideif].actreq!=-1);
  bqueue_removerequest(&ide[ideif].queue[ide[ideif].actdrv]);
  notblockedqueue[ideif]=0;
  ide[ideif].actreq=-1;
  return other_request(ideif);
}