Exemple #1
0
static void _flushData(int fd)
{
   int rd    = 0;
   struct itimerval ti, oti;
   char buf[1024];
   int len = 1023;
   int count = 200;
   usleep(d4RdTimeout);

   /* for error handling in case of timeout */
   timeoutGot = 0;

   /* set errno to 0 in order to get correct informations */
   /* in case of error                                    */
   errno = 0;

   if (debugD4)
     fprintf(stderr, "flush data: length: %i\n", len);
   do
     {
       usleep(d4RdTimeout);
       SET_TIMER(ti,oti, d4RdTimeout);
       rd = read(fd, buf, len);
       if (debugD4)
	 fprintf(stderr, "flush: read: %i %s\n", rd,
		 rd < 0 && errno != 0 ?strerror(errno) : "");
       RESET_TIMER(ti,oti);
       count--;
     } while ( count > 0 && (rd > 0 || (rd < 0 && errno == EAGAIN)));
}
int xfer(uint32_t *data_) {
    uint32_t data = *data_;
    int i;
    //WAIT_WITH_TIMEOUT(!(GBA_IN&(1<<MISO_BIT)), 25600, goto error);
    cli();

    RESET_TIMER();
    for (i=0;i<32;i++) {
        GBA_OUT &= ~((1<<CLK_BIT) | (1<<MOSI_BIT));

        GBA_OUT |= ((data>>31)&1)<<MOSI_BIT;
        WAIT_TIMER();
        GBA_OUT |= (1<<CLK_BIT);

        data<<=1;
        data |= (GBA_IN>>MISO_BIT)&1;
        WAIT_TIMER();
    }

    sei();
    *data_ = data;
    return 0;

    error:
    return -1;
}
Exemple #3
0
int main(int argc, char* argv[]) {
    wp_index* index;

    if(argc < 2) {
        fprintf(stderr, "Usage: %s <filename>+\n", argv[0]);
        return -1;
    }

    DIE_IF_ERROR(wp_index_create(&index, "index"));
    //wp_index_dumpinfo(index, stdout);

    printf("starting...\n");
    unsigned long total_bytes = 0;
    unsigned long chunk_bytes = 0;
    START_TIMER(total);
    START_TIMER(chunk);

    for(int i = 1; i < argc; i++) {
        FILE* f = fopen(argv[i], "r");
        if(f == NULL) {
            fprintf(stderr, "can't open %s: %s\n", argv[i], strerror(errno));
            break;
        }

        uint64_t doc_id;
        wp_entry* entry = wp_entry_new();
        DIE_IF_ERROR(wp_entry_add_file(entry, "body", f));
        DIE_IF_ERROR(wp_index_add_entry(index, entry, &doc_id));
        DIE_IF_ERROR(wp_entry_free(entry));
        fclose(f);

        struct stat fstat;
        stat(argv[i], &fstat);
        total_bytes += fstat.st_size;
        chunk_bytes += fstat.st_size;

        MARK_TIMER(chunk);
        if(TIMER_MS(chunk) > 1000) {
            MARK_TIMER(total);
#define STUFF(k, t) k / 1024, t / 1000.0, ((float)(k) / 1024.0) / ((float)(t) / 1000.0)
            fprintf(stderr, "processed %5luk in %3.1fs = %6.1fk/s. total: %5luk in %5.1fs = %6.1fk/s\n", STUFF(chunk_bytes, TIMER_MS(chunk)), STUFF(total_bytes, TIMER_MS(total)));
            RESET_TIMER(chunk);
            chunk_bytes = 0;
        }
    }
    //po = MMAP_OBJ(segment.postings, postings_list); // may have moved
    //fprintf(stderr, "after: segment has %d docs and %d postings\n", po->num_docs, po->num_postings);

    MARK_TIMER(total);
    fprintf(stderr, "In total, processed %luk in %.1fs = %.1fk/s\n", STUFF(total_bytes, TIMER_MS(total)));

    DIE_IF_ERROR(wp_index_unload(index));
    return 0;
}
Exemple #4
0
int main(int argc, char* argv[]) {
  if(argc < 2) {
    fprintf(stderr, "Usage: %s <filename>+\n", argv[0]);
    return -1;
  }

  fprintf(stderr, "starting...\n");

  new_query = 1;

  unsigned long total_bytes = 0;
  unsigned long chunk_bytes = 0;
  START_TIMER(total);
  START_TIMER(chunk);

  for(int i = 1; i < argc; i++) {
    FILE* f = fopen(argv[i], "r");
    if(f == NULL) {
      fprintf(stderr, "can't open %s: %s\n", argv[i], strerror(errno));
      break;
    }
    parse_file(f);
    fclose(f);

    struct stat fstat;
    stat(argv[i], &fstat);
    total_bytes += fstat.st_size;
    chunk_bytes += fstat.st_size;

    MARK_TIMER(chunk);
    if(TIMER_MS(chunk) > 1000) {
      MARK_TIMER(total);
#define STUFF(k, t) k / 1024, t / 1000.0, ((float)(k) / 1024.0) / ((float)(t) / 1000.0)
      fprintf(stderr, "processed %5luk in %3.1fs = %6.1fk/s. total: %5luk in %5.1fs = %6.1fk/s\n", STUFF(chunk_bytes, TIMER_MS(chunk)), STUFF(total_bytes, TIMER_MS(total)));
      RESET_TIMER(chunk);
      chunk_bytes = 0;
    }
  }

  MARK_TIMER(total);
  fprintf(stderr, "In total, processed %luk in %.1fs = %.1fk/s\n", STUFF(total_bytes, TIMER_MS(total)));

  return 0;
}
Exemple #5
0
static int
ps2cdvd_reset(struct cdrom_device_info *cdi)
{
	unsigned long flags;

	save_flags(flags);
	cli();
	ps2sif_lock(ps2cdvd_lock, "cdvd_reset");
	RESET_TIMER();
#ifdef CONFIG_PS2_SBIOS_VER_CHECK
	if (0x0201 <= sbios(SB_GETVER, NULL))
		ps2cdvdcall_reset();
#else
	ps2cdvdcall_reset();
#endif
	invalidate_discinfo();
	ps2cdvd_state = ps2cdvd_enter(STAT_WAIT_DISC);
	ps2sif_unlock(ps2cdvd_lock);
	restore_flags(flags);
	return 0;
}
Exemple #6
0
static srcentry_t *create_srcentry(u_int32 source)
{
    srcentry_t *node;
    srcentry_t *prev;

    if (search_srclist(source, &prev) == TRUE)
	return prev;

    node = calloc(1, sizeof(srcentry_t));
    if (!node) {
	logit(LOG_WARNING, 0, "Memory allocation error for srcentry %s",
	      inet_fmt(source, s1, sizeof(s1)));
	return NULL;
    }

    node->address = source;
    /* Free the memory if there is error getting the iif and
     * the next hop (upstream) router. */
    if (set_incoming(node, PIM_IIF_SOURCE) == FALSE) {
	free(node);
	return NULL;
    }

    RESET_TIMER(node->timer);
    node->mrtlink = NULL;
    node->cand_rp = NULL;
    node->next	  = prev->next;
    prev->next    = node;
    node->prev    = prev;
    if (node->next)
	node->next->prev = node;

    IF_DEBUG(DEBUG_MFC) {
	logit(LOG_DEBUG, 0, "create source entry, source %s",
	      inet_fmt(source, s1, sizeof(s1)));
    }

    return node;
}
Exemple #7
0
static void
ps2cdvd_cleanup()
{

	DPRINT(DBG_VERBOSE, "cleanup\n");

	ps2sif_lock(ps2cdvd_lock, "cdvd_cleanup");
	RESET_TIMER();

	if (initialized & INIT_LABELBUF) {
		DPRINT(DBG_VERBOSE, "free labelbuf %p\n", labelbuf);
		kfree(labelbuf);
	}

	if (initialized & INIT_DATABUF) {
		DPRINT(DBG_VERBOSE, "free databuf %p\n", ps2cdvd_databufx);
		kfree(ps2cdvd_databufx);
	}

#if 0
	if (initialized & INIT_IOPSIDE) 
		ps2cdvd_cleanupiop();
#endif

	if (initialized & INIT_BLKDEV) {
		DPRINT(DBG_VERBOSE, "unregister block device\n");
		unregister_blkdev(MAJOR_NR, "ps2cdvd");
	}

	if (initialized & INIT_CDROM) {
		DPRINT(DBG_VERBOSE, "unregister cdrom\n");
		unregister_cdrom(&ps2cdvd_info);
	}

	blksize_size[MAJOR_NR] = NULL;

	initialized = 0;
	ps2sif_unlock(ps2cdvd_lock);
}
Exemple #8
0
void init_pim_mrt(void)
{
    /* TODO: delete any existing routing table */

    /* Initialize the source list */
    /* The first entry has address 'INADDR_ANY' and is not used */
    /* The order is the smallest address first. */
    srclist		= (srcentry_t *)calloc(1, sizeof(srcentry_t));
    if (!srclist)
	logit(LOG_ERR, 0, "Ran out of memory in init_pim_mrt()");
    srclist->next       = NULL;
    srclist->prev       = NULL;
    srclist->address	= INADDR_ANY_N;
    srclist->mrtlink    = NULL;
    srclist->incoming   = NO_VIF;
    srclist->upstream   = NULL;
    srclist->metric     = 0;
    srclist->preference = 0;
    RESET_TIMER(srclist->timer);
    srclist->cand_rp    = NULL;

    /* Initialize the group list */
    /* The first entry has address 'INADDR_ANY' and is not used */
    /* The order is the smallest address first. */
    grplist		= (grpentry_t *)calloc(1, sizeof(grpentry_t));
    if (!grplist)
	logit(LOG_ERR, 0, "Ran out of memory in init_pim_mrt()");
    grplist->next       = NULL;
    grplist->prev       = NULL;
    grplist->rpnext     = NULL;
    grplist->rpprev     = NULL;
    grplist->group	= INADDR_ANY_N;
    grplist->rpaddr     = INADDR_ANY_N;
    grplist->mrtlink    = NULL;
    grplist->active_rp_grp = NULL;
    grplist->grp_route   = NULL;
}
Exemple #9
0
static mrtentry_t *alloc_mrtentry(srcentry_t *src, grpentry_t *grp)
{
    mrtentry_t *mrt;
    u_int16 i, *timer;
    u_int8  vif_numbers;

    mrt = calloc(1, sizeof(mrtentry_t));
    if (!mrt) {
	logit(LOG_WARNING, 0, "alloc_mrtentry(): out of memory");
	return NULL;
    }

    /*
     * grpnext, grpprev, srcnext, srcprev will be setup when we link the
     * mrtentry to the source and group chains
     */
    mrt->source  = src;
    mrt->group   = grp;
    mrt->incoming = NO_VIF;
    VIFM_CLRALL(mrt->joined_oifs);
    VIFM_CLRALL(mrt->leaves);
    VIFM_CLRALL(mrt->pruned_oifs);
    VIFM_CLRALL(mrt->asserted_oifs);
    VIFM_CLRALL(mrt->oifs);
    mrt->upstream = NULL;
    mrt->metric = 0;
    mrt->preference = 0;
    mrt->pmbr_addr = INADDR_ANY_N;
#ifdef RSRR
    mrt->rsrr_cache = NULL;
#endif /* RSRR */

    /* XXX: TODO: if we are short in memory, we can reserve as few as possible
     * space for vif timers (per group and/or routing entry), but then everytime
     * when a new interfaces is configured, the router will be restarted and
     * will delete the whole routing table. The "memory is cheap" solution is
     * to reserve timer space for all potential vifs in advance and then no
     * need to delete the routing table and disturb the forwarding.
     */
#ifdef SAVE_MEMORY
    mrt->vif_timers	    = (u_int16 *)calloc(1, sizeof(u_int16) * numvifs);
    mrt->vif_deletion_delay = (u_int16 *)calloc(1, sizeof(u_int16) * numvifs);
    vif_numbers = numvifs;
#else
    mrt->vif_timers	    = (u_int16 *)calloc(1, sizeof(u_int16) * total_interfaces);
    mrt->vif_deletion_delay = (u_int16 *)calloc(1, sizeof(u_int16) * total_interfaces);
    vif_numbers = total_interfaces;
#endif /* SAVE_MEMORY */
    if (!mrt->vif_timers || !mrt->vif_deletion_delay) {
	logit(LOG_WARNING, 0, "alloc_mrtentry(): out of memory");
	FREE_MRTENTRY(mrt);
	return NULL;
    }

    /* Reset the timers */
    for (i = 0, timer = mrt->vif_timers; i < vif_numbers; i++, timer++)
	RESET_TIMER(*timer);

    for (i = 0, timer = mrt->vif_deletion_delay; i < vif_numbers; i++, timer++)
	RESET_TIMER(*timer);

    mrt->flags = MRTF_NEW;
    RESET_TIMER(mrt->timer);
    RESET_TIMER(mrt->jp_timer);
    RESET_TIMER(mrt->rs_timer);
    RESET_TIMER(mrt->assert_timer);
    RESET_TIMER(mrt->assert_rate_timer);
    mrt->kernel_cache = NULL;

    return mrt;
}
Exemple #10
0
static int _readData(int fd, unsigned char *buf, int len)
{
   int rd    = 0;
   int total = 0;
   int toGet = 0;
   unsigned char  header[6];
   struct timeval beg, end;
   long dt;
   struct itimerval ti, oti;

   /* set errno to 0 in order to get correct informations */
   /* in case of error                                    */
   errno = 0;

   /* read the first 6 bytes */
   gettimeofday(&beg, NULL);
   while ( total < 6 )
   {
      SET_TIMER(ti,oti, d4RdTimeout);
      rd = read(fd, header+total, 6-total);
      RESET_TIMER(ti,oti);
      if ( rd <= 0 )
      {
         gettimeofday(&end, NULL);
         dt  = (end.tv_sec  - beg.tv_sec) * 1000;
         dt += (end.tv_usec - beg.tv_usec) / 1000;
         if ( dt > d4RdTimeout*3 )
         {
            if ( debugD4 )
               fprintf(stderr,"Timeout at _readData(), dt = %ld ms\n", dt);
            return -1;
            break;
         }
         continue;
      }
      else
      {
         total += rd;
      }
   }

   if ( debugD4 )
      printHexValues("Recv: ",header,total);

   if ( total == 6 )
   {
      toGet = (header[2] >> 8) + header[3] - 6;
      if (debugD4)
	fprintf(stderr, "toGet: %i\n", toGet);	
      if (toGet > len)
        return -1;
      total = 0;
      gettimeofday(&beg, NULL);
      while ( total < toGet )
      {
         SET_TIMER(ti,oti, d4RdTimeout);
         rd = read(fd, buf+total, toGet-total);
         RESET_TIMER(ti,oti);
         if ( rd <= 0 )
         {
            gettimeofday(&end, NULL);
            dt  = (end.tv_sec  - beg.tv_sec) * 1000;
            dt += (end.tv_usec - beg.tv_usec) / 1000;
            if ( dt > d4RdTimeout*3 )
            {
               if ( debugD4 )
                  fprintf(stderr,"Timeout at _readData(), dt = %ld ms\n",dt);
               return -1;
               break;
            }
            continue;
         }
         else
         {
            total += rd;
         }
      }
      if ( debugD4 )
         printHexValues("Recv: ",buf,total);
      return total;
   }
Exemple #11
0
int readAnswer(int fd, unsigned char *buf, int len)
{
   int rd    = 0;
   int total = 0;
   struct timeval beg, end;
   struct itimerval ti, oti;
   long dt;
   int count = 0;
   int first_read = 1;
   /* wait a little bit before reading an answer */
   usleep(d4RdTimeout);

   /* for error handling in case of timeout */
   timeoutGot = 0;

   /* set errno to 0 in order to get correct informations */
   /* in case of error                                    */
   errno = 0;

   gettimeofday(&beg, NULL);

   if (debugD4)
     fprintf(stderr, "length: %i\n", len);
   while ( total < len )
   {
      SET_TIMER(ti,oti, d4RdTimeout);
      rd = read(fd, buf+total, len-total);
      if (debugD4)
	{
	  if (first_read)
	    {
	      fprintf(stderr, "read: ");
	      first_read = 0;
	    }
	  if (rd < 0)
	    {
	      fprintf(stderr, "%i %s\n", rd, errno != 0 ?strerror(errno) : "");
	      first_read = 1;
	    }
	  else
	    fprintf(stderr, "%i ", rd);
	}
      RESET_TIMER(ti,oti);
      if ( rd <= 0 )
      {
         gettimeofday(&end, NULL);
         dt  = (end.tv_sec  - beg.tv_sec) * 1000;
         dt += (end.tv_usec - beg.tv_usec) / 1000;
         if ( dt > d4RdTimeout * 2 )
         {
            if ( debugD4 )
               fprintf(stderr,"Timeout 1 at readAnswer() rcv %d bytes\n",total);
            timeoutGot = 1;
            break;
         }
         count++;
         if ( count >= 100 )
         {
             timeoutGot = 1;
             if ( rd == 0 )
                errno = -1; /* tell that there is an abnormal condition */
             break;
         }
         errno = 0;
      } else {
         total += rd;
         if ( total > 3 )
         {
            /* the bytes idx 2 and 3 contain the length */
            /* in case of errors this may differ from   */
            /* the expected lenght. Setting len to this */
            /* value will avoid waiting for timeout     */
	    len = (buf[2] << 8) + buf[3];
	    len = (len > sizeof(buf))?sizeof(buf) - 1:len;
         }
      }
      usleep(d4RdTimeout);
   }
   
   if ( debugD4 )
   {
#  if PTIME
      gettimeofday(&end, NULL);
#  endif
      fprintf(stderr, "total: %i\n", total);
      printHexValues("Recv: ",buf,total);
#  if PTIME
      dt = (end.tv_sec  - beg.tv_sec) * 1000000;
      dt += end.tv_usec - beg.tv_usec;
      fprintf(stderr,"Read time %5.3f s\n",(double)dt/1000000);
#  endif
   }
   if ( timeoutGot )
   {
      if ( debugD4 )
         fprintf(stderr,"Timeout 2 at readAnswer()\n");
      return -1;
   }
   return total;
}
Exemple #12
0
static int writeCmd(int fd, unsigned char *cmd, int len)
{
   int w;
   int i = 0;
   struct  itimerval ti, oti;

# if PTIME
   struct timeval beg, end;
   long dt;
# endif
   if ( debugD4 )
   {
      printCmdType(cmd);
# if PTIME
      gettimeofday(&beg, NULL);
# endif
      if ( cmd[0] == 0 && cmd[1] == 0 )
      {
         printHexValues("Send: ", cmd, len);
      }
      else
      {
         printHexValues("Send: ", cmd, 6);
      }
   }

   usleep(1); /* according to Glen Steward, this will solve problems  */
              /* for the cartridge exchange with the Stylus Color 580 */

   timeoutGot = 0;
   errno = 0;
   while ( i < len )
   {
      SET_TIMER(ti,oti,d4WrTimeout);         
      w = SafeWrite(fd, cmd+i,len-i);
      RESET_TIMER(ti,oti);
      if ( w < 0 )
      {
         if ( debugD4 )
         {
	   perror("Write error");
         }
         i= -1;
         break;
      }
      else
         i += w;
   }

   if ( debugD4 )
   {
# if PTIME
      gettimeofday(&end, NULL);
      dt = (end.tv_sec  - beg.tv_sec) * 1000000;
      dt += end.tv_usec - beg.tv_usec;
      fprintf(stderr,"Write time %5.3f s\n",(double)dt/1000000);
# endif
   }

   if ( timeoutGot )
      return -1;
   return i;
}
Exemple #13
0
void
stop_vif(mifi_t vifi)
{
	struct uvif *v;
	struct listaddr *a;
	register pim_nbr_entry_t *n;
	register pim_nbr_entry_t *next;
	struct vif_acl *acl;
 
	/*
	 * TODO: make sure that the kernel viftable is
	 * consistent with the daemon table
	 */
	v = &uvifs[vifi];
	if (!(v->uv_flags & MIFF_REGISTER)) {
		k_leave(pim6_socket, &allpim6routers_group.sin6_addr,
			v->uv_ifindex);
		k_leave(mld6_socket, &allrouters_group.sin6_addr,
			v->uv_ifindex);

		/*
		 * Discard all group addresses.  (No need to tell kernel;
		 * the k_del_vif() call will clean up kernel state.)
		 */
		while (v->uv_groups != NULL) {
			a = v->uv_groups;
			v->uv_groups = a->al_next;

			/* reset all the timers */
			if (a->al_query) {
			    timer_clearTimer(a->al_query);
			}
			if (a->al_comp) {
			    timer_clearTimer(a->al_comp);
			}
			if (a->al_timerid) {
			    timer_clearTimer(a->al_timerid);
			}

			/* frees all the related sources */
			while (a->sources != NULL) {
			    struct listaddr *curr = a->sources;
			    a->sources = a->sources->al_next;
			    free((char *)curr);
			}
			a->sources = NULL;

			/* discard the group */
			free((char *)a);
		}
		v->uv_groups = NULL;
	}

	/*
	 * TODO: inform (eventually) the neighbors I am going down by sending
	 * PIM_HELLO with holdtime=0 so someone else should become a DR.
	 */
	/* TODO: dummy! Implement it!! Any problems if don't use it? */
	delete_vif_from_mrt(vifi);

	/*
	 * Delete the interface from the kernel's vif structure.
	 */
	k_del_vif(mld6_socket, vifi);
	v->uv_flags = (v->uv_flags & ~VIFF_QUERIER & ~VIFF_NONBRS) | VIFF_DOWN;
	if (!(v->uv_flags & MIFF_REGISTER)) {
		RESET_TIMER(v->uv_pim_hello_timer);
		RESET_TIMER(v->uv_jp_timer);
		RESET_TIMER(v->uv_gq_timer);

		for (n = v->uv_pim_neighbors; n != NULL; n = next) {
			/* Free the space for each neighbour */
			next = n->next;
			delete_pim6_nbr(n);
		}
		v->uv_pim_neighbors = NULL;
	}
	if (v->uv_querier != NULL) {
	    free(v->uv_querier);
	    v->uv_querier = NULL;
	}

	/* I/F address list */
	{
	    struct phaddr *pa, *pa_next;
	    for (pa = v->uv_addrs; pa; pa = pa_next) {
		pa_next = pa->pa_next;
		free(pa);
	    }
	}
	v->uv_addrs = NULL;
	v->uv_linklocal = NULL; /* uv_linklocal must be in uv_addrs */

	/* TODO: currently not used */
	/* The Access Control List (list with the scoped addresses) */
	while (v->uv_acl != NULL) {
		acl = v->uv_acl;
		v->uv_acl = acl->acl_next;
		free((char *)acl);
	}

	vifs_down = TRUE;

	IF_DEBUG(DEBUG_IF)
		log_msg(LOG_DEBUG, 0, "%s goes down, vif #%u out of service",
			v->uv_name, vifi);
}
Exemple #14
0
static void
ps2cdvd_state_machine(struct ps2cdvd_event* ev)
{
	unsigned long flags;
	int old_state = ps2cdvd_state;
	int new_state = ps2cdvd_state;
	struct sbr_common_arg *carg = ev->arg;

	DPRINT(DBG_STATE, "state: %s event: %s\n",
	       ps2cdvd_getstatestr(old_state),
	       ps2cdvd_geteventstr(ev->type));

	save_flags(flags);
	cli();

	switch (ps2cdvd_state) {
	case STAT_WAIT_DISC:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    if (ps2cdvd_lowlevel_lock() < 0) {
	      /* waiting for unlock... */
	      RESET_TIMER();
	      SET_TIMER(HZ * ps2cdvd_check_interval);
	    } else {
	      new_state = STAT_INIT_TRAYSTAT;
	    }
	    break;
	  case EV_INTR:
	  }
	  break;
	case STAT_INIT_TRAYSTAT:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    {
	      if (carg->result != 0) {
		new_state = STAT_WAIT_DISC;
	      } else {
		new_state = STAT_CHECK_DISCTYPE;
	      }
	    }
	    break;
	  }
	  break;
	case STAT_CHECK_DISCTYPE:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    disc_type = carg->result;
	    DPRINT(DBG_INFO, "ps2cdvd_getdisctype()='%s', %d\n",
		   ps2cdvd_getdisctypestr(disc_type), disc_type);
	    switch (disc_type) {
	    case SCECdPS2CDDA:		/* PS2 CD DA */
	    case SCECdPS2CD:		/* PS2 CD */
	    case SCECdPSCDDA:		/* PS CD DA */
	    case SCECdPSCD:		/* PS CD */
	    case SCECdCDDA:		/* CD DA */
	    case SCECdPS2DVD:		/* PS2 DVD */
	    case SCECdDVDV:		/* DVD video */
	      new_state = STAT_INIT_CHECK_READY;
	      break;
	    case SCECdDETCTDVDD:	/* DVD-dual detecting */
	    case SCECdDETCTDVDS:	/* DVD-single detecting */
	    case SCECdDETCTCD:		/* CD detecting */
	    case SCECdDETCT:		/* detecting */
	    case SCECdNODISC:		/* no disc */
	      new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
	      break;
	    case SCECdIllgalMedia:	/* illegal media */
	    case SCECdUNKNOWN:		/* unknown */
	      printk(KERN_CRIT "ps2cdvd: illegal media\n");
	      new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
	      break;
	    }
	    break;
	  }
	  break;
	case STAT_INIT_CHECK_READY:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    prev_read = jiffies;
	    if (carg->result == SCECdComplete) {
	      switch (disc_type) {
	      case SCECdPS2CDDA:	/* PS2 CD DA */
	      case SCECdPS2CD:		/* PS2 CD */
	      case SCECdPSCDDA:		/* PS CD DA */
	      case SCECdPSCD:		/* PS CD */
	      case SCECdCDDA:		/* CD DA */
		new_state = STAT_TOC_READ;
		media_mode = SCECdCD;
		break;
	      case SCECdPS2DVD:		/* PS2 DVD */
	      case SCECdDVDV:		/* DVD video */
		new_state = STAT_SET_MMODE;
		media_mode = SCECdDVD;
		break;
	      default:
		printk(KERN_CRIT "ps2cdvd: internal error at %s(%d)\n",
		       __FILE__, __LINE__);
		new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
		break;
	      }
	    } else {
	      new_state = STAT_WAIT_DISC;
	    }
	    break;
	  }
	  break;
	case STAT_TOC_READ:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    if (carg->result < 0) {
	      DPRINT(DBG_DIAG, "gettoc() failed\n");
	      new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
	    } else {
	      struct ps2cdvd_tocentry *toc;

	      toc_valid = 1;
	      toc = (struct ps2cdvd_tocentry *)tocbuf;
	      leadout_start = msftolba(decode_bcd(toc[2].abs_msf[0]),
				       decode_bcd(toc[2].abs_msf[1]),
				       decode_bcd(toc[2].abs_msf[2]));
#ifdef PS2CDVD_DEBUG
	      if (ps2cdvd_debug & DBG_INFO) {
		struct sbr_cdvd_gettoc_arg *arg = carg->arg;
		if (arg->media == 0) {
		  ps2cdvd_tocdump(DBG_LOG_LEVEL "ps2cdvd: ",
				  (struct ps2cdvd_tocentry *)tocbuf);
		} else {
		  /*
		   * we have no interrest in DVD Physical format information
		   ps2cdvd_hexdump(tocbuf, len);
		  */
		}
	      }
#endif
	      new_state = STAT_SET_MMODE;
	    }
	    break;
	  }
	  break;
	case STAT_SET_MMODE:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    if (carg->result == 0) {
	      DPRINT(DBG_DIAG, "set_mmode() failed\n");
	      new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
	    } else {
	      switch (disc_type) {
	      case SCECdPS2DVD:		/* PS2 DVD */
	      case SCECdPS2CDDA:		/* PS2 CD DA */
	      case SCECdPS2CD:		/* PS2 CD */
	      case SCECdPSCDDA:		/* PS CD DA */
	      case SCECdPSCD:		/* PS CD */
		new_state = STAT_LABEL_READ;
		break;
	      case SCECdDVDV:		/* DVD video */
	      case SCECdCDDA:		/* CD DA */
		if (disc_locked && disc_lock_key_valid) {
		  new_state = STAT_LABEL_READ;
		} else {
		  disc_changed++;
		  new_state = STAT_READY;
		}
		break;
	      default:
		printk(KERN_CRIT "ps2cdvd: internal error at %s(%d)\n",
		       __FILE__, __LINE__);
		new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
		break;
	      }
	      break;
	    }
	  }
	  break;
	case STAT_LABEL_READ:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    new_state = STAT_LABEL_READ_ERROR_CHECK;
	    break;
	  }
	  break;
	case STAT_LABEL_READ_ERROR_CHECK:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    if (carg->result != SCECdErNO) {
	      DPRINT(DBG_DIAG, "error: %s, code=0x%02x\n",
		     ps2cdvd_geterrorstr(carg->result),
		     carg->result);
	      if (disc_locked && disc_lock_key_valid) {
		printk(KERN_CRIT "ps2cdvd: =============================\n");
		printk(KERN_CRIT "ps2cdvd:          wrong disc.         \n");
		printk(KERN_CRIT "ps2cdvd: =============================\n");
		if (!ps2cdvd_wrong_disc_retry) {
		  INIT_REQUEST;
		  while (CURRENT)
		    end_request(0);
		  disc_changed++;
		}
	      }
	      new_state = disc_locked ? STAT_INVALID_DISC : STAT_WAIT_DISC;
	    } else {
	      unsigned long sum;
#ifdef PS2CDVD_DEBUG
	      struct iso_primary_descriptor *label;
	      label = (struct iso_primary_descriptor*)labelbuf;

	      if (ps2cdvd_debug & DBG_INFO) {
		printk(DBG_LOG_LEVEL "ps2cdvd: ");
		print_isofsstr(label->system_id, sizeof(label->system_id));
		print_isofsstr(label->volume_id, sizeof(label->volume_id));
		print_isofsstr(label->volume_set_id,
			       sizeof(label->volume_set_id));
		print_isofsstr(label->publisher_id,
			       sizeof(label->publisher_id));
		print_isofsstr(label->application_id,
			       sizeof(label->application_id));
		printk("\n");

		/* ps2cdvd_hexdump(DBG_LOG_LEVEL "ps2cdvd: ", labelbuf, 2048);
		 */
	      }
#endif
	      label_valid = 1;
	      DPRINT(DBG_DLOCK, "label is valid\n");
	      sum = checksum((u_long*)labelbuf, 2048/sizeof(u_long));
	      if (disc_lock_key_valid &&
		  disc_locked &&
		  disc_lock_key != sum) {
		printk(KERN_CRIT "ps2cdvd: =============================\n");
		printk(KERN_CRIT "ps2cdvd:          wrong disc.         \n");
		printk(KERN_CRIT "ps2cdvd: =============================\n");
		if (!ps2cdvd_wrong_disc_retry) {
		  INIT_REQUEST;
		  while (CURRENT)
		    end_request(0);
		  disc_changed++;
		}
		new_state = STAT_INVALID_DISC;
	      } else {
		disc_lock_key = sum;
		if (!disc_lock_key_valid && disc_locked) {
		  DPRINT(DBG_DLOCK, "disc lock key=%lX\n", sum);
		}
		disc_lock_key_valid = 1;
		new_state = STAT_READY;
	      }
	    }
	    break;
	  }
	  break;
	case STAT_READY:
	  switch (ev->type) {
	  case EV_TICK:
	    if (CURRENT == NULL || ps2sif_iswaiting(ps2cdvd_lock)) {
	      break;
	    }
	    /* fall through */
	  case EV_START:
	  case EV_TIMEOUT:
	    if (ps2cdvd_lowlevel_lock() < 0) {
	      /* waiting for unlock... */
	      RESET_TIMER();
	      SET_TIMER(HZ * ps2cdvd_check_interval);
	      break;
	    }
	    if (CURRENT == NULL) {
	      if (ps2cdvd_spindown * HZ < jiffies - prev_read) {
		new_state = STAT_SPINDOWN;
	      } else {
		/* nothing to do */
		ps2cdvd_lowlevel_unlock();
		RESET_TIMER();
		SET_TIMER(HZ * ps2cdvd_check_interval);
	      }
	    } else {
	      prev_read = jiffies;
	      if (jiffies - prev_tray_check < HZ/2) {
		new_state = STAT_READ;
	      } else {
		prev_tray_check = jiffies;
		new_state = STAT_CHECK_TRAY;
	      }
	    }
	    break;
	  case EV_INTR:
	    break;
	  }
	  break;
	case STAT_CHECK_TRAY:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    if (carg->result < 0) {
	      new_state = STAT_ERROR;
	    } else {
	      struct sbr_cdvd_trayreq_arg *arg = carg->arg;
	      if (arg->traycount != 0) {
		if (disc_locked) {
		  printk(KERN_CRIT"ps2cdvd: =============================\n");
		  printk(KERN_CRIT"ps2cdvd: the disc is currently locked.\n");
		  printk(KERN_CRIT"ps2cdvd: please don't take it away!\n");
		  printk(KERN_CRIT"ps2cdvd: =============================\n");
		}

		invalidate_discinfo();

		new_state = STAT_CHECK_DISCTYPE;
	      } else {
		if (CURRENT) {
		  new_state = STAT_READ;
		} else {
		  new_state = STAT_READY;
		}
	      }
	    }
	    break;
	  }
	  break;
	case STAT_READ:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    new_state = STAT_READ_ERROR_CHECK;
	    break;
	  }
	  break;
	case STAT_READ_EOM_RETRY:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    new_state = STAT_READ_ERROR_CHECK;
	    break;
	  }
	  break;
	case STAT_READ_ERROR_CHECK:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    if (carg->result == SCECdErNO) {
	      /*
	       * succeeded
	       */
	      while (CURRENT != NULL &&
		     ps2cdvd_databuf_addr <= CURRENT->sector/4 &&
		     CURRENT->sector/4 < ps2cdvd_databuf_addr + ps2cdvd_databuf_size) {
		memcpy(CURRENT->buffer,
		       ps2cdvd_databuf + DATA_SECT_SIZE * (CURRENT->sector/4 - ps2cdvd_databuf_addr),
		       DATA_SECT_SIZE);
		end_request(1);
	      }
	      if (!ps2sif_iswaiting(ps2cdvd_lock) && CURRENT != NULL) {
		/* tiny acceleration */
		new_state = STAT_READ;
	      } else {
		new_state = STAT_READY;
	      }
	    } else
	    if (carg->result == 0x38) {
	      /*
	       * sector format error
	       */
	      DPRINT(DBG_DIAG,
		     "error: sector format error, code=0x38 (ignored)\n");
	      memset(CURRENT->buffer, 0, DATA_SECT_SIZE);
	      end_request(1);
	      if (!ps2sif_iswaiting(ps2cdvd_lock) && CURRENT != NULL) {
		/* tiny acceleration */
		new_state = STAT_READ;
	      } else {
		new_state = STAT_READY;
	      }
	    } else
	    if (carg->result == SCECdErEOM &&
		ps2cdvd_databuf_addr != 
			CURRENT->sector/4 - ps2cdvd_databuf_size + 1 &&
		ps2cdvd_databuf_size <= CURRENT->sector/4) {
	      /* you got End Of Media and you have not retried */
	      DPRINT(DBG_DIAG, "error: %s, code=0x%02x (retry...)\n",
		     ps2cdvd_geterrorstr(carg->result),
		     carg->result);
	      new_state = STAT_READ_EOM_RETRY;
	    } else {
	      DPRINT(DBG_DIAG, "error: %s, code=0x%02x\n",
		     ps2cdvd_geterrorstr(carg->result),
		     carg->result);
	      ps2cdvd_databuf_addr = -1;
	      end_request(0);		/* I/O error */
	      new_state = STAT_READY;
	    }
	    break;
	  }
	  break;
	case STAT_INVALID_DISC:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    if (ps2cdvd_lowlevel_lock() < 0) {
	      /* waiting for unlock... */
	      RESET_TIMER();
	      SET_TIMER(HZ * ps2cdvd_check_interval);
	    } else {
	      new_state = STAT_CHECK_DISCTYPE;
	    }
	    break;
	  case EV_INTR:
	    break;
	  }
	  break;
	case STAT_SPINDOWN:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    break;
	  case EV_INTR:
	    if (CURRENT == NULL) {
	      new_state = STAT_IDLE;
	    } else {
	      DPRINT(DBG_VERBOSE, "re-spinup...\n");
	      new_state = STAT_CHECK_DISCTYPE;
	    }
	    break;
	  }
	  break;
	case STAT_IDLE:
	  switch (ev->type) {
	  case EV_START:
	  case EV_TIMEOUT:
	    if (ps2cdvd_lowlevel_lock() < 0) {
	      /* waiting for unlock... */
	      RESET_TIMER();
	      SET_TIMER(HZ * ps2cdvd_check_interval);
	    } else {
	      new_state = STAT_CHECK_DISCTYPE;
	    }
	    break;
	  case EV_INTR:
	    break;
	  }
	  break;
	case STAT_ERROR:
	  break;
	default:
	  printk(KERN_ERR "ps2cdvd: invalid state");
	  ps2cdvd_state = STAT_WAIT_DISC;
	  break;
	}

	if (new_state != old_state) {
		struct ps2cdvd_event tick;
		tick.type = EV_TICK;
		ps2cdvd_leave(old_state);
		ps2cdvd_state = ps2cdvd_enter(new_state);
		DPRINT(DBG_STATE, "  -> new state: %s\n",
		       ps2cdvd_getstatestr(ps2cdvd_state));
		if (old_state != ps2cdvd_state &&
		    ps2cdvd_state == STAT_READY) {
			ps2cdvd_state_machine(&tick);
		}
		wake_up_interruptible(&statq);
	}

	restore_flags(flags);
}

