1/* $NetBSD: ezload.c,v 1.11 2006/04/14 17:21:17 christos Exp $ */ 2 3/* 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson <lennart@augustsson.net>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: ezload.c,v 1.11 2006/04/14 17:21:17 christos Exp $"); 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/device.h> 39#include <sys/conf.h> 40 41#include <dev/usb/usb.h> 42#include <dev/usb/usbdi.h> 43#include <dev/usb/usbdi_util.h> 44 45#include <dev/usb/ezload.h> 46 47/* 48 * Vendor specific request code for Anchor Upload/Download 49 */ 50 51/* This one is implemented in the core */ 52#define ANCHOR_LOAD_INTERNAL 0xA0 53 54/* This is the highest internal RAM address for the AN2131Q */ 55#define ANCHOR_MAX_INTERNAL_ADDRESS 0x1B3F 56 57/* 58 * EZ-USB Control and Status Register. Bit 0 controls 8051 reset 59 */ 60#define ANCHOR_CPUCS_REG 0x7F92 61#define ANCHOR_RESET 0x01 62 63/* 64 * Although USB does not limit you here, the Anchor docs 65 * quote 64 as a limit, and Mato@activewireinc.com suggested 66 * to use 16. 67 */ 68#define ANCHOR_CHUNK 16 69 70/* 71 * This is a firmware loader for ezusb (Anchor) devices. When the firmware 72 * has been downloaded the device will simulate a disconnect and when it 73 * is next recognized by the USB software it will appear as another 74 * device. 75 */ 76 77#ifdef USB_DEBUG 78#define DPRINTF(x) if (ezloaddebug) printf x 79#define DPRINTFN(n,x) if (ezloaddebug>(n)) printf x 80int ezloaddebug = 0; 81#else 82#define DPRINTF(x) 83#define DPRINTFN(n,x) 84#endif 85 86usbd_status 87ezload_reset(usbd_device_handle dev, int reset) 88{ 89 usb_device_request_t req; 90 uByte rst; 91 92 DPRINTF(("ezload_reset: reset=%d\n", reset)); 93 94 rst = reset ? ANCHOR_RESET : 0; 95 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 96 req.bRequest = ANCHOR_LOAD_INTERNAL; 97 USETW(req.wValue, ANCHOR_CPUCS_REG); 98 USETW(req.wIndex, 0); 99 USETW(req.wLength, 1); 100 return (usbd_do_request(dev, &req, &rst)); 101} 102 103usbd_status 104ezload_download(usbd_device_handle dev, const struct ezdata *rec) 105{ 106 usb_device_request_t req; 107 const struct ezdata *ptr; 108 u_int len, offs; 109 int err; 110 111 DPRINTF(("ezload_down record=%p\n", rec)); 112 113 for (ptr = rec; ptr->length != 0; ptr++) { 114 115#if 0 116 if (ptr->address + ptr->length > ANCHOR_MAX_INTERNAL_ADDRESS) 117 return (USBD_INVAL); 118#endif 119 120 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 121 req.bRequest = ANCHOR_LOAD_INTERNAL; 122 USETW(req.wIndex, 0); 123 for (offs = 0; offs < ptr->length; offs += ANCHOR_CHUNK) { 124 len = ptr->length - offs; 125 if (len > ANCHOR_CHUNK) 126 len = ANCHOR_CHUNK; 127 USETW(req.wValue, ptr->address + offs); 128 USETW(req.wLength, len); 129 DPRINTFN(2,("ezload_download: addr=0x%x len=%d\n", 130 ptr->address + offs, len)); 131 /*XXXUNCONST*/ 132 err = usbd_do_request(dev, &req, 133 __UNCONST(ptr->data + offs)); 134 if (err) 135 return (err); 136 } 137 } 138 139 return (0); 140} 141 142usbd_status 143ezload_downloads_and_reset(usbd_device_handle dev, const struct ezdata **recs) 144{ 145 usbd_status err; 146 147 /*(void)ezload_reset(dev, 1);*/ 148 err = ezload_reset(dev, 1); 149 if (err) 150 return (err); 151 usbd_delay_ms(dev, 250); 152 while (*recs != NULL) { 153 err = ezload_download(dev, *recs++); 154 if (err) 155 return (err); 156 } 157 usbd_delay_ms(dev, 250); 158 err = ezload_reset(dev, 0); 159 usbd_delay_ms(dev, 250); 160 return (err); 161} 162