maple.c 17.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
 * Core maple bus functionality
 *
 *  Copyright (C) 2007 Adrian McMenamin
 *
 * Based on 2.4 code by:
 *
 *  Copyright (C) 2000-2001 YAEGASHI Takeshi
 *  Copyright (C) 2001 M. R. Brown
 *  Copyright (C) 2001 Paul Mundt
 *
 * and others.
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/maple.h>
#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/mach/dma.h>
#include <asm/mach/sysasic.h>
#include <asm/mach/maple.h>
34
#include <linux/delay.h>
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin");
MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}");

static void maple_dma_handler(struct work_struct *work);
static void maple_vblank_handler(struct work_struct *work);

static DECLARE_WORK(maple_dma_process, maple_dma_handler);
static DECLARE_WORK(maple_vblank_process, maple_vblank_handler);

static LIST_HEAD(maple_waitq);
static LIST_HEAD(maple_sentq);

static DEFINE_MUTEX(maple_list_lock);

static struct maple_driver maple_dummy_driver;
static struct device maple_bus;
static int subdevice_map[MAPLE_PORTS];
static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr;
static unsigned long maple_pnp_time;
57
static int started, scanning, liststatus, realscan;
58 59 60
static struct kmem_cache *maple_queue_cache;

struct maple_device_specify {
61 62
	int port;
	int unit;
63 64 65 66 67 68 69 70 71
};

/**
 *  maple_driver_register - register a device driver
 *  automatically makes the driver bus a maple bus
 *  @drv: the driver to be registered
 */
int maple_driver_register(struct device_driver *drv)
{
72 73 74 75
	if (!drv)
		return -EINVAL;
	drv->bus = &maple_bus_type;
	return driver_register(drv);
76 77 78 79 80 81
}
EXPORT_SYMBOL_GPL(maple_driver_register);

/* set hardware registers to enable next round of dma */
static void maplebus_dma_reset(void)
{
82 83 84 85 86 87
	ctrl_outl(MAPLE_MAGIC, MAPLE_RESET);
	/* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */
	ctrl_outl(1, MAPLE_TRIGTYPE);
	ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED);
	ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR);
	ctrl_outl(1, MAPLE_ENABLE);
88 89 90 91 92 93 94 95 96 97
}

/**
 * maple_getcond_callback - setup handling MAPLE_COMMAND_GETCOND
 * @dev: device responding
 * @callback: handler callback
 * @interval: interval in jiffies between callbacks
 * @function: the function code for the device
 */
void maple_getcond_callback(struct maple_device *dev,
98 99
			void (*callback) (struct mapleq *mq),
			unsigned long interval, unsigned long function)
100
{
101 102 103 104
	dev->callback = callback;
	dev->interval = interval;
	dev->function = cpu_to_be32(function);
	dev->when = jiffies;
105 106 107 108 109
}
EXPORT_SYMBOL_GPL(maple_getcond_callback);

static int maple_dma_done(void)
{
110
	return (ctrl_inl(MAPLE_STATE) & 1) == 0;
111 112 113 114
}

static void maple_release_device(struct device *dev)
{
115 116 117 118 119 120 121 122 123 124 125
	struct maple_device *mdev;
	struct mapleq *mq;
	if (!dev)
		return;
	mdev = to_maple_dev(dev);
	mq = mdev->mq;
	if (mq) {
		if (mq->recvbufdcsp)
			kmem_cache_free(maple_queue_cache, mq->recvbufdcsp);
		kfree(mq);
		mq = NULL;
126
	}
127
	kfree(mdev);
128 129 130 131 132 133 134 135
}

/**
 * maple_add_packet - add a single instruction to the queue
 * @mq: instruction to add to waiting queue
 */
void maple_add_packet(struct mapleq *mq)
{
136 137 138
	mutex_lock(&maple_list_lock);
	list_add(&mq->list, &maple_waitq);
	mutex_unlock(&maple_list_lock);
139 140 141
}
EXPORT_SYMBOL_GPL(maple_add_packet);

142
static struct mapleq *maple_allocq(struct maple_device *mdev)
143
{
144
	struct mapleq *mq;
145

146 147 148
	mq = kmalloc(sizeof(*mq), GFP_KERNEL);
	if (!mq)
		return NULL;
149

150
	mq->dev = mdev;
151 152 153 154 155 156
	mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL);
	mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp);
	if (!mq->recvbuf) {
		kfree(mq);
		return NULL;
	}
157

158
	return mq;
159 160 161 162
}

