Exemple #1
0
void ips_morpheus_intr(void *void_sc)
{
        ips_softc_t *sc = (ips_softc_t *)void_sc;
	u_int32_t oisr, iisr;
	int cmdnumber;
	ips_cmd_status_t status;

	iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
	oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
        PRINTF(9,"interrupt registers in:%x out:%x\n",iisr, oisr);
	if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
		DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
		return;	
	}
	while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
		cmdnumber = status.fields.command_id;
		sc->commandarray[cmdnumber].status.value = status.value;
		sc->commandarray[cmdnumber].timeout = 0;
		sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
		

		DEVICE_PRINTF(9,sc->dev, "got command %d\n", cmdnumber);
	}
        return;
}
Exemple #2
0
/* see if we should reinitialize the card and wait for it to timeout or complete initialization */
int ips_morpheus_reinit(ips_softc_t *sc, int force)
{
        u_int32_t tmp;
	int i;

	tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
	if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
	    (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
		ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
		return 0;
	}
	ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
	ips_read_4(sc, MORPHEUS_REG_OIMR);

	device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
	ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
	DELAY(5000000);
	ips_read_4(sc, MORPHEUS_REG_OIMR);

	tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
	for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
		DELAY(1000000);
		DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
		tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
	}
	if(tmp & MORPHEUS_BIT_POST1)
		ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);

        if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
                device_printf(sc->dev,"Adapter error during initialization.\n");
		return 1;
        }
	for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
		DELAY(1000000);	
		DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
		tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
	}
	if(tmp & MORPHEUS_BIT_POST2)
		ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);

	if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
		device_printf(sc->dev, "adapter failed config check\n");
		return 1;
        }
	ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
	if(force && ips_clear_adapter(sc)){
		device_printf(sc->dev, "adapter clear failed\n");
		return 1;
	}
	return 0;
}
Exemple #3
0
/* clean up so we can unload the driver. */
int ips_adapter_free(ips_softc_t *sc)
{
	int error = 0;
	intrmask_t mask;
	if(sc->state & IPS_DEV_OPEN)
		return EBUSY;
	if((error = ips_diskdev_free(sc)))
		return error;
	if(ips_cmdqueue_free(sc)){
		device_printf(sc->dev,
		     "trying to exit when command queue is not empty!\n");
		return EBUSY;
	}
	DEVICE_PRINTF(1, sc->dev, "free\n");
	mask = splbio();
	untimeout(ips_timeout, sc, sc->timer);
	splx(mask);
	if (mtx_initialized(&sc->cmd_mtx))
		mtx_destroy(&sc->cmd_mtx);

	if(sc->sg_dmatag)
		bus_dma_tag_destroy(sc->sg_dmatag);
	if(sc->command_dmatag)
		bus_dma_tag_destroy(sc->command_dmatag);
	if(sc->device_file)
	        destroy_dev(sc->device_file);
        return 0;
}
Exemple #4
0
static int ipsd_close(struct disk *dp)
{
	ipsdisk_softc_t *dsc = dp->d_drv1;
	dsc->state &= ~IPS_DEV_OPEN;
	DEVICE_PRINTF(2, dsc->dev, "I'm closed for the day\n");
        return 0;
}
Exemple #5
0
static int ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags)
{
	intrmask_t mask;
	ips_command_t *command;
	ips_wait_list_t *waiter;
	unsigned long memflags = 0;
	if(IPS_NOWAIT_FLAG & flags)
		memflags = M_NOWAIT;
	waiter = malloc(sizeof(ips_wait_list_t), M_DEVBUF, memflags);
	if(!waiter)
		return ENOMEM;
	mask = splbio();
	if(sc->state & IPS_OFFLINE){
		splx(mask);
		return EIO;
	}
	command = SLIST_FIRST(&sc->free_cmd_list);
	if(command && !(sc->state & IPS_TIMEOUT)){
		SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
		(sc->used_commands)++;
		splx(mask);
		clear_ips_command(command);
		bzero(command->command_buffer, IPS_COMMAND_LEN);
		free(waiter, M_DEVBUF);
		command->arg = data;
		return callback(command);
	}
	DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n"); 
	waiter->callback = callback; 
	waiter->data = data;
	STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
	splx(mask);
	return 0;
}
Exemple #6
0
static void ips_run_waiting_command(ips_softc_t *sc)
{
	ips_wait_list_t *waiter;
	ips_command_t	*command;
	int (*callback)(ips_command_t*);
	intrmask_t mask;

	mask = splbio();
	waiter = STAILQ_FIRST(&sc->cmd_wait_list);
	command = SLIST_FIRST(&sc->free_cmd_list);
	if(!waiter || !command){
		splx(mask);
		return;
	}
	DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
	SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
	STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
	(sc->used_commands)++;
	splx(mask);
	clear_ips_command(command);
	bzero(command->command_buffer, IPS_COMMAND_LEN);
	command->arg = waiter->data;
	callback = waiter->callback;
	free(waiter, M_DEVBUF);
	callback(command);
	return;	
}
Exemple #7
0
static __inline int ips_morpheus_check_intr(ips_softc_t *sc)
{
	int cmdnumber;
	ips_cmd_status_t status;
	ips_command_t *command;
	int found = 0;
	u_int32_t oisr;

	oisr = ips_read_4(sc, MORPHEUS_REG_OISR);
	PRINTF(9, "interrupt registers out:%x\n", oisr);
	if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
		DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
		return (0);	
	}
	while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
		cmdnumber = status.fields.command_id;
		command = &sc->commandarray[cmdnumber];
		command->status.value = status.value;
		command->timeout = 0;
		command->callback(command);

		found = 1;
	}
        return (found);
}
Exemple #8
0
static int
ipsd_probe(device_t dev)
{
	DEVICE_PRINTF(2, dev, "in probe\n");
	device_set_desc(dev, "Logical Drive");
	return 0;
}
Exemple #9
0
/* handle opening of disk device.  It must set up all
   information about the geometry and size of the disk */