__initfunc(int ps2cdvd_init(void))
{
	int res;

	DPRINT(DBG_VERBOSE, "init: get lock\n");
	if ((ps2cdvd_lock = ps2sif_getlock(PS2LOCK_CDVD)) == NULL) {
		printk(KERN_ERR "ps2cdvd: Can't get lock\n");
		ps2cdvd_cleanup();
		return -EINVAL;
	}
	ps2sif_lockqueueinit(&ps2cdvd_lock_qi);
	ps2cdvd_lock_qi.name = "ps2cdvd";

	DPRINT(DBG_VERBOSE, "init: initialize timer\n");
	init_timer(&io_timer);
	io_timer.function = (void(*)(u_long))ps2cdvd_timer;
	ps2cdvd_state = STAT_WAIT_DISC;

	DPRINT(DBG_VERBOSE, "init: allocate diaklabel buffer\n");
	labelbuf = kmalloc(2048, GFP_KERNEL);
	if (labelbuf == NULL) {
		printk(KERN_ERR "ps2cdvd: Can't allocate buffer\n");
		ps2cdvd_cleanup();
		return -ENOMEM;
	}
	initialized |= INIT_LABELBUF;

	DPRINT(DBG_VERBOSE, "allocate buffer\n");
	ps2cdvd_databufx = kmalloc(ps2cdvd_databuf_size * AUDIO_SECT_SIZE +
				   BUFFER_ALIGNMENT, GFP_KERNEL);
	if (ps2cdvd_databufx == NULL) {
		printk(KERN_ERR "ps2cdvd: Can't allocate buffer\n");
		ps2cdvd_cleanup();
		return -ENOMEM;
	}
	ps2cdvd_databuf = ALIGN(ps2cdvd_databufx, BUFFER_ALIGNMENT);
	initialized |= INIT_DATABUF;

	DPRINT(DBG_VERBOSE, "init: call sbios\n");
	if (ps2cdvdcall_init()) {
		printk(KERN_ERR "ps2cdvd: Can't initialize CD/DVD-ROM subsystem\n");
		ps2cdvd_cleanup();
		return -EIO;
	}
#ifdef CONFIG_PS2_SBIOS_VER_CHECK
	if (0x0201 <= sbios(SB_GETVER, NULL))
		ps2cdvdcall_reset();
#else
	ps2cdvdcall_reset();
#endif
	initialized |= INIT_IOPSIDE;

	DPRINT(DBG_VERBOSE, "init: register block device\n");
	if ((res = register_blkdev(MAJOR_NR, "ps2cdvd", &cdrom_fops)) < 0) {
		printk(KERN_ERR "ps2cdvd: Unable to get major %d for PS2 CD/DVD-ROM\n",
		       MAJOR_NR);
		ps2cdvd_cleanup();
                return -EIO;
	}
	if (MAJOR_NR == 0) MAJOR_NR = res;
	initialized |= INIT_BLKDEV;

	blksize_size[MAJOR_NR] = ps2cdvd_blocksizes;
	hardsect_size[MAJOR_NR] = ps2cdvd_hardsectsizes;
	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
	read_ahead[MAJOR_NR] = ps2cdvd_read_ahead;

	DPRINT(DBG_VERBOSE, "init: register cdrom\n");
	ps2cdvd_info.dev = MKDEV(MAJOR_NR, 0);
        if (register_cdrom(&ps2cdvd_info) != 0) {
		printk(KERN_ERR "ps2cdvd: Cannot register PS2 CD/DVD-ROM\n");
		ps2cdvd_cleanup();
		return -EIO;
        }
	initialized |= INIT_CDROM;

	printk(KERN_INFO "PS2 CD/DVD-ROM driver\n");

	if (ps2cdvd_lowlevel_lock() == 0)
	  ps2cdvd_state = ps2cdvd_enter(STAT_INIT_TRAYSTAT);
	else
	  ps2cdvd_state = ps2cdvd_enter(STAT_WAIT_DISC);

	return 0;
}
Exemple #15
0
static int
ps2cdvd_enter_leave(int state, int enter)
{
	int res_state = state;

	switch (state) {
	case STAT_WAIT_DISC:
	  if (enter) {
	    if (ps2cdvd_state != STAT_CHECK_DISCTYPE)
	      invalidate_discinfo();
	    ps2cdvd_lowlevel_unlock();
	    if (CURRENT)
	      DPRINT(DBG_DIAG, "abort all pending request\n");
	    while (CURRENT)
	      end_request(0);
	    SET_TIMER(HZ * ps2cdvd_check_interval);
	  } else {
	    RESET_TIMER();
	  }
	  break;
	case STAT_INIT_TRAYSTAT:
	  if (enter) {
	    if (ps2cdvd_send_trayreq(SCECdTrayCheck) < 0) {
	      DPRINT(DBG_DIAG, "send_trayreq() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_CHECK_DISCTYPE:
	  if (enter) {
	    disc_type = INVALID_DISCTYPE;
	    if (ps2cdvd_send_gettype() < 0) {
	      DPRINT(DBG_DIAG, "send_gettype() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_INIT_CHECK_READY:
	  if (enter) {
	    //if (ps2cdvd_send_ready(1 /* non block */) < 0) {
	    if (ps2cdvd_send_ready(0 /* block */) < 0) {
	      DPRINT(DBG_DIAG, "send_ready() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_TOC_READ:
	  if (enter) {
	    if (ps2cdvd_send_gettoc(tocbuf, sizeof(tocbuf)) < 0) {
	      DPRINT(DBG_DIAG, "send_gettoc() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_SET_MMODE:
	  if (enter) {
	    DPRINT(DBG_INFO, "media mode %s\n",
		   media_mode == SCECdCD ? "CD" : "DVD");
	    if (ps2cdvd_send_mmode(media_mode) < 0) {
	      DPRINT(DBG_DIAG, "send_mmode() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_LABEL_READ:
	  if (enter) {
	    if (ps2cdvd_send_read(16, 1, labelbuf, &DataMode) < 0) {
	      DPRINT(DBG_DIAG, "send_read() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_LABEL_READ_ERROR_CHECK:
	  if (enter) {
	    if (ps2cdvd_send_geterror() < 0) {
	      DPRINT(DBG_DIAG, "send_geterror() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_READY:
	  if (enter) {
	    ps2cdvd_lowlevel_unlock();
	    SET_TIMER(HZ * ps2cdvd_check_interval);
	  } else {
	    RESET_TIMER();
	  }
	  break;
	case STAT_CHECK_TRAY:
	  if (enter) {
	    if (ps2cdvd_send_trayreq(2) < 0) {
	      DPRINT(DBG_DIAG, "send_trayreq() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_READ:
	  if (enter) {
	    DPRINT(DBG_READ, "REQ %p: sec=%ld  n=%ld  buf=%p\n",
		   CURRENT, CURRENT->sector,
		   CURRENT->current_nr_sectors, CURRENT->buffer);
	    if (ps2cdvd_send_read(CURRENT->sector/4,
				  ps2cdvd_databuf_size,
				  ps2cdvd_databuf,
				  &DataMode) < 0) {
	      DPRINT(DBG_DIAG, "send_readdata() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    } else {
	      ps2cdvd_databuf_addr = CURRENT->sector/4;
	    }
	  } else {
	  }
	  break;
	case STAT_READ_EOM_RETRY:
	  if (enter) {
	    DPRINT(DBG_READ, "REQ %p: sec=%ld  n=%ld  buf=%p (EOM retry)\n",
		   CURRENT, CURRENT->sector,
		   CURRENT->current_nr_sectors, CURRENT->buffer);
	    if (ps2cdvd_send_read(CURRENT->sector/4 - ps2cdvd_databuf_size + 1,
				  ps2cdvd_databuf_size,
				  ps2cdvd_databuf,
				  &DataMode) < 0) {
	      DPRINT(DBG_DIAG, "send_readdata() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    } else {
	      ps2cdvd_databuf_addr =
		CURRENT->sector/4 - ps2cdvd_databuf_size + 1;
	    }
	  } else {
	  }
	  break;
	case STAT_READ_ERROR_CHECK:
	  if (enter) {
	    if (ps2cdvd_send_geterror() < 0) {
	      DPRINT(DBG_DIAG, "send_geterror() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_INVALID_DISC:
	  if (enter) {
	    if (!disc_locked) {
	      DPRINT(DBG_DIAG, "attempt to enter INVALID_DISC state while !disc_locked\n");
	      res_state = ps2cdvd_enter(STAT_WAIT_DISC);
	    } else {
	      invalidate_discinfo();
	      ps2cdvd_lowlevel_unlock();
	      SET_TIMER(HZ * ps2cdvd_check_interval);
	    }
	  } else {
	    RESET_TIMER();
	  }
	  break;
	case STAT_SPINDOWN:
	  if (enter) {
	    if (ps2cdvd_send_stop() < 0) {
	      DPRINT(DBG_DIAG, "send_stop() failed\n");
	      res_state = ps2cdvd_enter(STAT_ERROR);
	    }
	  } else {
	  }
	  break;
	case STAT_IDLE:
	  if (enter) {
	    invalidate_discinfo();
	    ps2cdvd_lowlevel_unlock();
	  } else {
	    RESET_TIMER();
	  }
	  break;
	case STAT_ERROR:
	  if (enter) {
	    invalidate_discinfo();
	    while (CURRENT)
	      end_request(0);
	    ps2cdvd_lowlevel_unlock();
	  } else {
	  }
	  break;
	default:
	  printk(KERN_CRIT "ps2cdvd: INVALID STATE\n");
	  break;
	}

	return res_state;
}