static struct maple_device *maple_alloc_dev(int port, int unit)
{
163
	struct maple_device *mdev;
164

165 166
	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
	if (!mdev)
167
		return NULL;
168

169 170 171
	mdev->port = port;
	mdev->unit = unit;
	mdev->mq = maple_allocq(mdev);
172

173 174
	if (!mdev->mq) {
		kfree(mdev);
175 176
		return NULL;
	}
177 178 179 180
	mdev->dev.bus = &maple_bus_type;
	mdev->dev.parent = &maple_bus;
	mdev->function = 0;
	return mdev;
181 182 183 184
}

static void maple_free_dev(struct maple_device *mdev)
{
185 186 187
	if (!mdev)
		return;
	if (mdev->mq) {
188 189 190
		if (mdev->mq->recvbufdcsp)
			kmem_cache_free(maple_queue_cache,
				mdev->mq->recvbufdcsp);
191 192 193
		kfree(mdev->mq);
	}
	kfree(mdev);
194 195 196 197 198 199 200
}

/* process the command queue into a maple command block
 * terminating command has bit 32 of first long set to 0
 */
static void maple_build_block(struct mapleq *mq)
{
201 202
	int port, unit, from, to, len;
	unsigned long *lsendbuf = mq->sendbuf;
203

204 205 206 207 208
	port = mq->dev->port & 3;
	unit = mq->dev->unit;
	len = mq->length;
	from = port << 6;
	to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20);
209

210 211
	*maple_lastptr &= 0x7fffffff;
	maple_lastptr = maple_sendptr;
212

213 214 215 216
	*maple_sendptr++ = (port << 16) | len | 0x80000000;
	*maple_sendptr++ = PHYSADDR(mq->recvbuf);
	*maple_sendptr++ =
	    mq->command | (to << 8) | (from << 16) | (len << 24);
217

218 219
	while (len-- > 0)
		*maple_sendptr++ = *lsendbuf++;
220 221 222 223 224
}

/* build up command queue */
static void maple_send(void)
{
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
	int i;
	int maple_packets;
	struct mapleq *mq, *nmq;

	if (!list_empty(&maple_sentq))
		return;
	if (list_empty(&maple_waitq) || !maple_dma_done())
		return;
	maple_packets = 0;
	maple_sendptr = maple_lastptr = maple_sendbuf;
	list_for_each_entry_safe(mq, nmq, &maple_waitq, list) {
		maple_build_block(mq);
		list_move(&mq->list, &maple_sentq);
		if (maple_packets++ > MAPLE_MAXPACKETS)
			break;
	}
	if (maple_packets > 0) {
		for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++)
			dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE,
				       PAGE_SIZE, DMA_BIDIRECTIONAL);
	}
246 247 248
}

static int attach_matching_maple_driver(struct device_driver *driver,
249
					void *devptr)
250
{
251 252 253 254 255 256 257 258 259 260 261 262
	struct maple_driver *maple_drv;
	struct maple_device *mdev;

	mdev = devptr;
	maple_drv = to_maple_driver(driver);
	if (mdev->devinfo.function & be32_to_cpu(maple_drv->function)) {
		if (maple_drv->connect(mdev) == 0) {
			mdev->driver = maple_drv;
			return 1;
		}
	}
	return 0;
263 264 265 266
}

static void maple_detach_driver(struct maple_device *mdev)
{
267 268 269 270 271 272 273
	if (!mdev)
		return;
	if (mdev->driver) {
		if (mdev->driver->disconnect)
			mdev->driver->disconnect(mdev);
	}
	mdev->driver = NULL;
274 275
	device_unregister(&mdev->dev);
	mdev = NULL;
276 277 278
}

/* process initial MAPLE_COMMAND_DEVINFO for each device or port */
279
static void maple_attach_driver(struct maple_device *mdev)
280
{
281
	char *p, *recvbuf;
282 283 284
	unsigned long function;
	int matched, retval;

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
	recvbuf = mdev->mq->recvbuf;
	/* copy the data as individual elements in
	* case of memory optimisation */
	memcpy(&mdev->devinfo.function, recvbuf + 4, 4);
	memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12);
	memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1);
	memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1);
	memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30);
	memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60);
	memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2);
	memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2);
	memcpy(mdev->product_name, mdev->devinfo.product_name, 30);
	mdev->product_name[30] = '\0';
	memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60);
	mdev->product_licence[60] = '\0';

	for (p = mdev->product_name + 29; mdev->product_name <= p; p--)