static int ipsd_open(struct disk *dp)
{
	ipsdisk_softc_t *dsc = dp->d_drv1;

	dsc->state |= IPS_DEV_OPEN;
	DEVICE_PRINTF(2, dsc->dev, "I'm open\n");
       	return 0;
}
Exemple #10
0
static int
ipsd_close(struct dev_close_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	ipsdisk_softc_t *dsc = dev->si_drv1;

	dsc->state &= ~IPS_DEV_OPEN;
	DEVICE_PRINTF(2, dsc->dev, "I'm closed for the day\n");
	return 0;
}
Exemple #11
0
static int ipsd_detach(device_t dev)
{
	ipsdisk_softc_t *dsc;

	DEVICE_PRINTF(2, dev,"in detach\n");
	dsc = (ipsdisk_softc_t *)device_get_softc(dev);
	if(dsc->state & IPS_DEV_OPEN)
		return (EBUSY);
	disk_destroy(dsc->ipsd_disk);
	return 0;
}
Exemple #12
0
static void ipsd_strategy(struct bio *iobuf)
{
	ipsdisk_softc_t *dsc;

	dsc = iobuf->bio_disk->d_drv1;	
	DEVICE_PRINTF(8,dsc->dev,"in strategy\n");
	iobuf->bio_driver1 = (void *)(uintptr_t)dsc->sc->drives[dsc->disk_number].drivenum;
	mtx_lock(&dsc->sc->queue_mtx);
	bioq_insert_tail(&dsc->sc->queue, iobuf);
	ips_start_io_request(dsc->sc);
	mtx_unlock(&dsc->sc->queue_mtx);
}
Exemple #13
0
/*
 * handle opening of disk device.  It must set up all information about
 * the geometry and size of the disk
 */