302 303 304 305
		if (*p == ' ')
			*p = '\0';
		else
			break;
306
	for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--)
307 308 309 310 311
		if (*p == ' ')
			*p = '\0';
		else
			break;

312 313 314 315 316 317 318
	if (realscan) {
		printk(KERN_INFO "Maple device detected: %s\n",
			mdev->product_name);
		printk(KERN_INFO "Maple device: %s\n", mdev->product_licence);
	}

	function = be32_to_cpu(mdev->devinfo.function);
319 320 321 322

	if (function > 0x200) {
		/* Do this silently - as not a real device */
		function = 0;
323 324
		mdev->driver = &maple_dummy_driver;
		sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port);
325
	} else {
326 327 328 329
		if (realscan)
			printk(KERN_INFO
				"Maple bus at (%d, %d): Function 0x%lX\n",
				mdev->port, mdev->unit, function);
330 331

		matched =
332
		    bus_for_each_drv(&maple_bus_type, NULL, mdev,
333 334 335 336
				     attach_matching_maple_driver);

		if (matched == 0) {
			/* Driver does not exist yet */
337 338 339 340
			if (realscan)
				printk(KERN_INFO
					"No maple driver found.\n");
			mdev->driver = &maple_dummy_driver;
341
		}
342 343
		sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port,
			mdev->unit, function);
344
	}
345 346 347
	mdev->function = function;
	mdev->dev.release = &maple_release_device;
	retval = device_register(&mdev->dev);
348 349
	if (retval) {
		printk(KERN_INFO
350 351 352 353 354 355
		"Maple bus: Attempt to register device"
		" (%x, %x) failed.\n",
		mdev->port, mdev->unit);
		maple_free_dev(mdev);
		mdev = NULL;
		return;
356
	}
357 358 359 360 361 362 363 364 365
}

/*
 * if device has been registered for the given
 * port and unit then return 1 - allows identification
 * of which devices need to be attached or detached
 */
static int detach_maple_device(struct device *device, void *portptr)
{
366 367 368 369 370 371 372 373
	struct maple_device_specify *ds;
	struct maple_device *mdev;

	ds = portptr;
	mdev = to_maple_dev(device);
	if (mdev->port == ds->port && mdev->unit == ds->unit)
		return 1;
	return 0;
374 375 376 377
}

static int setup_maple_commands(struct device *device, void *ignored)
{
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
	struct maple_device *maple_dev = to_maple_dev(device);

	if ((maple_dev->interval > 0)
	    && time_after(jiffies, maple_dev->when)) {
		maple_dev->when = jiffies + maple_dev->interval;
		maple_dev->mq->command = MAPLE_COMMAND_GETCOND;
		maple_dev->mq->sendbuf = &maple_dev->function;
		maple_dev->mq->length = 1;
		maple_add_packet(maple_dev->mq);
		liststatus++;
	} else {
		if (time_after(jiffies, maple_pnp_time)) {
			maple_dev->mq->command = MAPLE_COMMAND_DEVINFO;
			maple_dev->mq->length = 0;
			maple_add_packet(maple_dev->mq);
			liststatus++;
		}
	}

	return 0;
398 399 400 401 402
}

/* VBLANK bottom half - implemented via workqueue */
static void maple_vblank_handler(struct work_struct *work)
{
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	if (!maple_dma_done())
		return;
	if (!list_empty(&maple_sentq))
		return;
	ctrl_outl(0, MAPLE_ENABLE);
	liststatus = 0;
	bus_for_each_dev(&maple_bus_type, NULL, NULL,
			 setup_maple_commands);
	if (time_after(jiffies, maple_pnp_time))
		maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL;
	if (liststatus && list_empty(&maple_sentq)) {
		INIT_LIST_HEAD(&maple_sentq);
		maple_send();
	}
	maplebus_dma_reset();
418 419 420 421 422
}

/* handle devices added via hotplugs - placing them on queue for DEVINFO*/
static void maple_map_subunits(struct maple_device *mdev, int submask)
{
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
	int retval, k, devcheck;
	struct maple_device *mdev_add;
	struct maple_device_specify ds;

	for (k = 0; k < 5; k++) {
		ds.port = mdev->port;
		ds.unit = k + 1;
		retval =
		    bus_for_each_dev(&maple_bus_type, NULL, &ds,
				     detach_maple_device);
		if (retval) {
			submask = submask >> 1;
			continue;
		}
		devcheck = submask & 0x01;
		if (devcheck) {
			mdev_add = maple_alloc_dev(mdev->port, k + 1);
			if (!mdev_add)
				return;
			mdev_add->mq->command = MAPLE_COMMAND_DEVINFO;
			mdev_add->mq->length = 0;
			maple_add_packet(mdev_add->mq);
			scanning = 1;
		}
		submask = submask >> 1;
	}
449 450 451 452 453
}

/* mark a device as removed */
static void maple_clean_submap(struct maple_device *mdev)
{
454
	int killbit;
455

456 457 458 459
	killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20);
	killbit = ~killbit;
	killbit &= 0xFF;
	subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit;
460 461 462 463
}

/* handle empty port or hotplug removal */
static void maple_response_none(struct maple_device *mdev,
464
				struct mapleq *mq)
465
{
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
	if (mdev->unit != 0) {
		list_del(&mq->list);
		maple_clean_submap(mdev);
		printk(KERN_INFO
		       "Maple bus device detaching at (%d, %d)\n",
		       mdev->port, mdev->unit);
		maple_detach_driver(mdev);
		return;
	}
	if (!started) {
		printk(KERN_INFO "No maple devices attached to port %d\n",
		       mdev->port);
		return;
	}
	maple_clean_submap(mdev);
481 482 483 484
}

/* preprocess hotplugs or scans */
static void maple_response_devinfo(struct maple_device *mdev,
485
				   char *recvbuf)
486
{
487 488 489 490 491 492 493 494 495 496 497 498
	char submask;
	if ((!started) || (scanning == 2)) {
		maple_attach_driver(mdev);
		return;
	}
	if (mdev->unit == 0) {
		submask = recvbuf[2] & 0x1F;
		if (submask ^ subdevice_map[mdev->port]) {
			maple_map_subunits(mdev, submask);
			subdevice_map[mdev->port] = submask;
		}
	}
499 500 501 502 503
}

/* maple dma end bottom half - implemented via workqueue */
static void maple_dma_handler(struct work_struct *work)
{
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
	struct mapleq *mq, *nmq;
	struct maple_device *dev;
	char *recvbuf;
	enum maple_code code;

	if (!maple_dma_done())
		return;
	ctrl_outl(0, MAPLE_ENABLE);
	if (!list_empty(&maple_sentq)) {
		list_for_each_entry_safe(mq, nmq, &maple_sentq, list) {
			recvbuf = mq->recvbuf;
			code = recvbuf[0];
			dev = mq->dev;
			switch (code) {
			case MAPLE_RESPONSE_NONE:
				maple_response_none(dev, mq);
				break;

			case MAPLE_RESPONSE_DEVINFO:
				maple_response_devinfo(dev, recvbuf);
				break;

			case MAPLE_RESPONSE_DATATRF:
				if (dev->callback)
					dev->callback(mq);
				break;

			case MAPLE_RESPONSE_FILEERR:
			case MAPLE_RESPONSE_AGAIN:
			case MAPLE_RESPONSE_BADCMD:
			case MAPLE_RESPONSE_BADFUNC:
				printk(KERN_DEBUG
				       "Maple non-fatal error 0x%X\n",
				       code);
				break;

			case MAPLE_RESPONSE_ALLINFO:
				printk(KERN_DEBUG
542 543
				       "Maple - extended device information"
					" not supported\n");
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
				break;

			case MAPLE_RESPONSE_OK:
				break;

			default:
				break;
			}
		}
		INIT_LIST_HEAD(&maple_sentq);
		if (scanning == 1) {
			maple_send();
			scanning = 2;
		} else
			scanning = 0;

		if (started == 0)
			started = 1;
	}
	maplebus_dma_reset();
564 565 566 567
}

static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id)
{
568 569 570
	/* Load everything into the bottom half */
	schedule_work(&maple_dma_process);
	return IRQ_HANDLED;
571 572 573 574
}

static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id)
{
575 576
	schedule_work(&maple_vblank_process);
	return IRQ_HANDLED;
577 578 579 580
}

static int maple_set_dma_interrupt_handler(void)
{
581 582
	return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt,
		IRQF_SHARED, "maple bus DMA", &maple_dummy_driver);
583 584 585 586
}

static int maple_set_vblank_interrupt_handler(void)
{
587 588
	return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt,
		IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver);
589 590 591 592
}

static int maple_get_dma_buffer(void)
{
593 594 595 596 597 598
	maple_sendbuf =
	    (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
				      MAPLE_DMA_PAGES);
	if (!maple_sendbuf)
		return -ENOMEM;
	return 0;
599 600 601
}