static int
ipsd_open(struct dev_open_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	ipsdisk_softc_t *dsc = dev->si_drv1;

	if (dsc == NULL)
		return (ENXIO);
	dsc->state |= IPS_DEV_OPEN;
	DEVICE_PRINTF(2, dsc->dev, "I'm open\n");
	return 0;
}
Exemple #14
0
static int
ipsd_attach(device_t dev)
{
	device_t adapter;
	ipsdisk_softc_t *dsc;
	struct disk_info info;
	u_int totalsectors;
	u_int nheads, nsectors;

	DEVICE_PRINTF(2, dev, "in attach\n");
	dsc = (ipsdisk_softc_t *)device_get_softc(dev);
	bzero(dsc, sizeof(ipsdisk_softc_t));
	adapter = device_get_parent(dev);
	dsc->dev = dev;
	dsc->sc = device_get_softc(adapter);
	dsc->unit = device_get_unit(dev);
	dsc->disk_number = (uintptr_t) device_get_ivars(dev);
	totalsectors = dsc->sc->drives[dsc->disk_number].sector_count;
	if ((totalsectors > 0x400000) &&
	    ((dsc->sc->adapter_info.miscflags & 0x8) == 0)) {
		nheads = IPS_NORM_HEADS;
		nsectors = IPS_NORM_SECTORS;
	} else {
		nheads = IPS_COMP_HEADS;
		nsectors = IPS_COMP_SECTORS;
	}
	devstat_add_entry(&dsc->stats, "ipsd", dsc->unit, DEV_BSIZE,
			  DEVSTAT_NO_ORDERED_TAGS,
			  DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_SCSI,
			  DEVSTAT_PRIORITY_DISK);
	dsc->ipsd_dev_t = disk_create(dsc->unit, &dsc->ipsd_disk, &ipsd_ops);
	dsc->ipsd_dev_t->si_drv1 = dsc;
	dsc->ipsd_dev_t->si_iosize_max = IPS_MAX_IO_SIZE;

	bzero(&info, sizeof(info));
	info.d_media_blksize	= IPS_BLKSIZE;		/* mandatory */
	info.d_media_blocks	= totalsectors;

	info.d_type		= DTYPE_ESDI;		/* optional */
	info.d_nheads		= nheads;
	info.d_secpertrack	= nsectors;
	info.d_ncylinders	= totalsectors / nheads / nsectors;
	info.d_secpercyl	= nsectors / nheads;

	disk_setdiskinfo(&dsc->ipsd_disk, &info);

	device_printf(dev, "Logical Drive  (%dMB)\n",
	    dsc->sc->drives[dsc->disk_number].sector_count >> 11);
	return 0;
}
Exemple #15
0
static int
ipsd_strategy(struct dev_strategy_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	struct bio *bio = ap->a_bio;
	ipsdisk_softc_t *dsc;

	dsc = dev->si_drv1;
	DEVICE_PRINTF(8, dsc->dev, "in strategy\n");
	bio->bio_driver_info = dsc;
	devstat_start_transaction(&dsc->stats);
	lockmgr(&dsc->sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
	bioqdisksort(&dsc->sc->bio_queue, bio);
	ips_start_io_request(dsc->sc);
	lockmgr(&dsc->sc->queue_lock, LK_RELEASE);
	return(0);
}
Exemple #16
0
static int ipsd_attach(device_t dev)
{
	device_t adapter;
	ipsdisk_softc_t *dsc;
	u_int totalsectors;

	DEVICE_PRINTF(2,dev, "in attach\n");

	dsc = (ipsdisk_softc_t *)device_get_softc(dev);
	bzero(dsc, sizeof(ipsdisk_softc_t));
	adapter = device_get_parent(dev);
	dsc->dev = dev;
	dsc->sc = device_get_softc(adapter);
	dsc->unit = device_get_unit(dev);
	dsc->disk_number = (uintptr_t) device_get_ivars(dev);
	dsc->ipsd_disk = disk_alloc();
	dsc->ipsd_disk->d_drv1 = dsc;
	dsc->ipsd_disk->d_name = "ipsd";
	dsc->ipsd_disk->d_maxsize = IPS_MAX_IO_SIZE;
	dsc->ipsd_disk->d_open = ipsd_open;
	dsc->ipsd_disk->d_close = ipsd_close;
	dsc->ipsd_disk->d_strategy = ipsd_strategy;
	dsc->ipsd_disk->d_dump = ipsd_dump;

	totalsectors = dsc->sc->drives[dsc->disk_number].sector_count;
   	if ((totalsectors > 0x400000) &&
       			((dsc->sc->adapter_info.miscflags & 0x8) == 0)) {
      		dsc->ipsd_disk->d_fwheads = IPS_NORM_HEADS;
      		dsc->ipsd_disk->d_fwsectors = IPS_NORM_SECTORS;
   	} else {
      		dsc->ipsd_disk->d_fwheads = IPS_COMP_HEADS;
      		dsc->ipsd_disk->d_fwsectors = IPS_COMP_SECTORS;
   	}
	dsc->ipsd_disk->d_sectorsize = IPS_BLKSIZE;
	dsc->ipsd_disk->d_mediasize = (off_t)totalsectors * IPS_BLKSIZE;
	dsc->ipsd_disk->d_unit = dsc->unit;
	dsc->ipsd_disk->d_flags = 0;
	disk_create(dsc->ipsd_disk, DISK_VERSION);

	device_printf(dev, "Logical Drive  (%dMB)\n",
		      dsc->sc->drives[dsc->disk_number].sector_count >> 11);
	return 0;
}
Exemple #17
0
/* clean up so we can unload the driver. */
int ips_adapter_free(ips_softc_t *sc)
{
	int error = 0;
	if(sc->state & IPS_DEV_OPEN)
		return EBUSY;
	if((error = ips_diskdev_free(sc)))
		return error;
	if(ips_cmdqueue_free(sc)){
		device_printf(sc->dev,
		     "trying to exit when command queue is not empty!\n");
		return EBUSY;
	}
	DEVICE_PRINTF(1, sc->dev, "free\n");
	callout_drain(&sc->timer);

	if(sc->sg_dmatag)
		bus_dma_tag_destroy(sc->sg_dmatag);
	if(sc->command_dmatag)
		bus_dma_tag_destroy(sc->command_dmatag);
	if(sc->device_file)
	        destroy_dev(sc->device_file);
        return 0;
}
Exemple #18
0
/* check card and initialize it */
int ips_adapter_init(ips_softc_t *sc)
{
        DEVICE_PRINTF(1,sc->dev, "initializing\n");
        if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
				/* alignemnt */	1,
				/* boundary  */	0,
				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
				/* highaddr  */	BUS_SPACE_MAXADDR,
				/* filter    */	NULL,
				/* filterarg */	NULL,
				/* maxsize   */	IPS_COMMAND_LEN + 
						    IPS_MAX_SG_LEN,
				/* numsegs   */	1,
				/* maxsegsize*/	IPS_COMMAND_LEN + 
						    IPS_MAX_SG_LEN,
				/* flags     */	0,
				&sc->command_dmatag) != 0) {
                device_printf(sc->dev, "can't alloc command dma tag\n");
		goto error;
        }
	if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
				/* alignemnt */	1,
				/* boundary  */	0,
				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
				/* highaddr  */	BUS_SPACE_MAXADDR,
				/* filter    */	NULL,
				/* filterarg */	NULL,
				/* maxsize   */	IPS_MAX_IOBUF_SIZE,
				/* numsegs   */	IPS_MAX_SG_ELEMENTS,
				/* maxsegsize*/	IPS_MAX_IOBUF_SIZE,
				/* flags     */	0,
				&sc->sg_dmatag) != 0) {
		device_printf(sc->dev, "can't alloc SG dma tag\n");
		goto error;
	}
	/* create one command buffer until we know how many commands this card
           can handle */
	sc->max_cmds = 1;
	ips_cmdqueue_init(sc);

	if(sc->ips_adapter_reinit(sc, 0))
		goto error;

	mtx_init(&sc->cmd_mtx, "ips command mutex", NULL, MTX_DEF);
	if(ips_get_adapter_info(sc) || ips_get_drive_info(sc)){
		device_printf(sc->dev, "failed to get configuration data from device\n");
		goto error;
	}
	ips_update_nvram(sc); /* no error check as failure doesn't matter */

        ips_cmdqueue_free(sc);
	if(sc->adapter_info.max_concurrent_cmds)
        	sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
	else
		sc->max_cmds = 32;
        if(ips_cmdqueue_init(sc)){
		device_printf(sc->dev, "failed to initialize command buffers\n");
		goto error;
	}
        sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
                                        S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
	sc->device_file->si_drv1 = sc;
	ips_diskdev_init(sc);
	sc->timer = timeout(ips_timeout, sc, 10*hz);
        return 0;

error:
	ips_adapter_free(sc);
	return ENXIO;
}
Exemple #19
0
/* check card and initialize it */
int ips_adapter_init(ips_softc_t *sc)
{
        int i;
        DEVICE_PRINTF(1,sc->dev, "initializing\n");

        if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
				/* alignemnt */	1,
				/* boundary  */	0,
				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
				/* highaddr  */	BUS_SPACE_MAXADDR,
				/* filter    */	NULL,
				/* filterarg */	NULL,
				/* maxsize   */	IPS_COMMAND_LEN + 
						    IPS_MAX_SG_LEN,
				/* numsegs   */	1,
				/* maxsegsize*/	IPS_COMMAND_LEN + 
						    IPS_MAX_SG_LEN,
				/* flags     */	0,
				/* lockfunc  */ NULL,
				/* lockarg   */ NULL,
				&sc->command_dmatag) != 0) {
                device_printf(sc->dev, "can't alloc command dma tag\n");
		goto error;
        }
	if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
				/* alignemnt */	1,
				/* boundary  */	0,
				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
				/* highaddr  */	BUS_SPACE_MAXADDR,
				/* filter    */	NULL,
				/* filterarg */	NULL,
				/* maxsize   */	IPS_MAX_IOBUF_SIZE,
				/* numsegs   */	IPS_MAX_SG_ELEMENTS,
				/* maxsegsize*/	IPS_MAX_IOBUF_SIZE,
				/* flags     */	0,
				/* lockfunc  */ busdma_lock_mutex,
				/* lockarg   */ &sc->queue_mtx,
				&sc->sg_dmatag) != 0) {
		device_printf(sc->dev, "can't alloc SG dma tag\n");
		goto error;
	}
	/* create one command buffer until we know how many commands this card
           can handle */
	sc->max_cmds = 1;
	ips_cmdqueue_init(sc);

	if(sc->ips_adapter_reinit(sc, 0))
		goto error;

	/* initialize ffdc values */
	microtime(&sc->ffdc_resettime);
	sc->ffdc_resetcount = 1;
	if ((i = ips_ffdc_reset(sc)) != 0) {
		device_printf(sc->dev, "failed to send ffdc reset to device (%d)\n", i);
		goto error;
	}
	if ((i = ips_get_adapter_info(sc)) != 0) {
		device_printf(sc->dev, "failed to get adapter configuration data from device (%d)\n", i);
		goto error;
	}
	ips_update_nvram(sc); /* no error check as failure doesn't matter */
	if(sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T){
		device_printf(sc->dev, "adapter type: %s\n", ips_adapter_name[sc->adapter_type]);
	}
 	if ((i = ips_get_drive_info(sc)) != 0) {
		device_printf(sc->dev, "failed to get drive configuration data from device (%d)\n", i);
		goto error;
	}

        ips_cmdqueue_free(sc);
	if(sc->adapter_info.max_concurrent_cmds)
        	sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
	else
		sc->max_cmds = 32;
        if(ips_cmdqueue_init(sc)){
		device_printf(sc->dev, "failed to initialize command buffers\n");
		goto error;
	}
        sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
                                        S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
	sc->device_file->si_drv1 = sc;
	ips_diskdev_init(sc);
	callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
        return 0;

error:
	ips_adapter_free(sc);
	return ENXIO;
}