static int match_maple_bus_driver(struct device *devptr,
602
				  struct device_driver *drvptr)
603
{
604 605 606 607 608 609 610 611 612 613 614 615
	struct maple_driver *maple_drv;
	struct maple_device *maple_dev;

	maple_drv = container_of(drvptr, struct maple_driver, drv);
	maple_dev = container_of(devptr, struct maple_device, dev);
	/* Trap empty port case */
	if (maple_dev->devinfo.function == 0xFFFFFFFF)
		return 0;
	else if (maple_dev->devinfo.function &
		 be32_to_cpu(maple_drv->function))
		return 1;
	return 0;
616 617
}

618 619
static int maple_bus_uevent(struct device *dev,
			    struct kobj_uevent_env *env)
620
{
621
	return 0;
622 623 624 625 626 627 628
}

static void maple_bus_release(struct device *dev)
{
}

static struct maple_driver maple_dummy_driver = {
629 630 631
	.drv = {
		.name = "maple_dummy_driver",
		.bus = &maple_bus_type,
632
	},
633 634 635
};

struct bus_type maple_bus_type = {
636 637 638
	.name = "maple",
	.match = match_maple_bus_driver,
	.uevent = maple_bus_uevent,
639 640 641 642
};
EXPORT_SYMBOL_GPL(maple_bus_type);

static struct device maple_bus = {
643 644
	.bus_id = "maple",
	.release = maple_bus_release,
645 646 647 648
};

static int __init maple_bus_init(void)
{
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
	int retval, i;
	struct maple_device *mdev[MAPLE_PORTS];
	ctrl_outl(0, MAPLE_STATE);

	retval = device_register(&maple_bus);
	if (retval)
		goto cleanup;

	retval = bus_register(&maple_bus_type);
	if (retval)
		goto cleanup_device;

	retval = driver_register(&maple_dummy_driver.drv);
	if (retval)
		goto cleanup_bus;

	/* allocate memory for maple bus dma */
	retval = maple_get_dma_buffer();
	if (retval) {
		printk(KERN_INFO
		       "Maple bus: Failed to allocate Maple DMA buffers\n");
		goto cleanup_basic;
	}

	/* set up DMA interrupt handler */
	retval = maple_set_dma_interrupt_handler();
	if (retval) {
		printk(KERN_INFO
		       "Maple bus: Failed to grab maple DMA IRQ\n");
		goto cleanup_dma;
	}

	/* set up VBLANK interrupt handler */
	retval = maple_set_vblank_interrupt_handler();
	if (retval) {
		printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n");
		goto cleanup_irq;
	}

	maple_queue_cache =
	    kmem_cache_create("maple_queue_cache", 0x400, 0,
690
			      SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL);
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705

	if (!maple_queue_cache)
		goto cleanup_bothirqs;

	/* setup maple ports */
	for (i = 0; i < MAPLE_PORTS; i++) {
		mdev[i] = maple_alloc_dev(i, 0);
		if (!mdev[i]) {
			while (i-- > 0)
				maple_free_dev(mdev[i]);
			goto cleanup_cache;
		}
		mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO;
		mdev[i]->mq->length = 0;
		maple_add_packet(mdev[i]->mq);
706
		/* delay aids hardware detection */
707
		mdelay(5);
708 709 710
		subdevice_map[i] = 0;
	}

711
	realscan = 1;
712 713 714 715 716 717 718 719 720
	/* setup maplebus hardware */
	maplebus_dma_reset();
	/* initial detection */
	maple_send();
	maple_pnp_time = jiffies;
	printk(KERN_INFO "Maple bus core now registered.\n");

	return 0;

721
cleanup_cache:
722 723
	kmem_cache_destroy(maple_queue_cache);

724
cleanup_bothirqs:
725 726
	free_irq(HW_EVENT_VSYNC, 0);

727
cleanup_irq:
728 729
	free_irq(HW_EVENT_MAPLE_DMA, 0);

730
cleanup_dma:
731 732
	free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);

733
cleanup_basic:
734 735
	driver_unregister(&maple_dummy_driver.drv);

736
cleanup_bus:
737 738
	bus_unregister(&maple_bus_type);

739
cleanup_device:
740 741
	device_unregister(&maple_bus);

742
cleanup:
743 744
	printk(KERN_INFO "Maple bus registration failed\n");
	return retval;
745
}
746 747
/* Push init to later to ensure hardware gets detected */
fs_initcall(maple_bus_init);