1*a2f3d83cSJiri Slaby (SUSE) // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2*a2f3d83cSJiri Slaby (SUSE) /* 3*a2f3d83cSJiri Slaby (SUSE) * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles 4*a2f3d83cSJiri Slaby (SUSE) * 5*a2f3d83cSJiri Slaby (SUSE) * Main part 6*a2f3d83cSJiri Slaby (SUSE) * 7*a2f3d83cSJiri Slaby (SUSE) * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria 8*a2f3d83cSJiri Slaby (SUSE) * 9*a2f3d83cSJiri Slaby (SUSE) * If distributed as part of the Linux kernel, this code is licensed under the 10*a2f3d83cSJiri Slaby (SUSE) * terms of the GPL v2. 11*a2f3d83cSJiri Slaby (SUSE) * 12*a2f3d83cSJiri Slaby (SUSE) * Otherwise, the following license terms apply: 13*a2f3d83cSJiri Slaby (SUSE) * 14*a2f3d83cSJiri Slaby (SUSE) * * Redistribution and use in source and binary forms, with or without 15*a2f3d83cSJiri Slaby (SUSE) * * modification, are permitted provided that the following conditions 16*a2f3d83cSJiri Slaby (SUSE) * * are met: 17*a2f3d83cSJiri Slaby (SUSE) * * 1) Redistributions of source code must retain the above copyright 18*a2f3d83cSJiri Slaby (SUSE) * * notice, this list of conditions and the following disclaimer. 19*a2f3d83cSJiri Slaby (SUSE) * * 2) Redistributions in binary form must reproduce the above copyright 20*a2f3d83cSJiri Slaby (SUSE) * * notice, this list of conditions and the following disclaimer in the 21*a2f3d83cSJiri Slaby (SUSE) * * documentation and/or other materials provided with the distribution. 22*a2f3d83cSJiri Slaby (SUSE) * * 3) The name of the author may not be used to endorse or promote products 23*a2f3d83cSJiri Slaby (SUSE) * * derived from this software without specific psisusbr written permission. 24*a2f3d83cSJiri Slaby (SUSE) * * 25*a2f3d83cSJiri Slaby (SUSE) * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR 26*a2f3d83cSJiri Slaby (SUSE) * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27*a2f3d83cSJiri Slaby (SUSE) * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28*a2f3d83cSJiri Slaby (SUSE) * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29*a2f3d83cSJiri Slaby (SUSE) * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30*a2f3d83cSJiri Slaby (SUSE) * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31*a2f3d83cSJiri Slaby (SUSE) * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32*a2f3d83cSJiri Slaby (SUSE) * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33*a2f3d83cSJiri Slaby (SUSE) * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34*a2f3d83cSJiri Slaby (SUSE) * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35*a2f3d83cSJiri Slaby (SUSE) * 36*a2f3d83cSJiri Slaby (SUSE) * Author: Thomas Winischhofer <thomas@winischhofer.net> 37*a2f3d83cSJiri Slaby (SUSE) * 38*a2f3d83cSJiri Slaby (SUSE) */ 39*a2f3d83cSJiri Slaby (SUSE) 40*a2f3d83cSJiri Slaby (SUSE) #include <linux/mutex.h> 41*a2f3d83cSJiri Slaby (SUSE) #include <linux/module.h> 42*a2f3d83cSJiri Slaby (SUSE) #include <linux/kernel.h> 43*a2f3d83cSJiri Slaby (SUSE) #include <linux/signal.h> 44*a2f3d83cSJiri Slaby (SUSE) #include <linux/errno.h> 45*a2f3d83cSJiri Slaby (SUSE) #include <linux/poll.h> 46*a2f3d83cSJiri Slaby (SUSE) #include <linux/init.h> 47*a2f3d83cSJiri Slaby (SUSE) #include <linux/slab.h> 48*a2f3d83cSJiri Slaby (SUSE) #include <linux/spinlock.h> 49*a2f3d83cSJiri Slaby (SUSE) #include <linux/kref.h> 50*a2f3d83cSJiri Slaby (SUSE) #include <linux/usb.h> 51*a2f3d83cSJiri Slaby (SUSE) #include <linux/vmalloc.h> 52*a2f3d83cSJiri Slaby (SUSE) 53*a2f3d83cSJiri Slaby (SUSE) #include "sisusb.h" 54*a2f3d83cSJiri Slaby (SUSE) 55*a2f3d83cSJiri Slaby (SUSE) #define SISUSB_DONTSYNC 56*a2f3d83cSJiri Slaby (SUSE) 57*a2f3d83cSJiri Slaby (SUSE) /* Forward declarations / clean-up routines */ 58*a2f3d83cSJiri Slaby (SUSE) 59*a2f3d83cSJiri Slaby (SUSE) static struct usb_driver sisusb_driver; 60*a2f3d83cSJiri Slaby (SUSE) 61*a2f3d83cSJiri Slaby (SUSE) static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) 62*a2f3d83cSJiri Slaby (SUSE) { 63*a2f3d83cSJiri Slaby (SUSE) int i; 64*a2f3d83cSJiri Slaby (SUSE) 65*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < NUMOBUFS; i++) { 66*a2f3d83cSJiri Slaby (SUSE) kfree(sisusb->obuf[i]); 67*a2f3d83cSJiri Slaby (SUSE) sisusb->obuf[i] = NULL; 68*a2f3d83cSJiri Slaby (SUSE) } 69*a2f3d83cSJiri Slaby (SUSE) kfree(sisusb->ibuf); 70*a2f3d83cSJiri Slaby (SUSE) sisusb->ibuf = NULL; 71*a2f3d83cSJiri Slaby (SUSE) } 72*a2f3d83cSJiri Slaby (SUSE) 73*a2f3d83cSJiri Slaby (SUSE) static void sisusb_free_urbs(struct sisusb_usb_data *sisusb) 74*a2f3d83cSJiri Slaby (SUSE) { 75*a2f3d83cSJiri Slaby (SUSE) int i; 76*a2f3d83cSJiri Slaby (SUSE) 77*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < NUMOBUFS; i++) { 78*a2f3d83cSJiri Slaby (SUSE) usb_free_urb(sisusb->sisurbout[i]); 79*a2f3d83cSJiri Slaby (SUSE) sisusb->sisurbout[i] = NULL; 80*a2f3d83cSJiri Slaby (SUSE) } 81*a2f3d83cSJiri Slaby (SUSE) usb_free_urb(sisusb->sisurbin); 82*a2f3d83cSJiri Slaby (SUSE) sisusb->sisurbin = NULL; 83*a2f3d83cSJiri Slaby (SUSE) } 84*a2f3d83cSJiri Slaby (SUSE) 85*a2f3d83cSJiri Slaby (SUSE) /* Level 0: USB transport layer */ 86*a2f3d83cSJiri Slaby (SUSE) 87*a2f3d83cSJiri Slaby (SUSE) /* 1. out-bulks */ 88*a2f3d83cSJiri Slaby (SUSE) 89*a2f3d83cSJiri Slaby (SUSE) /* out-urb management */ 90*a2f3d83cSJiri Slaby (SUSE) 91*a2f3d83cSJiri Slaby (SUSE) /* Return 1 if all free, 0 otherwise */ 92*a2f3d83cSJiri Slaby (SUSE) static int sisusb_all_free(struct sisusb_usb_data *sisusb) 93*a2f3d83cSJiri Slaby (SUSE) { 94*a2f3d83cSJiri Slaby (SUSE) int i; 95*a2f3d83cSJiri Slaby (SUSE) 96*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < sisusb->numobufs; i++) { 97*a2f3d83cSJiri Slaby (SUSE) 98*a2f3d83cSJiri Slaby (SUSE) if (sisusb->urbstatus[i] & SU_URB_BUSY) 99*a2f3d83cSJiri Slaby (SUSE) return 0; 100*a2f3d83cSJiri Slaby (SUSE) 101*a2f3d83cSJiri Slaby (SUSE) } 102*a2f3d83cSJiri Slaby (SUSE) 103*a2f3d83cSJiri Slaby (SUSE) return 1; 104*a2f3d83cSJiri Slaby (SUSE) } 105*a2f3d83cSJiri Slaby (SUSE) 106*a2f3d83cSJiri Slaby (SUSE) /* Kill all busy URBs */ 107*a2f3d83cSJiri Slaby (SUSE) static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) 108*a2f3d83cSJiri Slaby (SUSE) { 109*a2f3d83cSJiri Slaby (SUSE) int i; 110*a2f3d83cSJiri Slaby (SUSE) 111*a2f3d83cSJiri Slaby (SUSE) if (sisusb_all_free(sisusb)) 112*a2f3d83cSJiri Slaby (SUSE) return; 113*a2f3d83cSJiri Slaby (SUSE) 114*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < sisusb->numobufs; i++) { 115*a2f3d83cSJiri Slaby (SUSE) 116*a2f3d83cSJiri Slaby (SUSE) if (sisusb->urbstatus[i] & SU_URB_BUSY) 117*a2f3d83cSJiri Slaby (SUSE) usb_kill_urb(sisusb->sisurbout[i]); 118*a2f3d83cSJiri Slaby (SUSE) 119*a2f3d83cSJiri Slaby (SUSE) } 120*a2f3d83cSJiri Slaby (SUSE) } 121*a2f3d83cSJiri Slaby (SUSE) 122*a2f3d83cSJiri Slaby (SUSE) /* Return 1 if ok, 0 if error (not all complete within timeout) */ 123*a2f3d83cSJiri Slaby (SUSE) static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb) 124*a2f3d83cSJiri Slaby (SUSE) { 125*a2f3d83cSJiri Slaby (SUSE) int timeout = 5 * HZ, i = 1; 126*a2f3d83cSJiri Slaby (SUSE) 127*a2f3d83cSJiri Slaby (SUSE) wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)), 128*a2f3d83cSJiri Slaby (SUSE) timeout); 129*a2f3d83cSJiri Slaby (SUSE) 130*a2f3d83cSJiri Slaby (SUSE) return i; 131*a2f3d83cSJiri Slaby (SUSE) } 132*a2f3d83cSJiri Slaby (SUSE) 133*a2f3d83cSJiri Slaby (SUSE) static int sisusb_outurb_available(struct sisusb_usb_data *sisusb) 134*a2f3d83cSJiri Slaby (SUSE) { 135*a2f3d83cSJiri Slaby (SUSE) int i; 136*a2f3d83cSJiri Slaby (SUSE) 137*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < sisusb->numobufs; i++) { 138*a2f3d83cSJiri Slaby (SUSE) 139*a2f3d83cSJiri Slaby (SUSE) if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0) 140*a2f3d83cSJiri Slaby (SUSE) return i; 141*a2f3d83cSJiri Slaby (SUSE) 142*a2f3d83cSJiri Slaby (SUSE) } 143*a2f3d83cSJiri Slaby (SUSE) 144*a2f3d83cSJiri Slaby (SUSE) return -1; 145*a2f3d83cSJiri Slaby (SUSE) } 146*a2f3d83cSJiri Slaby (SUSE) 147*a2f3d83cSJiri Slaby (SUSE) static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb) 148*a2f3d83cSJiri Slaby (SUSE) { 149*a2f3d83cSJiri Slaby (SUSE) int i, timeout = 5 * HZ; 150*a2f3d83cSJiri Slaby (SUSE) 151*a2f3d83cSJiri Slaby (SUSE) wait_event_timeout(sisusb->wait_q, 152*a2f3d83cSJiri Slaby (SUSE) ((i = sisusb_outurb_available(sisusb)) >= 0), timeout); 153*a2f3d83cSJiri Slaby (SUSE) 154*a2f3d83cSJiri Slaby (SUSE) return i; 155*a2f3d83cSJiri Slaby (SUSE) } 156*a2f3d83cSJiri Slaby (SUSE) 157*a2f3d83cSJiri Slaby (SUSE) static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) 158*a2f3d83cSJiri Slaby (SUSE) { 159*a2f3d83cSJiri Slaby (SUSE) int i; 160*a2f3d83cSJiri Slaby (SUSE) 161*a2f3d83cSJiri Slaby (SUSE) i = sisusb_outurb_available(sisusb); 162*a2f3d83cSJiri Slaby (SUSE) 163*a2f3d83cSJiri Slaby (SUSE) if (i >= 0) 164*a2f3d83cSJiri Slaby (SUSE) sisusb->urbstatus[i] |= SU_URB_ALLOC; 165*a2f3d83cSJiri Slaby (SUSE) 166*a2f3d83cSJiri Slaby (SUSE) return i; 167*a2f3d83cSJiri Slaby (SUSE) } 168*a2f3d83cSJiri Slaby (SUSE) 169*a2f3d83cSJiri Slaby (SUSE) static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) 170*a2f3d83cSJiri Slaby (SUSE) { 171*a2f3d83cSJiri Slaby (SUSE) if ((index >= 0) && (index < sisusb->numobufs)) 172*a2f3d83cSJiri Slaby (SUSE) sisusb->urbstatus[index] &= ~SU_URB_ALLOC; 173*a2f3d83cSJiri Slaby (SUSE) } 174*a2f3d83cSJiri Slaby (SUSE) 175*a2f3d83cSJiri Slaby (SUSE) /* completion callback */ 176*a2f3d83cSJiri Slaby (SUSE) 177*a2f3d83cSJiri Slaby (SUSE) static void sisusb_bulk_completeout(struct urb *urb) 178*a2f3d83cSJiri Slaby (SUSE) { 179*a2f3d83cSJiri Slaby (SUSE) struct sisusb_urb_context *context = urb->context; 180*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 181*a2f3d83cSJiri Slaby (SUSE) 182*a2f3d83cSJiri Slaby (SUSE) if (!context) 183*a2f3d83cSJiri Slaby (SUSE) return; 184*a2f3d83cSJiri Slaby (SUSE) 185*a2f3d83cSJiri Slaby (SUSE) sisusb = context->sisusb; 186*a2f3d83cSJiri Slaby (SUSE) 187*a2f3d83cSJiri Slaby (SUSE) if (!sisusb || !sisusb->sisusb_dev || !sisusb->present) 188*a2f3d83cSJiri Slaby (SUSE) return; 189*a2f3d83cSJiri Slaby (SUSE) 190*a2f3d83cSJiri Slaby (SUSE) #ifndef SISUSB_DONTSYNC 191*a2f3d83cSJiri Slaby (SUSE) if (context->actual_length) 192*a2f3d83cSJiri Slaby (SUSE) *(context->actual_length) += urb->actual_length; 193*a2f3d83cSJiri Slaby (SUSE) #endif 194*a2f3d83cSJiri Slaby (SUSE) 195*a2f3d83cSJiri Slaby (SUSE) sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY; 196*a2f3d83cSJiri Slaby (SUSE) wake_up(&sisusb->wait_q); 197*a2f3d83cSJiri Slaby (SUSE) } 198*a2f3d83cSJiri Slaby (SUSE) 199*a2f3d83cSJiri Slaby (SUSE) static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, 200*a2f3d83cSJiri Slaby (SUSE) unsigned int pipe, void *data, int len, int *actual_length, 201*a2f3d83cSJiri Slaby (SUSE) int timeout, unsigned int tflags) 202*a2f3d83cSJiri Slaby (SUSE) { 203*a2f3d83cSJiri Slaby (SUSE) struct urb *urb = sisusb->sisurbout[index]; 204*a2f3d83cSJiri Slaby (SUSE) int retval, byteswritten = 0; 205*a2f3d83cSJiri Slaby (SUSE) 206*a2f3d83cSJiri Slaby (SUSE) /* Set up URB */ 207*a2f3d83cSJiri Slaby (SUSE) urb->transfer_flags = 0; 208*a2f3d83cSJiri Slaby (SUSE) 209*a2f3d83cSJiri Slaby (SUSE) usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len, 210*a2f3d83cSJiri Slaby (SUSE) sisusb_bulk_completeout, 211*a2f3d83cSJiri Slaby (SUSE) &sisusb->urbout_context[index]); 212*a2f3d83cSJiri Slaby (SUSE) 213*a2f3d83cSJiri Slaby (SUSE) urb->transfer_flags |= tflags; 214*a2f3d83cSJiri Slaby (SUSE) urb->actual_length = 0; 215*a2f3d83cSJiri Slaby (SUSE) 216*a2f3d83cSJiri Slaby (SUSE) /* Set up context */ 217*a2f3d83cSJiri Slaby (SUSE) sisusb->urbout_context[index].actual_length = (timeout) ? 218*a2f3d83cSJiri Slaby (SUSE) NULL : actual_length; 219*a2f3d83cSJiri Slaby (SUSE) 220*a2f3d83cSJiri Slaby (SUSE) /* Declare this urb/buffer in use */ 221*a2f3d83cSJiri Slaby (SUSE) sisusb->urbstatus[index] |= SU_URB_BUSY; 222*a2f3d83cSJiri Slaby (SUSE) 223*a2f3d83cSJiri Slaby (SUSE) /* Submit URB */ 224*a2f3d83cSJiri Slaby (SUSE) retval = usb_submit_urb(urb, GFP_KERNEL); 225*a2f3d83cSJiri Slaby (SUSE) 226*a2f3d83cSJiri Slaby (SUSE) /* If OK, and if timeout > 0, wait for completion */ 227*a2f3d83cSJiri Slaby (SUSE) if ((retval == 0) && timeout) { 228*a2f3d83cSJiri Slaby (SUSE) wait_event_timeout(sisusb->wait_q, 229*a2f3d83cSJiri Slaby (SUSE) (!(sisusb->urbstatus[index] & SU_URB_BUSY)), 230*a2f3d83cSJiri Slaby (SUSE) timeout); 231*a2f3d83cSJiri Slaby (SUSE) if (sisusb->urbstatus[index] & SU_URB_BUSY) { 232*a2f3d83cSJiri Slaby (SUSE) /* URB timed out... kill it and report error */ 233*a2f3d83cSJiri Slaby (SUSE) usb_kill_urb(urb); 234*a2f3d83cSJiri Slaby (SUSE) retval = -ETIMEDOUT; 235*a2f3d83cSJiri Slaby (SUSE) } else { 236*a2f3d83cSJiri Slaby (SUSE) /* Otherwise, report urb status */ 237*a2f3d83cSJiri Slaby (SUSE) retval = urb->status; 238*a2f3d83cSJiri Slaby (SUSE) byteswritten = urb->actual_length; 239*a2f3d83cSJiri Slaby (SUSE) } 240*a2f3d83cSJiri Slaby (SUSE) } 241*a2f3d83cSJiri Slaby (SUSE) 242*a2f3d83cSJiri Slaby (SUSE) if (actual_length) 243*a2f3d83cSJiri Slaby (SUSE) *actual_length = byteswritten; 244*a2f3d83cSJiri Slaby (SUSE) 245*a2f3d83cSJiri Slaby (SUSE) return retval; 246*a2f3d83cSJiri Slaby (SUSE) } 247*a2f3d83cSJiri Slaby (SUSE) 248*a2f3d83cSJiri Slaby (SUSE) /* 2. in-bulks */ 249*a2f3d83cSJiri Slaby (SUSE) 250*a2f3d83cSJiri Slaby (SUSE) /* completion callback */ 251*a2f3d83cSJiri Slaby (SUSE) 252*a2f3d83cSJiri Slaby (SUSE) static void sisusb_bulk_completein(struct urb *urb) 253*a2f3d83cSJiri Slaby (SUSE) { 254*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb = urb->context; 255*a2f3d83cSJiri Slaby (SUSE) 256*a2f3d83cSJiri Slaby (SUSE) if (!sisusb || !sisusb->sisusb_dev || !sisusb->present) 257*a2f3d83cSJiri Slaby (SUSE) return; 258*a2f3d83cSJiri Slaby (SUSE) 259*a2f3d83cSJiri Slaby (SUSE) sisusb->completein = 1; 260*a2f3d83cSJiri Slaby (SUSE) wake_up(&sisusb->wait_q); 261*a2f3d83cSJiri Slaby (SUSE) } 262*a2f3d83cSJiri Slaby (SUSE) 263*a2f3d83cSJiri Slaby (SUSE) static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, 264*a2f3d83cSJiri Slaby (SUSE) unsigned int pipe, void *data, int len, 265*a2f3d83cSJiri Slaby (SUSE) int *actual_length, int timeout, unsigned int tflags) 266*a2f3d83cSJiri Slaby (SUSE) { 267*a2f3d83cSJiri Slaby (SUSE) struct urb *urb = sisusb->sisurbin; 268*a2f3d83cSJiri Slaby (SUSE) int retval, readbytes = 0; 269*a2f3d83cSJiri Slaby (SUSE) 270*a2f3d83cSJiri Slaby (SUSE) urb->transfer_flags = 0; 271*a2f3d83cSJiri Slaby (SUSE) 272*a2f3d83cSJiri Slaby (SUSE) usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len, 273*a2f3d83cSJiri Slaby (SUSE) sisusb_bulk_completein, sisusb); 274*a2f3d83cSJiri Slaby (SUSE) 275*a2f3d83cSJiri Slaby (SUSE) urb->transfer_flags |= tflags; 276*a2f3d83cSJiri Slaby (SUSE) urb->actual_length = 0; 277*a2f3d83cSJiri Slaby (SUSE) 278*a2f3d83cSJiri Slaby (SUSE) sisusb->completein = 0; 279*a2f3d83cSJiri Slaby (SUSE) retval = usb_submit_urb(urb, GFP_KERNEL); 280*a2f3d83cSJiri Slaby (SUSE) if (retval == 0) { 281*a2f3d83cSJiri Slaby (SUSE) wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout); 282*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->completein) { 283*a2f3d83cSJiri Slaby (SUSE) /* URB timed out... kill it and report error */ 284*a2f3d83cSJiri Slaby (SUSE) usb_kill_urb(urb); 285*a2f3d83cSJiri Slaby (SUSE) retval = -ETIMEDOUT; 286*a2f3d83cSJiri Slaby (SUSE) } else { 287*a2f3d83cSJiri Slaby (SUSE) /* URB completed within timeout */ 288*a2f3d83cSJiri Slaby (SUSE) retval = urb->status; 289*a2f3d83cSJiri Slaby (SUSE) readbytes = urb->actual_length; 290*a2f3d83cSJiri Slaby (SUSE) } 291*a2f3d83cSJiri Slaby (SUSE) } 292*a2f3d83cSJiri Slaby (SUSE) 293*a2f3d83cSJiri Slaby (SUSE) if (actual_length) 294*a2f3d83cSJiri Slaby (SUSE) *actual_length = readbytes; 295*a2f3d83cSJiri Slaby (SUSE) 296*a2f3d83cSJiri Slaby (SUSE) return retval; 297*a2f3d83cSJiri Slaby (SUSE) } 298*a2f3d83cSJiri Slaby (SUSE) 299*a2f3d83cSJiri Slaby (SUSE) 300*a2f3d83cSJiri Slaby (SUSE) /* Level 1: */ 301*a2f3d83cSJiri Slaby (SUSE) 302*a2f3d83cSJiri Slaby (SUSE) /* Send a bulk message of variable size 303*a2f3d83cSJiri Slaby (SUSE) * 304*a2f3d83cSJiri Slaby (SUSE) * To copy the data from userspace, give pointer to "userbuffer", 305*a2f3d83cSJiri Slaby (SUSE) * to copy from (non-DMA) kernel memory, give "kernbuffer". If 306*a2f3d83cSJiri Slaby (SUSE) * both of these are NULL, it is assumed, that the transfer 307*a2f3d83cSJiri Slaby (SUSE) * buffer "sisusb->obuf[index]" is set up with the data to send. 308*a2f3d83cSJiri Slaby (SUSE) * Index is ignored if either kernbuffer or userbuffer is set. 309*a2f3d83cSJiri Slaby (SUSE) * If async is nonzero, URBs will be sent without waiting for 310*a2f3d83cSJiri Slaby (SUSE) * completion of the previous URB. 311*a2f3d83cSJiri Slaby (SUSE) * 312*a2f3d83cSJiri Slaby (SUSE) * (return 0 on success) 313*a2f3d83cSJiri Slaby (SUSE) */ 314*a2f3d83cSJiri Slaby (SUSE) 315*a2f3d83cSJiri Slaby (SUSE) static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, 316*a2f3d83cSJiri Slaby (SUSE) char *kernbuffer, const char __user *userbuffer, int index, 317*a2f3d83cSJiri Slaby (SUSE) ssize_t *bytes_written, unsigned int tflags, int async) 318*a2f3d83cSJiri Slaby (SUSE) { 319*a2f3d83cSJiri Slaby (SUSE) int result = 0, retry, count = len; 320*a2f3d83cSJiri Slaby (SUSE) int passsize, thispass, transferred_len = 0; 321*a2f3d83cSJiri Slaby (SUSE) int fromuser = (userbuffer != NULL) ? 1 : 0; 322*a2f3d83cSJiri Slaby (SUSE) int fromkern = (kernbuffer != NULL) ? 1 : 0; 323*a2f3d83cSJiri Slaby (SUSE) unsigned int pipe; 324*a2f3d83cSJiri Slaby (SUSE) char *buffer; 325*a2f3d83cSJiri Slaby (SUSE) 326*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) = 0; 327*a2f3d83cSJiri Slaby (SUSE) 328*a2f3d83cSJiri Slaby (SUSE) /* Sanity check */ 329*a2f3d83cSJiri Slaby (SUSE) if (!sisusb || !sisusb->present || !sisusb->sisusb_dev) 330*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 331*a2f3d83cSJiri Slaby (SUSE) 332*a2f3d83cSJiri Slaby (SUSE) /* If we copy data from kernel or userspace, force the 333*a2f3d83cSJiri Slaby (SUSE) * allocation of a buffer/urb. If we have the data in 334*a2f3d83cSJiri Slaby (SUSE) * the transfer buffer[index] already, reuse the buffer/URB 335*a2f3d83cSJiri Slaby (SUSE) * if the length is > buffer size. (So, transmitting 336*a2f3d83cSJiri Slaby (SUSE) * large data amounts directly from the transfer buffer 337*a2f3d83cSJiri Slaby (SUSE) * treats the buffer as a ring buffer. However, we need 338*a2f3d83cSJiri Slaby (SUSE) * to sync in this case.) 339*a2f3d83cSJiri Slaby (SUSE) */ 340*a2f3d83cSJiri Slaby (SUSE) if (fromuser || fromkern) 341*a2f3d83cSJiri Slaby (SUSE) index = -1; 342*a2f3d83cSJiri Slaby (SUSE) else if (len > sisusb->obufsize) 343*a2f3d83cSJiri Slaby (SUSE) async = 0; 344*a2f3d83cSJiri Slaby (SUSE) 345*a2f3d83cSJiri Slaby (SUSE) pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep); 346*a2f3d83cSJiri Slaby (SUSE) 347*a2f3d83cSJiri Slaby (SUSE) do { 348*a2f3d83cSJiri Slaby (SUSE) passsize = thispass = (sisusb->obufsize < count) ? 349*a2f3d83cSJiri Slaby (SUSE) sisusb->obufsize : count; 350*a2f3d83cSJiri Slaby (SUSE) 351*a2f3d83cSJiri Slaby (SUSE) if (index < 0) 352*a2f3d83cSJiri Slaby (SUSE) index = sisusb_get_free_outbuf(sisusb); 353*a2f3d83cSJiri Slaby (SUSE) 354*a2f3d83cSJiri Slaby (SUSE) if (index < 0) 355*a2f3d83cSJiri Slaby (SUSE) return -EIO; 356*a2f3d83cSJiri Slaby (SUSE) 357*a2f3d83cSJiri Slaby (SUSE) buffer = sisusb->obuf[index]; 358*a2f3d83cSJiri Slaby (SUSE) 359*a2f3d83cSJiri Slaby (SUSE) if (fromuser) { 360*a2f3d83cSJiri Slaby (SUSE) 361*a2f3d83cSJiri Slaby (SUSE) if (copy_from_user(buffer, userbuffer, passsize)) 362*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 363*a2f3d83cSJiri Slaby (SUSE) 364*a2f3d83cSJiri Slaby (SUSE) userbuffer += passsize; 365*a2f3d83cSJiri Slaby (SUSE) 366*a2f3d83cSJiri Slaby (SUSE) } else if (fromkern) { 367*a2f3d83cSJiri Slaby (SUSE) 368*a2f3d83cSJiri Slaby (SUSE) memcpy(buffer, kernbuffer, passsize); 369*a2f3d83cSJiri Slaby (SUSE) kernbuffer += passsize; 370*a2f3d83cSJiri Slaby (SUSE) 371*a2f3d83cSJiri Slaby (SUSE) } 372*a2f3d83cSJiri Slaby (SUSE) 373*a2f3d83cSJiri Slaby (SUSE) retry = 5; 374*a2f3d83cSJiri Slaby (SUSE) while (thispass) { 375*a2f3d83cSJiri Slaby (SUSE) 376*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->sisusb_dev) 377*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 378*a2f3d83cSJiri Slaby (SUSE) 379*a2f3d83cSJiri Slaby (SUSE) result = sisusb_bulkout_msg(sisusb, index, pipe, 380*a2f3d83cSJiri Slaby (SUSE) buffer, thispass, &transferred_len, 381*a2f3d83cSJiri Slaby (SUSE) async ? 0 : 5 * HZ, tflags); 382*a2f3d83cSJiri Slaby (SUSE) 383*a2f3d83cSJiri Slaby (SUSE) if (result == -ETIMEDOUT) { 384*a2f3d83cSJiri Slaby (SUSE) 385*a2f3d83cSJiri Slaby (SUSE) /* Will not happen if async */ 386*a2f3d83cSJiri Slaby (SUSE) if (!retry--) 387*a2f3d83cSJiri Slaby (SUSE) return -ETIME; 388*a2f3d83cSJiri Slaby (SUSE) 389*a2f3d83cSJiri Slaby (SUSE) continue; 390*a2f3d83cSJiri Slaby (SUSE) } 391*a2f3d83cSJiri Slaby (SUSE) 392*a2f3d83cSJiri Slaby (SUSE) if ((result == 0) && !async && transferred_len) { 393*a2f3d83cSJiri Slaby (SUSE) 394*a2f3d83cSJiri Slaby (SUSE) thispass -= transferred_len; 395*a2f3d83cSJiri Slaby (SUSE) buffer += transferred_len; 396*a2f3d83cSJiri Slaby (SUSE) 397*a2f3d83cSJiri Slaby (SUSE) } else 398*a2f3d83cSJiri Slaby (SUSE) break; 399*a2f3d83cSJiri Slaby (SUSE) } 400*a2f3d83cSJiri Slaby (SUSE) 401*a2f3d83cSJiri Slaby (SUSE) if (result) 402*a2f3d83cSJiri Slaby (SUSE) return result; 403*a2f3d83cSJiri Slaby (SUSE) 404*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) += passsize; 405*a2f3d83cSJiri Slaby (SUSE) count -= passsize; 406*a2f3d83cSJiri Slaby (SUSE) 407*a2f3d83cSJiri Slaby (SUSE) /* Force new allocation in next iteration */ 408*a2f3d83cSJiri Slaby (SUSE) if (fromuser || fromkern) 409*a2f3d83cSJiri Slaby (SUSE) index = -1; 410*a2f3d83cSJiri Slaby (SUSE) 411*a2f3d83cSJiri Slaby (SUSE) } while (count > 0); 412*a2f3d83cSJiri Slaby (SUSE) 413*a2f3d83cSJiri Slaby (SUSE) if (async) { 414*a2f3d83cSJiri Slaby (SUSE) #ifdef SISUSB_DONTSYNC 415*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) = len; 416*a2f3d83cSJiri Slaby (SUSE) /* Some URBs/buffers might be busy */ 417*a2f3d83cSJiri Slaby (SUSE) #else 418*a2f3d83cSJiri Slaby (SUSE) sisusb_wait_all_out_complete(sisusb); 419*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) = transferred_len; 420*a2f3d83cSJiri Slaby (SUSE) /* All URBs and all buffers are available */ 421*a2f3d83cSJiri Slaby (SUSE) #endif 422*a2f3d83cSJiri Slaby (SUSE) } 423*a2f3d83cSJiri Slaby (SUSE) 424*a2f3d83cSJiri Slaby (SUSE) return ((*bytes_written) == len) ? 0 : -EIO; 425*a2f3d83cSJiri Slaby (SUSE) } 426*a2f3d83cSJiri Slaby (SUSE) 427*a2f3d83cSJiri Slaby (SUSE) /* Receive a bulk message of variable size 428*a2f3d83cSJiri Slaby (SUSE) * 429*a2f3d83cSJiri Slaby (SUSE) * To copy the data to userspace, give pointer to "userbuffer", 430*a2f3d83cSJiri Slaby (SUSE) * to copy to kernel memory, give "kernbuffer". One of them 431*a2f3d83cSJiri Slaby (SUSE) * MUST be set. (There is no technique for letting the caller 432*a2f3d83cSJiri Slaby (SUSE) * read directly from the ibuf.) 433*a2f3d83cSJiri Slaby (SUSE) * 434*a2f3d83cSJiri Slaby (SUSE) */ 435*a2f3d83cSJiri Slaby (SUSE) 436*a2f3d83cSJiri Slaby (SUSE) static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, 437*a2f3d83cSJiri Slaby (SUSE) void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read, 438*a2f3d83cSJiri Slaby (SUSE) unsigned int tflags) 439*a2f3d83cSJiri Slaby (SUSE) { 440*a2f3d83cSJiri Slaby (SUSE) int result = 0, retry, count = len; 441*a2f3d83cSJiri Slaby (SUSE) int bufsize, thispass, transferred_len; 442*a2f3d83cSJiri Slaby (SUSE) unsigned int pipe; 443*a2f3d83cSJiri Slaby (SUSE) char *buffer; 444*a2f3d83cSJiri Slaby (SUSE) 445*a2f3d83cSJiri Slaby (SUSE) (*bytes_read) = 0; 446*a2f3d83cSJiri Slaby (SUSE) 447*a2f3d83cSJiri Slaby (SUSE) /* Sanity check */ 448*a2f3d83cSJiri Slaby (SUSE) if (!sisusb || !sisusb->present || !sisusb->sisusb_dev) 449*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 450*a2f3d83cSJiri Slaby (SUSE) 451*a2f3d83cSJiri Slaby (SUSE) pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep); 452*a2f3d83cSJiri Slaby (SUSE) buffer = sisusb->ibuf; 453*a2f3d83cSJiri Slaby (SUSE) bufsize = sisusb->ibufsize; 454*a2f3d83cSJiri Slaby (SUSE) 455*a2f3d83cSJiri Slaby (SUSE) retry = 5; 456*a2f3d83cSJiri Slaby (SUSE) 457*a2f3d83cSJiri Slaby (SUSE) #ifdef SISUSB_DONTSYNC 458*a2f3d83cSJiri Slaby (SUSE) if (!(sisusb_wait_all_out_complete(sisusb))) 459*a2f3d83cSJiri Slaby (SUSE) return -EIO; 460*a2f3d83cSJiri Slaby (SUSE) #endif 461*a2f3d83cSJiri Slaby (SUSE) 462*a2f3d83cSJiri Slaby (SUSE) while (count > 0) { 463*a2f3d83cSJiri Slaby (SUSE) 464*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->sisusb_dev) 465*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 466*a2f3d83cSJiri Slaby (SUSE) 467*a2f3d83cSJiri Slaby (SUSE) thispass = (bufsize < count) ? bufsize : count; 468*a2f3d83cSJiri Slaby (SUSE) 469*a2f3d83cSJiri Slaby (SUSE) result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass, 470*a2f3d83cSJiri Slaby (SUSE) &transferred_len, 5 * HZ, tflags); 471*a2f3d83cSJiri Slaby (SUSE) 472*a2f3d83cSJiri Slaby (SUSE) if (transferred_len) 473*a2f3d83cSJiri Slaby (SUSE) thispass = transferred_len; 474*a2f3d83cSJiri Slaby (SUSE) 475*a2f3d83cSJiri Slaby (SUSE) else if (result == -ETIMEDOUT) { 476*a2f3d83cSJiri Slaby (SUSE) 477*a2f3d83cSJiri Slaby (SUSE) if (!retry--) 478*a2f3d83cSJiri Slaby (SUSE) return -ETIME; 479*a2f3d83cSJiri Slaby (SUSE) 480*a2f3d83cSJiri Slaby (SUSE) continue; 481*a2f3d83cSJiri Slaby (SUSE) 482*a2f3d83cSJiri Slaby (SUSE) } else 483*a2f3d83cSJiri Slaby (SUSE) return -EIO; 484*a2f3d83cSJiri Slaby (SUSE) 485*a2f3d83cSJiri Slaby (SUSE) 486*a2f3d83cSJiri Slaby (SUSE) if (thispass) { 487*a2f3d83cSJiri Slaby (SUSE) 488*a2f3d83cSJiri Slaby (SUSE) (*bytes_read) += thispass; 489*a2f3d83cSJiri Slaby (SUSE) count -= thispass; 490*a2f3d83cSJiri Slaby (SUSE) 491*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 492*a2f3d83cSJiri Slaby (SUSE) 493*a2f3d83cSJiri Slaby (SUSE) if (copy_to_user(userbuffer, buffer, thispass)) 494*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 495*a2f3d83cSJiri Slaby (SUSE) 496*a2f3d83cSJiri Slaby (SUSE) userbuffer += thispass; 497*a2f3d83cSJiri Slaby (SUSE) 498*a2f3d83cSJiri Slaby (SUSE) } else { 499*a2f3d83cSJiri Slaby (SUSE) 500*a2f3d83cSJiri Slaby (SUSE) memcpy(kernbuffer, buffer, thispass); 501*a2f3d83cSJiri Slaby (SUSE) kernbuffer += thispass; 502*a2f3d83cSJiri Slaby (SUSE) 503*a2f3d83cSJiri Slaby (SUSE) } 504*a2f3d83cSJiri Slaby (SUSE) 505*a2f3d83cSJiri Slaby (SUSE) } 506*a2f3d83cSJiri Slaby (SUSE) 507*a2f3d83cSJiri Slaby (SUSE) } 508*a2f3d83cSJiri Slaby (SUSE) 509*a2f3d83cSJiri Slaby (SUSE) return ((*bytes_read) == len) ? 0 : -EIO; 510*a2f3d83cSJiri Slaby (SUSE) } 511*a2f3d83cSJiri Slaby (SUSE) 512*a2f3d83cSJiri Slaby (SUSE) static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len, 513*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet *packet) 514*a2f3d83cSJiri Slaby (SUSE) { 515*a2f3d83cSJiri Slaby (SUSE) int ret; 516*a2f3d83cSJiri Slaby (SUSE) ssize_t bytes_transferred = 0; 517*a2f3d83cSJiri Slaby (SUSE) __le32 tmp; 518*a2f3d83cSJiri Slaby (SUSE) 519*a2f3d83cSJiri Slaby (SUSE) if (len == 6) 520*a2f3d83cSJiri Slaby (SUSE) packet->data = 0; 521*a2f3d83cSJiri Slaby (SUSE) 522*a2f3d83cSJiri Slaby (SUSE) #ifdef SISUSB_DONTSYNC 523*a2f3d83cSJiri Slaby (SUSE) if (!(sisusb_wait_all_out_complete(sisusb))) 524*a2f3d83cSJiri Slaby (SUSE) return 1; 525*a2f3d83cSJiri Slaby (SUSE) #endif 526*a2f3d83cSJiri Slaby (SUSE) 527*a2f3d83cSJiri Slaby (SUSE) /* Eventually correct endianness */ 528*a2f3d83cSJiri Slaby (SUSE) SISUSB_CORRECT_ENDIANNESS_PACKET(packet); 529*a2f3d83cSJiri Slaby (SUSE) 530*a2f3d83cSJiri Slaby (SUSE) /* 1. send the packet */ 531*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len, 532*a2f3d83cSJiri Slaby (SUSE) (char *)packet, NULL, 0, &bytes_transferred, 0, 0); 533*a2f3d83cSJiri Slaby (SUSE) 534*a2f3d83cSJiri Slaby (SUSE) if ((ret == 0) && (len == 6)) { 535*a2f3d83cSJiri Slaby (SUSE) 536*a2f3d83cSJiri Slaby (SUSE) /* 2. if packet len == 6, it means we read, so wait for 32bit 537*a2f3d83cSJiri Slaby (SUSE) * return value and write it to packet->data 538*a2f3d83cSJiri Slaby (SUSE) */ 539*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4, 540*a2f3d83cSJiri Slaby (SUSE) (char *)&tmp, NULL, &bytes_transferred, 0); 541*a2f3d83cSJiri Slaby (SUSE) 542*a2f3d83cSJiri Slaby (SUSE) packet->data = le32_to_cpu(tmp); 543*a2f3d83cSJiri Slaby (SUSE) } 544*a2f3d83cSJiri Slaby (SUSE) 545*a2f3d83cSJiri Slaby (SUSE) return ret; 546*a2f3d83cSJiri Slaby (SUSE) } 547*a2f3d83cSJiri Slaby (SUSE) 548*a2f3d83cSJiri Slaby (SUSE) static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len, 549*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet *packet, unsigned int tflags) 550*a2f3d83cSJiri Slaby (SUSE) { 551*a2f3d83cSJiri Slaby (SUSE) int ret; 552*a2f3d83cSJiri Slaby (SUSE) ssize_t bytes_transferred = 0; 553*a2f3d83cSJiri Slaby (SUSE) __le32 tmp; 554*a2f3d83cSJiri Slaby (SUSE) 555*a2f3d83cSJiri Slaby (SUSE) if (len == 6) 556*a2f3d83cSJiri Slaby (SUSE) packet->data = 0; 557*a2f3d83cSJiri Slaby (SUSE) 558*a2f3d83cSJiri Slaby (SUSE) #ifdef SISUSB_DONTSYNC 559*a2f3d83cSJiri Slaby (SUSE) if (!(sisusb_wait_all_out_complete(sisusb))) 560*a2f3d83cSJiri Slaby (SUSE) return 1; 561*a2f3d83cSJiri Slaby (SUSE) #endif 562*a2f3d83cSJiri Slaby (SUSE) 563*a2f3d83cSJiri Slaby (SUSE) /* Eventually correct endianness */ 564*a2f3d83cSJiri Slaby (SUSE) SISUSB_CORRECT_ENDIANNESS_PACKET(packet); 565*a2f3d83cSJiri Slaby (SUSE) 566*a2f3d83cSJiri Slaby (SUSE) /* 1. send the packet */ 567*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len, 568*a2f3d83cSJiri Slaby (SUSE) (char *)packet, NULL, 0, &bytes_transferred, tflags, 0); 569*a2f3d83cSJiri Slaby (SUSE) 570*a2f3d83cSJiri Slaby (SUSE) if ((ret == 0) && (len == 6)) { 571*a2f3d83cSJiri Slaby (SUSE) 572*a2f3d83cSJiri Slaby (SUSE) /* 2. if packet len == 6, it means we read, so wait for 32bit 573*a2f3d83cSJiri Slaby (SUSE) * return value and write it to packet->data 574*a2f3d83cSJiri Slaby (SUSE) */ 575*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4, 576*a2f3d83cSJiri Slaby (SUSE) (char *)&tmp, NULL, &bytes_transferred, 0); 577*a2f3d83cSJiri Slaby (SUSE) 578*a2f3d83cSJiri Slaby (SUSE) packet->data = le32_to_cpu(tmp); 579*a2f3d83cSJiri Slaby (SUSE) } 580*a2f3d83cSJiri Slaby (SUSE) 581*a2f3d83cSJiri Slaby (SUSE) return ret; 582*a2f3d83cSJiri Slaby (SUSE) } 583*a2f3d83cSJiri Slaby (SUSE) 584*a2f3d83cSJiri Slaby (SUSE) /* access video memory and mmio (return 0 on success) */ 585*a2f3d83cSJiri Slaby (SUSE) 586*a2f3d83cSJiri Slaby (SUSE) /* Low level */ 587*a2f3d83cSJiri Slaby (SUSE) 588*a2f3d83cSJiri Slaby (SUSE) /* The following routines assume being used to transfer byte, word, 589*a2f3d83cSJiri Slaby (SUSE) * long etc. 590*a2f3d83cSJiri Slaby (SUSE) * This means that 591*a2f3d83cSJiri Slaby (SUSE) * - the write routines expect "data" in machine endianness format. 592*a2f3d83cSJiri Slaby (SUSE) * The data will be converted to leXX in sisusb_xxx_packet. 593*a2f3d83cSJiri Slaby (SUSE) * - the read routines can expect read data in machine-endianess. 594*a2f3d83cSJiri Slaby (SUSE) */ 595*a2f3d83cSJiri Slaby (SUSE) 596*a2f3d83cSJiri Slaby (SUSE) static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, 597*a2f3d83cSJiri Slaby (SUSE) u32 addr, u8 data) 598*a2f3d83cSJiri Slaby (SUSE) { 599*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 600*a2f3d83cSJiri Slaby (SUSE) 601*a2f3d83cSJiri Slaby (SUSE) packet.header = (1 << (addr & 3)) | (type << 6); 602*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 603*a2f3d83cSJiri Slaby (SUSE) packet.data = data << ((addr & 3) << 3); 604*a2f3d83cSJiri Slaby (SUSE) return sisusb_send_packet(sisusb, 10, &packet); 605*a2f3d83cSJiri Slaby (SUSE) } 606*a2f3d83cSJiri Slaby (SUSE) 607*a2f3d83cSJiri Slaby (SUSE) static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type, 608*a2f3d83cSJiri Slaby (SUSE) u32 addr, u16 data) 609*a2f3d83cSJiri Slaby (SUSE) { 610*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 611*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 612*a2f3d83cSJiri Slaby (SUSE) 613*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 614*a2f3d83cSJiri Slaby (SUSE) 615*a2f3d83cSJiri Slaby (SUSE) switch (addr & 3) { 616*a2f3d83cSJiri Slaby (SUSE) case 0: 617*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0003; 618*a2f3d83cSJiri Slaby (SUSE) packet.data = (u32)data; 619*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 620*a2f3d83cSJiri Slaby (SUSE) break; 621*a2f3d83cSJiri Slaby (SUSE) case 1: 622*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0006; 623*a2f3d83cSJiri Slaby (SUSE) packet.data = (u32)data << 8; 624*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 625*a2f3d83cSJiri Slaby (SUSE) break; 626*a2f3d83cSJiri Slaby (SUSE) case 2: 627*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000c; 628*a2f3d83cSJiri Slaby (SUSE) packet.data = (u32)data << 16; 629*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 630*a2f3d83cSJiri Slaby (SUSE) break; 631*a2f3d83cSJiri Slaby (SUSE) case 3: 632*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0008; 633*a2f3d83cSJiri Slaby (SUSE) packet.data = (u32)data << 24; 634*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 635*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0001; 636*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 637*a2f3d83cSJiri Slaby (SUSE) packet.data = (u32)data >> 8; 638*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 10, &packet); 639*a2f3d83cSJiri Slaby (SUSE) } 640*a2f3d83cSJiri Slaby (SUSE) 641*a2f3d83cSJiri Slaby (SUSE) return ret; 642*a2f3d83cSJiri Slaby (SUSE) } 643*a2f3d83cSJiri Slaby (SUSE) 644*a2f3d83cSJiri Slaby (SUSE) static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type, 645*a2f3d83cSJiri Slaby (SUSE) u32 addr, u32 data) 646*a2f3d83cSJiri Slaby (SUSE) { 647*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 648*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 649*a2f3d83cSJiri Slaby (SUSE) 650*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 651*a2f3d83cSJiri Slaby (SUSE) 652*a2f3d83cSJiri Slaby (SUSE) switch (addr & 3) { 653*a2f3d83cSJiri Slaby (SUSE) case 0: 654*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0007; 655*a2f3d83cSJiri Slaby (SUSE) packet.data = data & 0x00ffffff; 656*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 657*a2f3d83cSJiri Slaby (SUSE) break; 658*a2f3d83cSJiri Slaby (SUSE) case 1: 659*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000e; 660*a2f3d83cSJiri Slaby (SUSE) packet.data = data << 8; 661*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 662*a2f3d83cSJiri Slaby (SUSE) break; 663*a2f3d83cSJiri Slaby (SUSE) case 2: 664*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000c; 665*a2f3d83cSJiri Slaby (SUSE) packet.data = data << 16; 666*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 667*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0001; 668*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 669*a2f3d83cSJiri Slaby (SUSE) packet.data = (data >> 16) & 0x00ff; 670*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 10, &packet); 671*a2f3d83cSJiri Slaby (SUSE) break; 672*a2f3d83cSJiri Slaby (SUSE) case 3: 673*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0008; 674*a2f3d83cSJiri Slaby (SUSE) packet.data = data << 24; 675*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 676*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0003; 677*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 678*a2f3d83cSJiri Slaby (SUSE) packet.data = (data >> 8) & 0xffff; 679*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 10, &packet); 680*a2f3d83cSJiri Slaby (SUSE) } 681*a2f3d83cSJiri Slaby (SUSE) 682*a2f3d83cSJiri Slaby (SUSE) return ret; 683*a2f3d83cSJiri Slaby (SUSE) } 684*a2f3d83cSJiri Slaby (SUSE) 685*a2f3d83cSJiri Slaby (SUSE) static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, 686*a2f3d83cSJiri Slaby (SUSE) u32 addr, u32 data) 687*a2f3d83cSJiri Slaby (SUSE) { 688*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 689*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 690*a2f3d83cSJiri Slaby (SUSE) 691*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 692*a2f3d83cSJiri Slaby (SUSE) 693*a2f3d83cSJiri Slaby (SUSE) switch (addr & 3) { 694*a2f3d83cSJiri Slaby (SUSE) case 0: 695*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000f; 696*a2f3d83cSJiri Slaby (SUSE) packet.data = data; 697*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 698*a2f3d83cSJiri Slaby (SUSE) break; 699*a2f3d83cSJiri Slaby (SUSE) case 1: 700*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000e; 701*a2f3d83cSJiri Slaby (SUSE) packet.data = data << 8; 702*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 703*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0001; 704*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 705*a2f3d83cSJiri Slaby (SUSE) packet.data = data >> 24; 706*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 10, &packet); 707*a2f3d83cSJiri Slaby (SUSE) break; 708*a2f3d83cSJiri Slaby (SUSE) case 2: 709*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000c; 710*a2f3d83cSJiri Slaby (SUSE) packet.data = data << 16; 711*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 712*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0003; 713*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 714*a2f3d83cSJiri Slaby (SUSE) packet.data = data >> 16; 715*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 10, &packet); 716*a2f3d83cSJiri Slaby (SUSE) break; 717*a2f3d83cSJiri Slaby (SUSE) case 3: 718*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0008; 719*a2f3d83cSJiri Slaby (SUSE) packet.data = data << 24; 720*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 10, &packet); 721*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0007; 722*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 723*a2f3d83cSJiri Slaby (SUSE) packet.data = data >> 8; 724*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 10, &packet); 725*a2f3d83cSJiri Slaby (SUSE) } 726*a2f3d83cSJiri Slaby (SUSE) 727*a2f3d83cSJiri Slaby (SUSE) return ret; 728*a2f3d83cSJiri Slaby (SUSE) } 729*a2f3d83cSJiri Slaby (SUSE) 730*a2f3d83cSJiri Slaby (SUSE) /* The xxx_bulk routines copy a buffer of variable size. They treat the 731*a2f3d83cSJiri Slaby (SUSE) * buffer as chars, therefore lsb/msb has to be corrected if using the 732*a2f3d83cSJiri Slaby (SUSE) * byte/word/long/etc routines for speed-up 733*a2f3d83cSJiri Slaby (SUSE) * 734*a2f3d83cSJiri Slaby (SUSE) * If data is from userland, set "userbuffer" (and clear "kernbuffer"), 735*a2f3d83cSJiri Slaby (SUSE) * if data is in kernel space, set "kernbuffer" (and clear "userbuffer"); 736*a2f3d83cSJiri Slaby (SUSE) * if neither "kernbuffer" nor "userbuffer" are given, it is assumed 737*a2f3d83cSJiri Slaby (SUSE) * that the data already is in the transfer buffer "sisusb->obuf[index]". 738*a2f3d83cSJiri Slaby (SUSE) */ 739*a2f3d83cSJiri Slaby (SUSE) 740*a2f3d83cSJiri Slaby (SUSE) static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, 741*a2f3d83cSJiri Slaby (SUSE) char *kernbuffer, int length, const char __user *userbuffer, 742*a2f3d83cSJiri Slaby (SUSE) int index, ssize_t *bytes_written) 743*a2f3d83cSJiri Slaby (SUSE) { 744*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 745*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 746*a2f3d83cSJiri Slaby (SUSE) static int msgcount; 747*a2f3d83cSJiri Slaby (SUSE) u8 swap8, fromkern = kernbuffer ? 1 : 0; 748*a2f3d83cSJiri Slaby (SUSE) u16 swap16; 749*a2f3d83cSJiri Slaby (SUSE) u32 swap32, flag = (length >> 28) & 1; 750*a2f3d83cSJiri Slaby (SUSE) u8 buf[4]; 751*a2f3d83cSJiri Slaby (SUSE) 752*a2f3d83cSJiri Slaby (SUSE) /* if neither kernbuffer not userbuffer are given, assume 753*a2f3d83cSJiri Slaby (SUSE) * data in obuf 754*a2f3d83cSJiri Slaby (SUSE) */ 755*a2f3d83cSJiri Slaby (SUSE) if (!fromkern && !userbuffer) 756*a2f3d83cSJiri Slaby (SUSE) kernbuffer = sisusb->obuf[index]; 757*a2f3d83cSJiri Slaby (SUSE) 758*a2f3d83cSJiri Slaby (SUSE) (*bytes_written = 0); 759*a2f3d83cSJiri Slaby (SUSE) 760*a2f3d83cSJiri Slaby (SUSE) length &= 0x00ffffff; 761*a2f3d83cSJiri Slaby (SUSE) 762*a2f3d83cSJiri Slaby (SUSE) while (length) { 763*a2f3d83cSJiri Slaby (SUSE) switch (length) { 764*a2f3d83cSJiri Slaby (SUSE) case 1: 765*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 766*a2f3d83cSJiri Slaby (SUSE) if (get_user(swap8, (u8 __user *)userbuffer)) 767*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 768*a2f3d83cSJiri Slaby (SUSE) } else 769*a2f3d83cSJiri Slaby (SUSE) swap8 = kernbuffer[0]; 770*a2f3d83cSJiri Slaby (SUSE) 771*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, 772*a2f3d83cSJiri Slaby (SUSE) addr, swap8); 773*a2f3d83cSJiri Slaby (SUSE) 774*a2f3d83cSJiri Slaby (SUSE) if (!ret) 775*a2f3d83cSJiri Slaby (SUSE) (*bytes_written)++; 776*a2f3d83cSJiri Slaby (SUSE) 777*a2f3d83cSJiri Slaby (SUSE) return ret; 778*a2f3d83cSJiri Slaby (SUSE) 779*a2f3d83cSJiri Slaby (SUSE) case 2: 780*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 781*a2f3d83cSJiri Slaby (SUSE) if (get_user(swap16, (u16 __user *)userbuffer)) 782*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 783*a2f3d83cSJiri Slaby (SUSE) } else 784*a2f3d83cSJiri Slaby (SUSE) swap16 = *((u16 *)kernbuffer); 785*a2f3d83cSJiri Slaby (SUSE) 786*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, 787*a2f3d83cSJiri Slaby (SUSE) addr, swap16); 788*a2f3d83cSJiri Slaby (SUSE) 789*a2f3d83cSJiri Slaby (SUSE) if (!ret) 790*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) += 2; 791*a2f3d83cSJiri Slaby (SUSE) 792*a2f3d83cSJiri Slaby (SUSE) return ret; 793*a2f3d83cSJiri Slaby (SUSE) 794*a2f3d83cSJiri Slaby (SUSE) case 3: 795*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 796*a2f3d83cSJiri Slaby (SUSE) if (copy_from_user(&buf, userbuffer, 3)) 797*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 798*a2f3d83cSJiri Slaby (SUSE) #ifdef __BIG_ENDIAN 799*a2f3d83cSJiri Slaby (SUSE) swap32 = (buf[0] << 16) | 800*a2f3d83cSJiri Slaby (SUSE) (buf[1] << 8) | 801*a2f3d83cSJiri Slaby (SUSE) buf[2]; 802*a2f3d83cSJiri Slaby (SUSE) #else 803*a2f3d83cSJiri Slaby (SUSE) swap32 = (buf[2] << 16) | 804*a2f3d83cSJiri Slaby (SUSE) (buf[1] << 8) | 805*a2f3d83cSJiri Slaby (SUSE) buf[0]; 806*a2f3d83cSJiri Slaby (SUSE) #endif 807*a2f3d83cSJiri Slaby (SUSE) } else 808*a2f3d83cSJiri Slaby (SUSE) #ifdef __BIG_ENDIAN 809*a2f3d83cSJiri Slaby (SUSE) swap32 = (kernbuffer[0] << 16) | 810*a2f3d83cSJiri Slaby (SUSE) (kernbuffer[1] << 8) | 811*a2f3d83cSJiri Slaby (SUSE) kernbuffer[2]; 812*a2f3d83cSJiri Slaby (SUSE) #else 813*a2f3d83cSJiri Slaby (SUSE) swap32 = (kernbuffer[2] << 16) | 814*a2f3d83cSJiri Slaby (SUSE) (kernbuffer[1] << 8) | 815*a2f3d83cSJiri Slaby (SUSE) kernbuffer[0]; 816*a2f3d83cSJiri Slaby (SUSE) #endif 817*a2f3d83cSJiri Slaby (SUSE) 818*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM, 819*a2f3d83cSJiri Slaby (SUSE) addr, swap32); 820*a2f3d83cSJiri Slaby (SUSE) 821*a2f3d83cSJiri Slaby (SUSE) if (!ret) 822*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) += 3; 823*a2f3d83cSJiri Slaby (SUSE) 824*a2f3d83cSJiri Slaby (SUSE) return ret; 825*a2f3d83cSJiri Slaby (SUSE) 826*a2f3d83cSJiri Slaby (SUSE) case 4: 827*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 828*a2f3d83cSJiri Slaby (SUSE) if (get_user(swap32, (u32 __user *)userbuffer)) 829*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 830*a2f3d83cSJiri Slaby (SUSE) } else 831*a2f3d83cSJiri Slaby (SUSE) swap32 = *((u32 *)kernbuffer); 832*a2f3d83cSJiri Slaby (SUSE) 833*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, 834*a2f3d83cSJiri Slaby (SUSE) addr, swap32); 835*a2f3d83cSJiri Slaby (SUSE) if (!ret) 836*a2f3d83cSJiri Slaby (SUSE) (*bytes_written) += 4; 837*a2f3d83cSJiri Slaby (SUSE) 838*a2f3d83cSJiri Slaby (SUSE) return ret; 839*a2f3d83cSJiri Slaby (SUSE) 840*a2f3d83cSJiri Slaby (SUSE) default: 841*a2f3d83cSJiri Slaby (SUSE) if ((length & ~3) > 0x10000) { 842*a2f3d83cSJiri Slaby (SUSE) 843*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 844*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x000001d4; 845*a2f3d83cSJiri Slaby (SUSE) packet.data = addr; 846*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_bridge_packet(sisusb, 10, 847*a2f3d83cSJiri Slaby (SUSE) &packet, 0); 848*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 849*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x000001d0; 850*a2f3d83cSJiri Slaby (SUSE) packet.data = (length & ~3); 851*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, 852*a2f3d83cSJiri Slaby (SUSE) &packet, 0); 853*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 854*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x000001c0; 855*a2f3d83cSJiri Slaby (SUSE) packet.data = flag | 0x16; 856*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, 857*a2f3d83cSJiri Slaby (SUSE) &packet, 0); 858*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 859*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bulk_msg(sisusb, 860*a2f3d83cSJiri Slaby (SUSE) SISUSB_EP_GFX_LBULK_OUT, 861*a2f3d83cSJiri Slaby (SUSE) (length & ~3), 862*a2f3d83cSJiri Slaby (SUSE) NULL, userbuffer, 0, 863*a2f3d83cSJiri Slaby (SUSE) bytes_written, 0, 1); 864*a2f3d83cSJiri Slaby (SUSE) userbuffer += (*bytes_written); 865*a2f3d83cSJiri Slaby (SUSE) } else if (fromkern) { 866*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bulk_msg(sisusb, 867*a2f3d83cSJiri Slaby (SUSE) SISUSB_EP_GFX_LBULK_OUT, 868*a2f3d83cSJiri Slaby (SUSE) (length & ~3), 869*a2f3d83cSJiri Slaby (SUSE) kernbuffer, NULL, 0, 870*a2f3d83cSJiri Slaby (SUSE) bytes_written, 0, 1); 871*a2f3d83cSJiri Slaby (SUSE) kernbuffer += (*bytes_written); 872*a2f3d83cSJiri Slaby (SUSE) } else { 873*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bulk_msg(sisusb, 874*a2f3d83cSJiri Slaby (SUSE) SISUSB_EP_GFX_LBULK_OUT, 875*a2f3d83cSJiri Slaby (SUSE) (length & ~3), 876*a2f3d83cSJiri Slaby (SUSE) NULL, NULL, index, 877*a2f3d83cSJiri Slaby (SUSE) bytes_written, 0, 1); 878*a2f3d83cSJiri Slaby (SUSE) kernbuffer += ((*bytes_written) & 879*a2f3d83cSJiri Slaby (SUSE) (sisusb->obufsize-1)); 880*a2f3d83cSJiri Slaby (SUSE) } 881*a2f3d83cSJiri Slaby (SUSE) 882*a2f3d83cSJiri Slaby (SUSE) } else { 883*a2f3d83cSJiri Slaby (SUSE) 884*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 885*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000194; 886*a2f3d83cSJiri Slaby (SUSE) packet.data = addr; 887*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_bridge_packet(sisusb, 10, 888*a2f3d83cSJiri Slaby (SUSE) &packet, 0); 889*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 890*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000190; 891*a2f3d83cSJiri Slaby (SUSE) packet.data = (length & ~3); 892*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, 893*a2f3d83cSJiri Slaby (SUSE) &packet, 0); 894*a2f3d83cSJiri Slaby (SUSE) if (sisusb->flagb0 != 0x16) { 895*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 896*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000180; 897*a2f3d83cSJiri Slaby (SUSE) packet.data = flag | 0x16; 898*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 899*a2f3d83cSJiri Slaby (SUSE) 10, &packet, 0); 900*a2f3d83cSJiri Slaby (SUSE) sisusb->flagb0 = 0x16; 901*a2f3d83cSJiri Slaby (SUSE) } 902*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 903*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bulk_msg(sisusb, 904*a2f3d83cSJiri Slaby (SUSE) SISUSB_EP_GFX_BULK_OUT, 905*a2f3d83cSJiri Slaby (SUSE) (length & ~3), 906*a2f3d83cSJiri Slaby (SUSE) NULL, userbuffer, 0, 907*a2f3d83cSJiri Slaby (SUSE) bytes_written, 0, 1); 908*a2f3d83cSJiri Slaby (SUSE) userbuffer += (*bytes_written); 909*a2f3d83cSJiri Slaby (SUSE) } else if (fromkern) { 910*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bulk_msg(sisusb, 911*a2f3d83cSJiri Slaby (SUSE) SISUSB_EP_GFX_BULK_OUT, 912*a2f3d83cSJiri Slaby (SUSE) (length & ~3), 913*a2f3d83cSJiri Slaby (SUSE) kernbuffer, NULL, 0, 914*a2f3d83cSJiri Slaby (SUSE) bytes_written, 0, 1); 915*a2f3d83cSJiri Slaby (SUSE) kernbuffer += (*bytes_written); 916*a2f3d83cSJiri Slaby (SUSE) } else { 917*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bulk_msg(sisusb, 918*a2f3d83cSJiri Slaby (SUSE) SISUSB_EP_GFX_BULK_OUT, 919*a2f3d83cSJiri Slaby (SUSE) (length & ~3), 920*a2f3d83cSJiri Slaby (SUSE) NULL, NULL, index, 921*a2f3d83cSJiri Slaby (SUSE) bytes_written, 0, 1); 922*a2f3d83cSJiri Slaby (SUSE) kernbuffer += ((*bytes_written) & 923*a2f3d83cSJiri Slaby (SUSE) (sisusb->obufsize-1)); 924*a2f3d83cSJiri Slaby (SUSE) } 925*a2f3d83cSJiri Slaby (SUSE) } 926*a2f3d83cSJiri Slaby (SUSE) if (ret) { 927*a2f3d83cSJiri Slaby (SUSE) msgcount++; 928*a2f3d83cSJiri Slaby (SUSE) if (msgcount < 500) 929*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 930*a2f3d83cSJiri Slaby (SUSE) "Wrote %zd of %d bytes, error %d\n", 931*a2f3d83cSJiri Slaby (SUSE) *bytes_written, length, 932*a2f3d83cSJiri Slaby (SUSE) ret); 933*a2f3d83cSJiri Slaby (SUSE) else if (msgcount == 500) 934*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 935*a2f3d83cSJiri Slaby (SUSE) "Too many errors, logging stopped\n"); 936*a2f3d83cSJiri Slaby (SUSE) } 937*a2f3d83cSJiri Slaby (SUSE) addr += (*bytes_written); 938*a2f3d83cSJiri Slaby (SUSE) length -= (*bytes_written); 939*a2f3d83cSJiri Slaby (SUSE) } 940*a2f3d83cSJiri Slaby (SUSE) 941*a2f3d83cSJiri Slaby (SUSE) if (ret) 942*a2f3d83cSJiri Slaby (SUSE) break; 943*a2f3d83cSJiri Slaby (SUSE) 944*a2f3d83cSJiri Slaby (SUSE) } 945*a2f3d83cSJiri Slaby (SUSE) 946*a2f3d83cSJiri Slaby (SUSE) return ret ? -EIO : 0; 947*a2f3d83cSJiri Slaby (SUSE) } 948*a2f3d83cSJiri Slaby (SUSE) 949*a2f3d83cSJiri Slaby (SUSE) /* Remember: Read data in packet is in machine-endianess! So for 950*a2f3d83cSJiri Slaby (SUSE) * byte, word, 24bit, long no endian correction is necessary. 951*a2f3d83cSJiri Slaby (SUSE) */ 952*a2f3d83cSJiri Slaby (SUSE) 953*a2f3d83cSJiri Slaby (SUSE) static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, 954*a2f3d83cSJiri Slaby (SUSE) u32 addr, u8 *data) 955*a2f3d83cSJiri Slaby (SUSE) { 956*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 957*a2f3d83cSJiri Slaby (SUSE) int ret; 958*a2f3d83cSJiri Slaby (SUSE) 959*a2f3d83cSJiri Slaby (SUSE) CLEARPACKET(&packet); 960*a2f3d83cSJiri Slaby (SUSE) packet.header = (1 << (addr & 3)) | (type << 6); 961*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 962*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 963*a2f3d83cSJiri Slaby (SUSE) *data = (u8)(packet.data >> ((addr & 3) << 3)); 964*a2f3d83cSJiri Slaby (SUSE) return ret; 965*a2f3d83cSJiri Slaby (SUSE) } 966*a2f3d83cSJiri Slaby (SUSE) 967*a2f3d83cSJiri Slaby (SUSE) static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type, 968*a2f3d83cSJiri Slaby (SUSE) u32 addr, u16 *data) 969*a2f3d83cSJiri Slaby (SUSE) { 970*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 971*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 972*a2f3d83cSJiri Slaby (SUSE) 973*a2f3d83cSJiri Slaby (SUSE) CLEARPACKET(&packet); 974*a2f3d83cSJiri Slaby (SUSE) 975*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 976*a2f3d83cSJiri Slaby (SUSE) 977*a2f3d83cSJiri Slaby (SUSE) switch (addr & 3) { 978*a2f3d83cSJiri Slaby (SUSE) case 0: 979*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0003; 980*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 981*a2f3d83cSJiri Slaby (SUSE) *data = (u16)(packet.data); 982*a2f3d83cSJiri Slaby (SUSE) break; 983*a2f3d83cSJiri Slaby (SUSE) case 1: 984*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0006; 985*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 986*a2f3d83cSJiri Slaby (SUSE) *data = (u16)(packet.data >> 8); 987*a2f3d83cSJiri Slaby (SUSE) break; 988*a2f3d83cSJiri Slaby (SUSE) case 2: 989*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000c; 990*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 991*a2f3d83cSJiri Slaby (SUSE) *data = (u16)(packet.data >> 16); 992*a2f3d83cSJiri Slaby (SUSE) break; 993*a2f3d83cSJiri Slaby (SUSE) case 3: 994*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0008; 995*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 996*a2f3d83cSJiri Slaby (SUSE) *data = (u16)(packet.data >> 24); 997*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0001; 998*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 999*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 6, &packet); 1000*a2f3d83cSJiri Slaby (SUSE) *data |= (u16)(packet.data << 8); 1001*a2f3d83cSJiri Slaby (SUSE) } 1002*a2f3d83cSJiri Slaby (SUSE) 1003*a2f3d83cSJiri Slaby (SUSE) return ret; 1004*a2f3d83cSJiri Slaby (SUSE) } 1005*a2f3d83cSJiri Slaby (SUSE) 1006*a2f3d83cSJiri Slaby (SUSE) static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type, 1007*a2f3d83cSJiri Slaby (SUSE) u32 addr, u32 *data) 1008*a2f3d83cSJiri Slaby (SUSE) { 1009*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 1010*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 1011*a2f3d83cSJiri Slaby (SUSE) 1012*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 1013*a2f3d83cSJiri Slaby (SUSE) 1014*a2f3d83cSJiri Slaby (SUSE) switch (addr & 3) { 1015*a2f3d83cSJiri Slaby (SUSE) case 0: 1016*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0007; 1017*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1018*a2f3d83cSJiri Slaby (SUSE) *data = packet.data & 0x00ffffff; 1019*a2f3d83cSJiri Slaby (SUSE) break; 1020*a2f3d83cSJiri Slaby (SUSE) case 1: 1021*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000e; 1022*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1023*a2f3d83cSJiri Slaby (SUSE) *data = packet.data >> 8; 1024*a2f3d83cSJiri Slaby (SUSE) break; 1025*a2f3d83cSJiri Slaby (SUSE) case 2: 1026*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000c; 1027*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1028*a2f3d83cSJiri Slaby (SUSE) *data = packet.data >> 16; 1029*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0001; 1030*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 1031*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 6, &packet); 1032*a2f3d83cSJiri Slaby (SUSE) *data |= ((packet.data & 0xff) << 16); 1033*a2f3d83cSJiri Slaby (SUSE) break; 1034*a2f3d83cSJiri Slaby (SUSE) case 3: 1035*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0008; 1036*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1037*a2f3d83cSJiri Slaby (SUSE) *data = packet.data >> 24; 1038*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0003; 1039*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 1040*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 6, &packet); 1041*a2f3d83cSJiri Slaby (SUSE) *data |= ((packet.data & 0xffff) << 8); 1042*a2f3d83cSJiri Slaby (SUSE) } 1043*a2f3d83cSJiri Slaby (SUSE) 1044*a2f3d83cSJiri Slaby (SUSE) return ret; 1045*a2f3d83cSJiri Slaby (SUSE) } 1046*a2f3d83cSJiri Slaby (SUSE) 1047*a2f3d83cSJiri Slaby (SUSE) static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, 1048*a2f3d83cSJiri Slaby (SUSE) u32 addr, u32 *data) 1049*a2f3d83cSJiri Slaby (SUSE) { 1050*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 1051*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 1052*a2f3d83cSJiri Slaby (SUSE) 1053*a2f3d83cSJiri Slaby (SUSE) packet.address = addr & ~3; 1054*a2f3d83cSJiri Slaby (SUSE) 1055*a2f3d83cSJiri Slaby (SUSE) switch (addr & 3) { 1056*a2f3d83cSJiri Slaby (SUSE) case 0: 1057*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000f; 1058*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1059*a2f3d83cSJiri Slaby (SUSE) *data = packet.data; 1060*a2f3d83cSJiri Slaby (SUSE) break; 1061*a2f3d83cSJiri Slaby (SUSE) case 1: 1062*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000e; 1063*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1064*a2f3d83cSJiri Slaby (SUSE) *data = packet.data >> 8; 1065*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0001; 1066*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 1067*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 6, &packet); 1068*a2f3d83cSJiri Slaby (SUSE) *data |= (packet.data << 24); 1069*a2f3d83cSJiri Slaby (SUSE) break; 1070*a2f3d83cSJiri Slaby (SUSE) case 2: 1071*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x000c; 1072*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1073*a2f3d83cSJiri Slaby (SUSE) *data = packet.data >> 16; 1074*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0003; 1075*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 1076*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 6, &packet); 1077*a2f3d83cSJiri Slaby (SUSE) *data |= (packet.data << 16); 1078*a2f3d83cSJiri Slaby (SUSE) break; 1079*a2f3d83cSJiri Slaby (SUSE) case 3: 1080*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0008; 1081*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1082*a2f3d83cSJiri Slaby (SUSE) *data = packet.data >> 24; 1083*a2f3d83cSJiri Slaby (SUSE) packet.header = (type << 6) | 0x0007; 1084*a2f3d83cSJiri Slaby (SUSE) packet.address = (addr & ~3) + 4; 1085*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_packet(sisusb, 6, &packet); 1086*a2f3d83cSJiri Slaby (SUSE) *data |= (packet.data << 8); 1087*a2f3d83cSJiri Slaby (SUSE) } 1088*a2f3d83cSJiri Slaby (SUSE) 1089*a2f3d83cSJiri Slaby (SUSE) return ret; 1090*a2f3d83cSJiri Slaby (SUSE) } 1091*a2f3d83cSJiri Slaby (SUSE) 1092*a2f3d83cSJiri Slaby (SUSE) static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, 1093*a2f3d83cSJiri Slaby (SUSE) char *kernbuffer, int length, char __user *userbuffer, 1094*a2f3d83cSJiri Slaby (SUSE) ssize_t *bytes_read) 1095*a2f3d83cSJiri Slaby (SUSE) { 1096*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 1097*a2f3d83cSJiri Slaby (SUSE) char buf[4]; 1098*a2f3d83cSJiri Slaby (SUSE) u16 swap16; 1099*a2f3d83cSJiri Slaby (SUSE) u32 swap32; 1100*a2f3d83cSJiri Slaby (SUSE) 1101*a2f3d83cSJiri Slaby (SUSE) (*bytes_read = 0); 1102*a2f3d83cSJiri Slaby (SUSE) 1103*a2f3d83cSJiri Slaby (SUSE) length &= 0x00ffffff; 1104*a2f3d83cSJiri Slaby (SUSE) 1105*a2f3d83cSJiri Slaby (SUSE) while (length) { 1106*a2f3d83cSJiri Slaby (SUSE) switch (length) { 1107*a2f3d83cSJiri Slaby (SUSE) case 1: 1108*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, 1109*a2f3d83cSJiri Slaby (SUSE) addr, &buf[0]); 1110*a2f3d83cSJiri Slaby (SUSE) if (!ret) { 1111*a2f3d83cSJiri Slaby (SUSE) (*bytes_read)++; 1112*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 1113*a2f3d83cSJiri Slaby (SUSE) if (put_user(buf[0], (u8 __user *)userbuffer)) 1114*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 1115*a2f3d83cSJiri Slaby (SUSE) } else 1116*a2f3d83cSJiri Slaby (SUSE) kernbuffer[0] = buf[0]; 1117*a2f3d83cSJiri Slaby (SUSE) } 1118*a2f3d83cSJiri Slaby (SUSE) return ret; 1119*a2f3d83cSJiri Slaby (SUSE) 1120*a2f3d83cSJiri Slaby (SUSE) case 2: 1121*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, 1122*a2f3d83cSJiri Slaby (SUSE) addr, &swap16); 1123*a2f3d83cSJiri Slaby (SUSE) if (!ret) { 1124*a2f3d83cSJiri Slaby (SUSE) (*bytes_read) += 2; 1125*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 1126*a2f3d83cSJiri Slaby (SUSE) if (put_user(swap16, (u16 __user *)userbuffer)) 1127*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 1128*a2f3d83cSJiri Slaby (SUSE) } else { 1129*a2f3d83cSJiri Slaby (SUSE) *((u16 *)kernbuffer) = swap16; 1130*a2f3d83cSJiri Slaby (SUSE) } 1131*a2f3d83cSJiri Slaby (SUSE) } 1132*a2f3d83cSJiri Slaby (SUSE) return ret; 1133*a2f3d83cSJiri Slaby (SUSE) 1134*a2f3d83cSJiri Slaby (SUSE) case 3: 1135*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM, 1136*a2f3d83cSJiri Slaby (SUSE) addr, &swap32); 1137*a2f3d83cSJiri Slaby (SUSE) if (!ret) { 1138*a2f3d83cSJiri Slaby (SUSE) (*bytes_read) += 3; 1139*a2f3d83cSJiri Slaby (SUSE) #ifdef __BIG_ENDIAN 1140*a2f3d83cSJiri Slaby (SUSE) buf[0] = (swap32 >> 16) & 0xff; 1141*a2f3d83cSJiri Slaby (SUSE) buf[1] = (swap32 >> 8) & 0xff; 1142*a2f3d83cSJiri Slaby (SUSE) buf[2] = swap32 & 0xff; 1143*a2f3d83cSJiri Slaby (SUSE) #else 1144*a2f3d83cSJiri Slaby (SUSE) buf[2] = (swap32 >> 16) & 0xff; 1145*a2f3d83cSJiri Slaby (SUSE) buf[1] = (swap32 >> 8) & 0xff; 1146*a2f3d83cSJiri Slaby (SUSE) buf[0] = swap32 & 0xff; 1147*a2f3d83cSJiri Slaby (SUSE) #endif 1148*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 1149*a2f3d83cSJiri Slaby (SUSE) if (copy_to_user(userbuffer, 1150*a2f3d83cSJiri Slaby (SUSE) &buf[0], 3)) 1151*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 1152*a2f3d83cSJiri Slaby (SUSE) } else { 1153*a2f3d83cSJiri Slaby (SUSE) kernbuffer[0] = buf[0]; 1154*a2f3d83cSJiri Slaby (SUSE) kernbuffer[1] = buf[1]; 1155*a2f3d83cSJiri Slaby (SUSE) kernbuffer[2] = buf[2]; 1156*a2f3d83cSJiri Slaby (SUSE) } 1157*a2f3d83cSJiri Slaby (SUSE) } 1158*a2f3d83cSJiri Slaby (SUSE) return ret; 1159*a2f3d83cSJiri Slaby (SUSE) 1160*a2f3d83cSJiri Slaby (SUSE) default: 1161*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, 1162*a2f3d83cSJiri Slaby (SUSE) addr, &swap32); 1163*a2f3d83cSJiri Slaby (SUSE) if (!ret) { 1164*a2f3d83cSJiri Slaby (SUSE) (*bytes_read) += 4; 1165*a2f3d83cSJiri Slaby (SUSE) if (userbuffer) { 1166*a2f3d83cSJiri Slaby (SUSE) if (put_user(swap32, (u32 __user *)userbuffer)) 1167*a2f3d83cSJiri Slaby (SUSE) return -EFAULT; 1168*a2f3d83cSJiri Slaby (SUSE) 1169*a2f3d83cSJiri Slaby (SUSE) userbuffer += 4; 1170*a2f3d83cSJiri Slaby (SUSE) } else { 1171*a2f3d83cSJiri Slaby (SUSE) *((u32 *)kernbuffer) = swap32; 1172*a2f3d83cSJiri Slaby (SUSE) kernbuffer += 4; 1173*a2f3d83cSJiri Slaby (SUSE) } 1174*a2f3d83cSJiri Slaby (SUSE) addr += 4; 1175*a2f3d83cSJiri Slaby (SUSE) length -= 4; 1176*a2f3d83cSJiri Slaby (SUSE) } 1177*a2f3d83cSJiri Slaby (SUSE) } 1178*a2f3d83cSJiri Slaby (SUSE) if (ret) 1179*a2f3d83cSJiri Slaby (SUSE) break; 1180*a2f3d83cSJiri Slaby (SUSE) } 1181*a2f3d83cSJiri Slaby (SUSE) 1182*a2f3d83cSJiri Slaby (SUSE) return ret; 1183*a2f3d83cSJiri Slaby (SUSE) } 1184*a2f3d83cSJiri Slaby (SUSE) 1185*a2f3d83cSJiri Slaby (SUSE) /* High level: Gfx (indexed) register access */ 1186*a2f3d83cSJiri Slaby (SUSE) 1187*a2f3d83cSJiri Slaby (SUSE) static int sisusb_setidxreg(struct sisusb_usb_data *sisusb, u32 port, 1188*a2f3d83cSJiri Slaby (SUSE) u8 index, u8 data) 1189*a2f3d83cSJiri Slaby (SUSE) { 1190*a2f3d83cSJiri Slaby (SUSE) int ret; 1191*a2f3d83cSJiri Slaby (SUSE) 1192*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); 1193*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); 1194*a2f3d83cSJiri Slaby (SUSE) return ret; 1195*a2f3d83cSJiri Slaby (SUSE) } 1196*a2f3d83cSJiri Slaby (SUSE) 1197*a2f3d83cSJiri Slaby (SUSE) static int sisusb_getidxreg(struct sisusb_usb_data *sisusb, u32 port, 1198*a2f3d83cSJiri Slaby (SUSE) u8 index, u8 *data) 1199*a2f3d83cSJiri Slaby (SUSE) { 1200*a2f3d83cSJiri Slaby (SUSE) int ret; 1201*a2f3d83cSJiri Slaby (SUSE) 1202*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); 1203*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); 1204*a2f3d83cSJiri Slaby (SUSE) return ret; 1205*a2f3d83cSJiri Slaby (SUSE) } 1206*a2f3d83cSJiri Slaby (SUSE) 1207*a2f3d83cSJiri Slaby (SUSE) static int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, u32 port, u8 idx, 1208*a2f3d83cSJiri Slaby (SUSE) u8 myand, u8 myor) 1209*a2f3d83cSJiri Slaby (SUSE) { 1210*a2f3d83cSJiri Slaby (SUSE) int ret; 1211*a2f3d83cSJiri Slaby (SUSE) u8 tmp; 1212*a2f3d83cSJiri Slaby (SUSE) 1213*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx); 1214*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp); 1215*a2f3d83cSJiri Slaby (SUSE) tmp &= myand; 1216*a2f3d83cSJiri Slaby (SUSE) tmp |= myor; 1217*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp); 1218*a2f3d83cSJiri Slaby (SUSE) return ret; 1219*a2f3d83cSJiri Slaby (SUSE) } 1220*a2f3d83cSJiri Slaby (SUSE) 1221*a2f3d83cSJiri Slaby (SUSE) static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb, 1222*a2f3d83cSJiri Slaby (SUSE) u32 port, u8 idx, u8 data, u8 mask) 1223*a2f3d83cSJiri Slaby (SUSE) { 1224*a2f3d83cSJiri Slaby (SUSE) int ret; 1225*a2f3d83cSJiri Slaby (SUSE) u8 tmp; 1226*a2f3d83cSJiri Slaby (SUSE) 1227*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx); 1228*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp); 1229*a2f3d83cSJiri Slaby (SUSE) tmp &= ~(mask); 1230*a2f3d83cSJiri Slaby (SUSE) tmp |= (data & mask); 1231*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp); 1232*a2f3d83cSJiri Slaby (SUSE) return ret; 1233*a2f3d83cSJiri Slaby (SUSE) } 1234*a2f3d83cSJiri Slaby (SUSE) 1235*a2f3d83cSJiri Slaby (SUSE) static int sisusb_setidxregor(struct sisusb_usb_data *sisusb, u32 port, 1236*a2f3d83cSJiri Slaby (SUSE) u8 index, u8 myor) 1237*a2f3d83cSJiri Slaby (SUSE) { 1238*a2f3d83cSJiri Slaby (SUSE) return sisusb_setidxregandor(sisusb, port, index, 0xff, myor); 1239*a2f3d83cSJiri Slaby (SUSE) } 1240*a2f3d83cSJiri Slaby (SUSE) 1241*a2f3d83cSJiri Slaby (SUSE) static int sisusb_setidxregand(struct sisusb_usb_data *sisusb, u32 port, 1242*a2f3d83cSJiri Slaby (SUSE) u8 idx, u8 myand) 1243*a2f3d83cSJiri Slaby (SUSE) { 1244*a2f3d83cSJiri Slaby (SUSE) return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00); 1245*a2f3d83cSJiri Slaby (SUSE) } 1246*a2f3d83cSJiri Slaby (SUSE) 1247*a2f3d83cSJiri Slaby (SUSE) /* Write/read video ram */ 1248*a2f3d83cSJiri Slaby (SUSE) 1249*a2f3d83cSJiri Slaby (SUSE) #ifdef SISUSBENDIANTEST 1250*a2f3d83cSJiri Slaby (SUSE) static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb) 1251*a2f3d83cSJiri Slaby (SUSE) { 1252*a2f3d83cSJiri Slaby (SUSE) static u8 srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; 1253*a2f3d83cSJiri Slaby (SUSE) char destbuffer[10]; 1254*a2f3d83cSJiri Slaby (SUSE) int i, j; 1255*a2f3d83cSJiri Slaby (SUSE) 1256*a2f3d83cSJiri Slaby (SUSE) sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7); 1257*a2f3d83cSJiri Slaby (SUSE) 1258*a2f3d83cSJiri Slaby (SUSE) for (i = 1; i <= 7; i++) { 1259*a2f3d83cSJiri Slaby (SUSE) dev_dbg(&sisusb->sisusb_dev->dev, 1260*a2f3d83cSJiri Slaby (SUSE) "sisusb: rwtest %d bytes\n", i); 1261*a2f3d83cSJiri Slaby (SUSE) sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i); 1262*a2f3d83cSJiri Slaby (SUSE) for (j = 0; j < i; j++) { 1263*a2f3d83cSJiri Slaby (SUSE) dev_dbg(&sisusb->sisusb_dev->dev, 1264*a2f3d83cSJiri Slaby (SUSE) "rwtest read[%d] = %x\n", 1265*a2f3d83cSJiri Slaby (SUSE) j, destbuffer[j]); 1266*a2f3d83cSJiri Slaby (SUSE) } 1267*a2f3d83cSJiri Slaby (SUSE) } 1268*a2f3d83cSJiri Slaby (SUSE) } 1269*a2f3d83cSJiri Slaby (SUSE) #endif 1270*a2f3d83cSJiri Slaby (SUSE) 1271*a2f3d83cSJiri Slaby (SUSE) /* access pci config registers (reg numbers 0, 4, 8, etc) */ 1272*a2f3d83cSJiri Slaby (SUSE) 1273*a2f3d83cSJiri Slaby (SUSE) static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb, 1274*a2f3d83cSJiri Slaby (SUSE) int regnum, u32 data) 1275*a2f3d83cSJiri Slaby (SUSE) { 1276*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 1277*a2f3d83cSJiri Slaby (SUSE) 1278*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x008f; 1279*a2f3d83cSJiri Slaby (SUSE) packet.address = regnum | 0x10000; 1280*a2f3d83cSJiri Slaby (SUSE) packet.data = data; 1281*a2f3d83cSJiri Slaby (SUSE) return sisusb_send_packet(sisusb, 10, &packet); 1282*a2f3d83cSJiri Slaby (SUSE) } 1283*a2f3d83cSJiri Slaby (SUSE) 1284*a2f3d83cSJiri Slaby (SUSE) static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb, 1285*a2f3d83cSJiri Slaby (SUSE) int regnum, u32 *data) 1286*a2f3d83cSJiri Slaby (SUSE) { 1287*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 1288*a2f3d83cSJiri Slaby (SUSE) int ret; 1289*a2f3d83cSJiri Slaby (SUSE) 1290*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x008f; 1291*a2f3d83cSJiri Slaby (SUSE) packet.address = (u32)regnum | 0x10000; 1292*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_packet(sisusb, 6, &packet); 1293*a2f3d83cSJiri Slaby (SUSE) *data = packet.data; 1294*a2f3d83cSJiri Slaby (SUSE) return ret; 1295*a2f3d83cSJiri Slaby (SUSE) } 1296*a2f3d83cSJiri Slaby (SUSE) 1297*a2f3d83cSJiri Slaby (SUSE) /* Clear video RAM */ 1298*a2f3d83cSJiri Slaby (SUSE) 1299*a2f3d83cSJiri Slaby (SUSE) static int sisusb_clear_vram(struct sisusb_usb_data *sisusb, 1300*a2f3d83cSJiri Slaby (SUSE) u32 address, int length) 1301*a2f3d83cSJiri Slaby (SUSE) { 1302*a2f3d83cSJiri Slaby (SUSE) int ret, i; 1303*a2f3d83cSJiri Slaby (SUSE) ssize_t j; 1304*a2f3d83cSJiri Slaby (SUSE) 1305*a2f3d83cSJiri Slaby (SUSE) if (address < sisusb->vrambase) 1306*a2f3d83cSJiri Slaby (SUSE) return 1; 1307*a2f3d83cSJiri Slaby (SUSE) 1308*a2f3d83cSJiri Slaby (SUSE) if (address >= sisusb->vrambase + sisusb->vramsize) 1309*a2f3d83cSJiri Slaby (SUSE) return 1; 1310*a2f3d83cSJiri Slaby (SUSE) 1311*a2f3d83cSJiri Slaby (SUSE) if (address + length > sisusb->vrambase + sisusb->vramsize) 1312*a2f3d83cSJiri Slaby (SUSE) length = sisusb->vrambase + sisusb->vramsize - address; 1313*a2f3d83cSJiri Slaby (SUSE) 1314*a2f3d83cSJiri Slaby (SUSE) if (length <= 0) 1315*a2f3d83cSJiri Slaby (SUSE) return 0; 1316*a2f3d83cSJiri Slaby (SUSE) 1317*a2f3d83cSJiri Slaby (SUSE) /* allocate free buffer/urb and clear the buffer */ 1318*a2f3d83cSJiri Slaby (SUSE) i = sisusb_alloc_outbuf(sisusb); 1319*a2f3d83cSJiri Slaby (SUSE) if (i < 0) 1320*a2f3d83cSJiri Slaby (SUSE) return -EBUSY; 1321*a2f3d83cSJiri Slaby (SUSE) 1322*a2f3d83cSJiri Slaby (SUSE) memset(sisusb->obuf[i], 0, sisusb->obufsize); 1323*a2f3d83cSJiri Slaby (SUSE) 1324*a2f3d83cSJiri Slaby (SUSE) /* We can write a length > buffer size here. The buffer 1325*a2f3d83cSJiri Slaby (SUSE) * data will simply be re-used (like a ring-buffer). 1326*a2f3d83cSJiri Slaby (SUSE) */ 1327*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j); 1328*a2f3d83cSJiri Slaby (SUSE) 1329*a2f3d83cSJiri Slaby (SUSE) /* Free the buffer/urb */ 1330*a2f3d83cSJiri Slaby (SUSE) sisusb_free_outbuf(sisusb, i); 1331*a2f3d83cSJiri Slaby (SUSE) 1332*a2f3d83cSJiri Slaby (SUSE) return ret; 1333*a2f3d83cSJiri Slaby (SUSE) } 1334*a2f3d83cSJiri Slaby (SUSE) 1335*a2f3d83cSJiri Slaby (SUSE) /* Initialize the graphics core (return 0 on success) 1336*a2f3d83cSJiri Slaby (SUSE) * This resets the graphics hardware and puts it into 1337*a2f3d83cSJiri Slaby (SUSE) * a defined mode (640x480@60Hz) 1338*a2f3d83cSJiri Slaby (SUSE) */ 1339*a2f3d83cSJiri Slaby (SUSE) 1340*a2f3d83cSJiri Slaby (SUSE) #define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) 1341*a2f3d83cSJiri Slaby (SUSE) #define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) 1342*a2f3d83cSJiri Slaby (SUSE) #define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d) 1343*a2f3d83cSJiri Slaby (SUSE) #define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d) 1344*a2f3d83cSJiri Slaby (SUSE) #define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o) 1345*a2f3d83cSJiri Slaby (SUSE) #define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a) 1346*a2f3d83cSJiri Slaby (SUSE) #define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o) 1347*a2f3d83cSJiri Slaby (SUSE) #define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) 1348*a2f3d83cSJiri Slaby (SUSE) #define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) 1349*a2f3d83cSJiri Slaby (SUSE) #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) 1350*a2f3d83cSJiri Slaby (SUSE) #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) 1351*a2f3d83cSJiri Slaby (SUSE) 1352*a2f3d83cSJiri Slaby (SUSE) static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) 1353*a2f3d83cSJiri Slaby (SUSE) { 1354*a2f3d83cSJiri Slaby (SUSE) int ret; 1355*a2f3d83cSJiri Slaby (SUSE) u8 tmp8; 1356*a2f3d83cSJiri Slaby (SUSE) 1357*a2f3d83cSJiri Slaby (SUSE) ret = GETIREG(SISSR, 0x16, &tmp8); 1358*a2f3d83cSJiri Slaby (SUSE) if (ramtype <= 1) { 1359*a2f3d83cSJiri Slaby (SUSE) tmp8 &= 0x3f; 1360*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1361*a2f3d83cSJiri Slaby (SUSE) tmp8 |= 0x80; 1362*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1363*a2f3d83cSJiri Slaby (SUSE) } else { 1364*a2f3d83cSJiri Slaby (SUSE) tmp8 |= 0xc0; 1365*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1366*a2f3d83cSJiri Slaby (SUSE) tmp8 &= 0x0f; 1367*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1368*a2f3d83cSJiri Slaby (SUSE) tmp8 |= 0x80; 1369*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1370*a2f3d83cSJiri Slaby (SUSE) tmp8 &= 0x0f; 1371*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1372*a2f3d83cSJiri Slaby (SUSE) tmp8 |= 0xd0; 1373*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1374*a2f3d83cSJiri Slaby (SUSE) tmp8 &= 0x0f; 1375*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1376*a2f3d83cSJiri Slaby (SUSE) tmp8 |= 0xa0; 1377*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, tmp8); 1378*a2f3d83cSJiri Slaby (SUSE) } 1379*a2f3d83cSJiri Slaby (SUSE) return ret; 1380*a2f3d83cSJiri Slaby (SUSE) } 1381*a2f3d83cSJiri Slaby (SUSE) 1382*a2f3d83cSJiri Slaby (SUSE) static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb, 1383*a2f3d83cSJiri Slaby (SUSE) int *bw, int *chab) 1384*a2f3d83cSJiri Slaby (SUSE) { 1385*a2f3d83cSJiri Slaby (SUSE) int ret; 1386*a2f3d83cSJiri Slaby (SUSE) u8 ramtype, done = 0; 1387*a2f3d83cSJiri Slaby (SUSE) u32 t0, t1, t2, t3; 1388*a2f3d83cSJiri Slaby (SUSE) u32 ramptr = SISUSB_PCI_MEMBASE; 1389*a2f3d83cSJiri Slaby (SUSE) 1390*a2f3d83cSJiri Slaby (SUSE) ret = GETIREG(SISSR, 0x3a, &ramtype); 1391*a2f3d83cSJiri Slaby (SUSE) ramtype &= 3; 1392*a2f3d83cSJiri Slaby (SUSE) 1393*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x13, 0x00); 1394*a2f3d83cSJiri Slaby (SUSE) 1395*a2f3d83cSJiri Slaby (SUSE) if (ramtype <= 1) { 1396*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x12); 1397*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISSR, 0x15, 0xef); 1398*a2f3d83cSJiri Slaby (SUSE) } else { 1399*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x02); 1400*a2f3d83cSJiri Slaby (SUSE) } 1401*a2f3d83cSJiri Slaby (SUSE) 1402*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_triggersr16(sisusb, ramtype); 1403*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 0, 0x01234567); 1404*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 4, 0x456789ab); 1405*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 8, 0x89abcdef); 1406*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 12, 0xcdef0123); 1407*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 16, 0x55555555); 1408*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 20, 0x55555555); 1409*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 24, 0xffffffff); 1410*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 28, 0xffffffff); 1411*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 0, &t0); 1412*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 4, &t1); 1413*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 8, &t2); 1414*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 12, &t3); 1415*a2f3d83cSJiri Slaby (SUSE) 1416*a2f3d83cSJiri Slaby (SUSE) if (ramtype <= 1) { 1417*a2f3d83cSJiri Slaby (SUSE) 1418*a2f3d83cSJiri Slaby (SUSE) *chab = 0; *bw = 64; 1419*a2f3d83cSJiri Slaby (SUSE) 1420*a2f3d83cSJiri Slaby (SUSE) if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) { 1421*a2f3d83cSJiri Slaby (SUSE) if ((t1 == 0x456789ab) && (t0 == 0x01234567)) { 1422*a2f3d83cSJiri Slaby (SUSE) *chab = 0; *bw = 64; 1423*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISSR, 0x14, 0xfd); 1424*a2f3d83cSJiri Slaby (SUSE) } 1425*a2f3d83cSJiri Slaby (SUSE) } 1426*a2f3d83cSJiri Slaby (SUSE) if ((t1 != 0x456789ab) || (t0 != 0x01234567)) { 1427*a2f3d83cSJiri Slaby (SUSE) *chab = 1; *bw = 64; 1428*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01); 1429*a2f3d83cSJiri Slaby (SUSE) 1430*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_triggersr16(sisusb, ramtype); 1431*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 0, 0x89abcdef); 1432*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 4, 0xcdef0123); 1433*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 8, 0x55555555); 1434*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 12, 0x55555555); 1435*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 16, 0xaaaaaaaa); 1436*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 20, 0xaaaaaaaa); 1437*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 4, &t1); 1438*a2f3d83cSJiri Slaby (SUSE) 1439*a2f3d83cSJiri Slaby (SUSE) if (t1 != 0xcdef0123) { 1440*a2f3d83cSJiri Slaby (SUSE) *bw = 32; 1441*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x15, 0x10); 1442*a2f3d83cSJiri Slaby (SUSE) } 1443*a2f3d83cSJiri Slaby (SUSE) } 1444*a2f3d83cSJiri Slaby (SUSE) 1445*a2f3d83cSJiri Slaby (SUSE) } else { 1446*a2f3d83cSJiri Slaby (SUSE) 1447*a2f3d83cSJiri Slaby (SUSE) *chab = 0; *bw = 64; /* default: cha, bw = 64 */ 1448*a2f3d83cSJiri Slaby (SUSE) 1449*a2f3d83cSJiri Slaby (SUSE) done = 0; 1450*a2f3d83cSJiri Slaby (SUSE) 1451*a2f3d83cSJiri Slaby (SUSE) if (t1 == 0x456789ab) { 1452*a2f3d83cSJiri Slaby (SUSE) if (t0 == 0x01234567) { 1453*a2f3d83cSJiri Slaby (SUSE) *chab = 0; *bw = 64; 1454*a2f3d83cSJiri Slaby (SUSE) done = 1; 1455*a2f3d83cSJiri Slaby (SUSE) } 1456*a2f3d83cSJiri Slaby (SUSE) } else { 1457*a2f3d83cSJiri Slaby (SUSE) if (t0 == 0x01234567) { 1458*a2f3d83cSJiri Slaby (SUSE) *chab = 0; *bw = 32; 1459*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x00); 1460*a2f3d83cSJiri Slaby (SUSE) done = 1; 1461*a2f3d83cSJiri Slaby (SUSE) } 1462*a2f3d83cSJiri Slaby (SUSE) } 1463*a2f3d83cSJiri Slaby (SUSE) 1464*a2f3d83cSJiri Slaby (SUSE) if (!done) { 1465*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x03); 1466*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_triggersr16(sisusb, ramtype); 1467*a2f3d83cSJiri Slaby (SUSE) 1468*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 0, 0x01234567); 1469*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 4, 0x456789ab); 1470*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 8, 0x89abcdef); 1471*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 12, 0xcdef0123); 1472*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 16, 0x55555555); 1473*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 20, 0x55555555); 1474*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 24, 0xffffffff); 1475*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(ramptr + 28, 0xffffffff); 1476*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 0, &t0); 1477*a2f3d83cSJiri Slaby (SUSE) ret |= READL(ramptr + 4, &t1); 1478*a2f3d83cSJiri Slaby (SUSE) 1479*a2f3d83cSJiri Slaby (SUSE) if (t1 == 0x456789ab) { 1480*a2f3d83cSJiri Slaby (SUSE) if (t0 == 0x01234567) { 1481*a2f3d83cSJiri Slaby (SUSE) *chab = 1; *bw = 64; 1482*a2f3d83cSJiri Slaby (SUSE) return ret; 1483*a2f3d83cSJiri Slaby (SUSE) } /* else error */ 1484*a2f3d83cSJiri Slaby (SUSE) } else { 1485*a2f3d83cSJiri Slaby (SUSE) if (t0 == 0x01234567) { 1486*a2f3d83cSJiri Slaby (SUSE) *chab = 1; *bw = 32; 1487*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x01); 1488*a2f3d83cSJiri Slaby (SUSE) } /* else error */ 1489*a2f3d83cSJiri Slaby (SUSE) } 1490*a2f3d83cSJiri Slaby (SUSE) } 1491*a2f3d83cSJiri Slaby (SUSE) } 1492*a2f3d83cSJiri Slaby (SUSE) return ret; 1493*a2f3d83cSJiri Slaby (SUSE) } 1494*a2f3d83cSJiri Slaby (SUSE) 1495*a2f3d83cSJiri Slaby (SUSE) static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb) 1496*a2f3d83cSJiri Slaby (SUSE) { 1497*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 1498*a2f3d83cSJiri Slaby (SUSE) u32 ramptr = SISUSB_PCI_MEMBASE; 1499*a2f3d83cSJiri Slaby (SUSE) u8 tmp1, tmp2, i, j; 1500*a2f3d83cSJiri Slaby (SUSE) 1501*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEB(ramptr, 0xaa); 1502*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEB(ramptr + 16, 0x55); 1503*a2f3d83cSJiri Slaby (SUSE) ret |= READB(ramptr, &tmp1); 1504*a2f3d83cSJiri Slaby (SUSE) ret |= READB(ramptr + 16, &tmp2); 1505*a2f3d83cSJiri Slaby (SUSE) if ((tmp1 != 0xaa) || (tmp2 != 0x55)) { 1506*a2f3d83cSJiri Slaby (SUSE) for (i = 0, j = 16; i < 2; i++, j += 16) { 1507*a2f3d83cSJiri Slaby (SUSE) ret |= GETIREG(SISSR, 0x21, &tmp1); 1508*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb)); 1509*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */ 1510*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */ 1511*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x21, tmp1); 1512*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEB(ramptr + 16 + j, j); 1513*a2f3d83cSJiri Slaby (SUSE) ret |= READB(ramptr + 16 + j, &tmp1); 1514*a2f3d83cSJiri Slaby (SUSE) if (tmp1 == j) { 1515*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEB(ramptr + j, j); 1516*a2f3d83cSJiri Slaby (SUSE) break; 1517*a2f3d83cSJiri Slaby (SUSE) } 1518*a2f3d83cSJiri Slaby (SUSE) } 1519*a2f3d83cSJiri Slaby (SUSE) } 1520*a2f3d83cSJiri Slaby (SUSE) return ret; 1521*a2f3d83cSJiri Slaby (SUSE) } 1522*a2f3d83cSJiri Slaby (SUSE) 1523*a2f3d83cSJiri Slaby (SUSE) static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, 1524*a2f3d83cSJiri Slaby (SUSE) int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw) 1525*a2f3d83cSJiri Slaby (SUSE) { 1526*a2f3d83cSJiri Slaby (SUSE) int ret = 0, ranksize; 1527*a2f3d83cSJiri Slaby (SUSE) u8 tmp; 1528*a2f3d83cSJiri Slaby (SUSE) 1529*a2f3d83cSJiri Slaby (SUSE) *iret = 0; 1530*a2f3d83cSJiri Slaby (SUSE) 1531*a2f3d83cSJiri Slaby (SUSE) if ((rankno == 2) && (dramtype[index][0] == 2)) 1532*a2f3d83cSJiri Slaby (SUSE) return ret; 1533*a2f3d83cSJiri Slaby (SUSE) 1534*a2f3d83cSJiri Slaby (SUSE) ranksize = dramtype[index][3] / 2 * bw / 32; 1535*a2f3d83cSJiri Slaby (SUSE) 1536*a2f3d83cSJiri Slaby (SUSE) if ((ranksize * rankno) > 128) 1537*a2f3d83cSJiri Slaby (SUSE) return ret; 1538*a2f3d83cSJiri Slaby (SUSE) 1539*a2f3d83cSJiri Slaby (SUSE) tmp = 0; 1540*a2f3d83cSJiri Slaby (SUSE) while ((ranksize >>= 1) > 0) 1541*a2f3d83cSJiri Slaby (SUSE) tmp += 0x10; 1542*a2f3d83cSJiri Slaby (SUSE) 1543*a2f3d83cSJiri Slaby (SUSE) tmp |= ((rankno - 1) << 2); 1544*a2f3d83cSJiri Slaby (SUSE) tmp |= ((bw / 64) & 0x02); 1545*a2f3d83cSJiri Slaby (SUSE) tmp |= (chab & 0x01); 1546*a2f3d83cSJiri Slaby (SUSE) 1547*a2f3d83cSJiri Slaby (SUSE) ret = SETIREG(SISSR, 0x14, tmp); 1548*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_triggersr16(sisusb, 0); /* sic! */ 1549*a2f3d83cSJiri Slaby (SUSE) 1550*a2f3d83cSJiri Slaby (SUSE) *iret = 1; 1551*a2f3d83cSJiri Slaby (SUSE) 1552*a2f3d83cSJiri Slaby (SUSE) return ret; 1553*a2f3d83cSJiri Slaby (SUSE) } 1554*a2f3d83cSJiri Slaby (SUSE) 1555*a2f3d83cSJiri Slaby (SUSE) static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, 1556*a2f3d83cSJiri Slaby (SUSE) u32 inc, int testn) 1557*a2f3d83cSJiri Slaby (SUSE) { 1558*a2f3d83cSJiri Slaby (SUSE) int ret = 0, i; 1559*a2f3d83cSJiri Slaby (SUSE) u32 j, tmp; 1560*a2f3d83cSJiri Slaby (SUSE) 1561*a2f3d83cSJiri Slaby (SUSE) *iret = 0; 1562*a2f3d83cSJiri Slaby (SUSE) 1563*a2f3d83cSJiri Slaby (SUSE) for (i = 0, j = 0; i < testn; i++) { 1564*a2f3d83cSJiri Slaby (SUSE) ret |= WRITEL(sisusb->vrambase + j, j); 1565*a2f3d83cSJiri Slaby (SUSE) j += inc; 1566*a2f3d83cSJiri Slaby (SUSE) } 1567*a2f3d83cSJiri Slaby (SUSE) 1568*a2f3d83cSJiri Slaby (SUSE) for (i = 0, j = 0; i < testn; i++) { 1569*a2f3d83cSJiri Slaby (SUSE) ret |= READL(sisusb->vrambase + j, &tmp); 1570*a2f3d83cSJiri Slaby (SUSE) if (tmp != j) 1571*a2f3d83cSJiri Slaby (SUSE) return ret; 1572*a2f3d83cSJiri Slaby (SUSE) 1573*a2f3d83cSJiri Slaby (SUSE) j += inc; 1574*a2f3d83cSJiri Slaby (SUSE) } 1575*a2f3d83cSJiri Slaby (SUSE) 1576*a2f3d83cSJiri Slaby (SUSE) *iret = 1; 1577*a2f3d83cSJiri Slaby (SUSE) return ret; 1578*a2f3d83cSJiri Slaby (SUSE) } 1579*a2f3d83cSJiri Slaby (SUSE) 1580*a2f3d83cSJiri Slaby (SUSE) static int sisusb_check_ranks(struct sisusb_usb_data *sisusb, 1581*a2f3d83cSJiri Slaby (SUSE) int *iret, int rankno, int idx, int bw, const u8 rtype[][5]) 1582*a2f3d83cSJiri Slaby (SUSE) { 1583*a2f3d83cSJiri Slaby (SUSE) int ret = 0, i, i2ret; 1584*a2f3d83cSJiri Slaby (SUSE) u32 inc; 1585*a2f3d83cSJiri Slaby (SUSE) 1586*a2f3d83cSJiri Slaby (SUSE) *iret = 0; 1587*a2f3d83cSJiri Slaby (SUSE) 1588*a2f3d83cSJiri Slaby (SUSE) for (i = rankno; i >= 1; i--) { 1589*a2f3d83cSJiri Slaby (SUSE) inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] + 1590*a2f3d83cSJiri Slaby (SUSE) bw / 64 + i); 1591*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2); 1592*a2f3d83cSJiri Slaby (SUSE) if (!i2ret) 1593*a2f3d83cSJiri Slaby (SUSE) return ret; 1594*a2f3d83cSJiri Slaby (SUSE) } 1595*a2f3d83cSJiri Slaby (SUSE) 1596*a2f3d83cSJiri Slaby (SUSE) inc = 1 << (rtype[idx][2] + bw / 64 + 2); 1597*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4); 1598*a2f3d83cSJiri Slaby (SUSE) if (!i2ret) 1599*a2f3d83cSJiri Slaby (SUSE) return ret; 1600*a2f3d83cSJiri Slaby (SUSE) 1601*a2f3d83cSJiri Slaby (SUSE) inc = 1 << (10 + bw / 64); 1602*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2); 1603*a2f3d83cSJiri Slaby (SUSE) if (!i2ret) 1604*a2f3d83cSJiri Slaby (SUSE) return ret; 1605*a2f3d83cSJiri Slaby (SUSE) 1606*a2f3d83cSJiri Slaby (SUSE) *iret = 1; 1607*a2f3d83cSJiri Slaby (SUSE) return ret; 1608*a2f3d83cSJiri Slaby (SUSE) } 1609*a2f3d83cSJiri Slaby (SUSE) 1610*a2f3d83cSJiri Slaby (SUSE) static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, 1611*a2f3d83cSJiri Slaby (SUSE) int bw, int chab) 1612*a2f3d83cSJiri Slaby (SUSE) { 1613*a2f3d83cSJiri Slaby (SUSE) int ret = 0, i2ret = 0, i, j; 1614*a2f3d83cSJiri Slaby (SUSE) static const u8 sdramtype[13][5] = { 1615*a2f3d83cSJiri Slaby (SUSE) { 2, 12, 9, 64, 0x35 }, 1616*a2f3d83cSJiri Slaby (SUSE) { 1, 13, 9, 64, 0x44 }, 1617*a2f3d83cSJiri Slaby (SUSE) { 2, 12, 8, 32, 0x31 }, 1618*a2f3d83cSJiri Slaby (SUSE) { 2, 11, 9, 32, 0x25 }, 1619*a2f3d83cSJiri Slaby (SUSE) { 1, 12, 9, 32, 0x34 }, 1620*a2f3d83cSJiri Slaby (SUSE) { 1, 13, 8, 32, 0x40 }, 1621*a2f3d83cSJiri Slaby (SUSE) { 2, 11, 8, 16, 0x21 }, 1622*a2f3d83cSJiri Slaby (SUSE) { 1, 12, 8, 16, 0x30 }, 1623*a2f3d83cSJiri Slaby (SUSE) { 1, 11, 9, 16, 0x24 }, 1624*a2f3d83cSJiri Slaby (SUSE) { 1, 11, 8, 8, 0x20 }, 1625*a2f3d83cSJiri Slaby (SUSE) { 2, 9, 8, 4, 0x01 }, 1626*a2f3d83cSJiri Slaby (SUSE) { 1, 10, 8, 4, 0x10 }, 1627*a2f3d83cSJiri Slaby (SUSE) { 1, 9, 8, 2, 0x00 } 1628*a2f3d83cSJiri Slaby (SUSE) }; 1629*a2f3d83cSJiri Slaby (SUSE) 1630*a2f3d83cSJiri Slaby (SUSE) *iret = 1; /* error */ 1631*a2f3d83cSJiri Slaby (SUSE) 1632*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < 13; i++) { 1633*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]); 1634*a2f3d83cSJiri Slaby (SUSE) for (j = 2; j > 0; j--) { 1635*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab, 1636*a2f3d83cSJiri Slaby (SUSE) sdramtype, bw); 1637*a2f3d83cSJiri Slaby (SUSE) if (!i2ret) 1638*a2f3d83cSJiri Slaby (SUSE) continue; 1639*a2f3d83cSJiri Slaby (SUSE) 1640*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw, 1641*a2f3d83cSJiri Slaby (SUSE) sdramtype); 1642*a2f3d83cSJiri Slaby (SUSE) if (i2ret) { 1643*a2f3d83cSJiri Slaby (SUSE) *iret = 0; /* ram size found */ 1644*a2f3d83cSJiri Slaby (SUSE) return ret; 1645*a2f3d83cSJiri Slaby (SUSE) } 1646*a2f3d83cSJiri Slaby (SUSE) } 1647*a2f3d83cSJiri Slaby (SUSE) } 1648*a2f3d83cSJiri Slaby (SUSE) 1649*a2f3d83cSJiri Slaby (SUSE) return ret; 1650*a2f3d83cSJiri Slaby (SUSE) } 1651*a2f3d83cSJiri Slaby (SUSE) 1652*a2f3d83cSJiri Slaby (SUSE) static int sisusb_setup_screen(struct sisusb_usb_data *sisusb, 1653*a2f3d83cSJiri Slaby (SUSE) int clrall, int drwfr) 1654*a2f3d83cSJiri Slaby (SUSE) { 1655*a2f3d83cSJiri Slaby (SUSE) int ret = 0; 1656*a2f3d83cSJiri Slaby (SUSE) u32 address; 1657*a2f3d83cSJiri Slaby (SUSE) int i, length, modex, modey, bpp; 1658*a2f3d83cSJiri Slaby (SUSE) 1659*a2f3d83cSJiri Slaby (SUSE) modex = 640; modey = 480; bpp = 2; 1660*a2f3d83cSJiri Slaby (SUSE) 1661*a2f3d83cSJiri Slaby (SUSE) address = sisusb->vrambase; /* Clear video ram */ 1662*a2f3d83cSJiri Slaby (SUSE) 1663*a2f3d83cSJiri Slaby (SUSE) if (clrall) 1664*a2f3d83cSJiri Slaby (SUSE) length = sisusb->vramsize; 1665*a2f3d83cSJiri Slaby (SUSE) else 1666*a2f3d83cSJiri Slaby (SUSE) length = modex * bpp * modey; 1667*a2f3d83cSJiri Slaby (SUSE) 1668*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_clear_vram(sisusb, address, length); 1669*a2f3d83cSJiri Slaby (SUSE) 1670*a2f3d83cSJiri Slaby (SUSE) if (!ret && drwfr) { 1671*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < modex; i++) { 1672*a2f3d83cSJiri Slaby (SUSE) address = sisusb->vrambase + (i * bpp); 1673*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, 1674*a2f3d83cSJiri Slaby (SUSE) address, 0xf100); 1675*a2f3d83cSJiri Slaby (SUSE) address += (modex * (modey-1) * bpp); 1676*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, 1677*a2f3d83cSJiri Slaby (SUSE) address, 0xf100); 1678*a2f3d83cSJiri Slaby (SUSE) } 1679*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < modey; i++) { 1680*a2f3d83cSJiri Slaby (SUSE) address = sisusb->vrambase + ((i * modex) * bpp); 1681*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, 1682*a2f3d83cSJiri Slaby (SUSE) address, 0xf100); 1683*a2f3d83cSJiri Slaby (SUSE) address += ((modex - 1) * bpp); 1684*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, 1685*a2f3d83cSJiri Slaby (SUSE) address, 0xf100); 1686*a2f3d83cSJiri Slaby (SUSE) } 1687*a2f3d83cSJiri Slaby (SUSE) } 1688*a2f3d83cSJiri Slaby (SUSE) 1689*a2f3d83cSJiri Slaby (SUSE) return ret; 1690*a2f3d83cSJiri Slaby (SUSE) } 1691*a2f3d83cSJiri Slaby (SUSE) 1692*a2f3d83cSJiri Slaby (SUSE) static void sisusb_set_default_mode(struct sisusb_usb_data *sisusb, 1693*a2f3d83cSJiri Slaby (SUSE) int touchengines) 1694*a2f3d83cSJiri Slaby (SUSE) { 1695*a2f3d83cSJiri Slaby (SUSE) int i, j, modex, bpp, du; 1696*a2f3d83cSJiri Slaby (SUSE) u8 sr31, cr63, tmp8; 1697*a2f3d83cSJiri Slaby (SUSE) static const char attrdata[] = { 1698*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 1699*a2f3d83cSJiri Slaby (SUSE) 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 1700*a2f3d83cSJiri Slaby (SUSE) 0x01, 0x00, 0x00, 0x00 1701*a2f3d83cSJiri Slaby (SUSE) }; 1702*a2f3d83cSJiri Slaby (SUSE) static const char crtcrdata[] = { 1703*a2f3d83cSJiri Slaby (SUSE) 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 1704*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1705*a2f3d83cSJiri Slaby (SUSE) 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, 1706*a2f3d83cSJiri Slaby (SUSE) 0xff 1707*a2f3d83cSJiri Slaby (SUSE) }; 1708*a2f3d83cSJiri Slaby (SUSE) static const char grcdata[] = { 1709*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 1710*a2f3d83cSJiri Slaby (SUSE) 0xff 1711*a2f3d83cSJiri Slaby (SUSE) }; 1712*a2f3d83cSJiri Slaby (SUSE) static const char crtcdata[] = { 1713*a2f3d83cSJiri Slaby (SUSE) 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e, 1714*a2f3d83cSJiri Slaby (SUSE) 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05, 1715*a2f3d83cSJiri Slaby (SUSE) 0x00 1716*a2f3d83cSJiri Slaby (SUSE) }; 1717*a2f3d83cSJiri Slaby (SUSE) 1718*a2f3d83cSJiri Slaby (SUSE) modex = 640; bpp = 2; 1719*a2f3d83cSJiri Slaby (SUSE) 1720*a2f3d83cSJiri Slaby (SUSE) GETIREG(SISSR, 0x31, &sr31); 1721*a2f3d83cSJiri Slaby (SUSE) GETIREG(SISCR, 0x63, &cr63); 1722*a2f3d83cSJiri Slaby (SUSE) SETIREGOR(SISSR, 0x01, 0x20); 1723*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x63, cr63 & 0xbf); 1724*a2f3d83cSJiri Slaby (SUSE) SETIREGOR(SISCR, 0x17, 0x80); 1725*a2f3d83cSJiri Slaby (SUSE) SETIREGOR(SISSR, 0x1f, 0x04); 1726*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x07, 0xfb); 1727*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x00, 0x03); /* seq */ 1728*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x01, 0x21); 1729*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x02, 0x0f); 1730*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x03, 0x00); 1731*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x04, 0x0e); 1732*a2f3d83cSJiri Slaby (SUSE) SETREG(SISMISCW, 0x23); /* misc */ 1733*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i <= 0x18; i++) { /* crtc */ 1734*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, i, crtcrdata[i]); 1735*a2f3d83cSJiri Slaby (SUSE) } 1736*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i <= 0x13; i++) { /* att */ 1737*a2f3d83cSJiri Slaby (SUSE) GETREG(SISINPSTAT, &tmp8); 1738*a2f3d83cSJiri Slaby (SUSE) SETREG(SISAR, i); 1739*a2f3d83cSJiri Slaby (SUSE) SETREG(SISAR, attrdata[i]); 1740*a2f3d83cSJiri Slaby (SUSE) } 1741*a2f3d83cSJiri Slaby (SUSE) GETREG(SISINPSTAT, &tmp8); 1742*a2f3d83cSJiri Slaby (SUSE) SETREG(SISAR, 0x14); 1743*a2f3d83cSJiri Slaby (SUSE) SETREG(SISAR, 0x00); 1744*a2f3d83cSJiri Slaby (SUSE) GETREG(SISINPSTAT, &tmp8); 1745*a2f3d83cSJiri Slaby (SUSE) SETREG(SISAR, 0x20); 1746*a2f3d83cSJiri Slaby (SUSE) GETREG(SISINPSTAT, &tmp8); 1747*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i <= 0x08; i++) { /* grc */ 1748*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISGR, i, grcdata[i]); 1749*a2f3d83cSJiri Slaby (SUSE) } 1750*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISGR, 0x05, 0xbf); 1751*a2f3d83cSJiri Slaby (SUSE) for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */ 1752*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, i, 0x00); 1753*a2f3d83cSJiri Slaby (SUSE) } 1754*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x37, 0xfe); 1755*a2f3d83cSJiri Slaby (SUSE) SETREG(SISMISCW, 0xef); /* sync */ 1756*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x11, 0x00); /* crtc */ 1757*a2f3d83cSJiri Slaby (SUSE) for (j = 0x00, i = 0; i <= 7; i++, j++) 1758*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, j, crtcdata[i]); 1759*a2f3d83cSJiri Slaby (SUSE) 1760*a2f3d83cSJiri Slaby (SUSE) for (j = 0x10; i <= 10; i++, j++) 1761*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, j, crtcdata[i]); 1762*a2f3d83cSJiri Slaby (SUSE) 1763*a2f3d83cSJiri Slaby (SUSE) for (j = 0x15; i <= 12; i++, j++) 1764*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, j, crtcdata[i]); 1765*a2f3d83cSJiri Slaby (SUSE) 1766*a2f3d83cSJiri Slaby (SUSE) for (j = 0x0A; i <= 15; i++, j++) 1767*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, j, crtcdata[i]); 1768*a2f3d83cSJiri Slaby (SUSE) 1769*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0)); 1770*a2f3d83cSJiri Slaby (SUSE) SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5)); 1771*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x14, 0x4f); 1772*a2f3d83cSJiri Slaby (SUSE) du = (modex / 16) * (bpp * 2); /* offset/pitch */ 1773*a2f3d83cSJiri Slaby (SUSE) SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f)); 1774*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x13, (du & 0xff)); 1775*a2f3d83cSJiri Slaby (SUSE) du <<= 5; 1776*a2f3d83cSJiri Slaby (SUSE) tmp8 = du >> 8; 1777*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x10, tmp8); 1778*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x31, 0x00); /* VCLK */ 1779*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x2b, 0x1b); 1780*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x2c, 0xe1); 1781*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x2d, 0x01); 1782*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */ 1783*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x08, 0xae); 1784*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x09, 0xf0); 1785*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x08, 0x34); 1786*a2f3d83cSJiri Slaby (SUSE) SETIREGOR(SISSR, 0x3d, 0x01); 1787*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */ 1788*a2f3d83cSJiri Slaby (SUSE) SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a); 1789*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x19, 0x00); 1790*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISCR, 0x1a, 0xfc); 1791*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x0f, 0xb7); 1792*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x31, 0xfb); 1793*a2f3d83cSJiri Slaby (SUSE) SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0); 1794*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x32, 0xf3); 1795*a2f3d83cSJiri Slaby (SUSE) SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03); 1796*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x52, 0x6c); 1797*a2f3d83cSJiri Slaby (SUSE) 1798*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */ 1799*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x0c, 0x00); 1800*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x0d, 0x00); 1801*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x37, 0xfe); 1802*a2f3d83cSJiri Slaby (SUSE) 1803*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x32, 0x20); 1804*a2f3d83cSJiri Slaby (SUSE) SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */ 1805*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x63, (cr63 & 0xbf)); 1806*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x31, (sr31 & 0xfb)); 1807*a2f3d83cSJiri Slaby (SUSE) 1808*a2f3d83cSJiri Slaby (SUSE) if (touchengines) { 1809*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x20, 0xa1); /* enable engines */ 1810*a2f3d83cSJiri Slaby (SUSE) SETIREGOR(SISSR, 0x1e, 0x5a); 1811*a2f3d83cSJiri Slaby (SUSE) 1812*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */ 1813*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x27, 0x1f); 1814*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISSR, 0x26, 0x00); 1815*a2f3d83cSJiri Slaby (SUSE) } 1816*a2f3d83cSJiri Slaby (SUSE) 1817*a2f3d83cSJiri Slaby (SUSE) SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */ 1818*a2f3d83cSJiri Slaby (SUSE) } 1819*a2f3d83cSJiri Slaby (SUSE) 1820*a2f3d83cSJiri Slaby (SUSE) static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) 1821*a2f3d83cSJiri Slaby (SUSE) { 1822*a2f3d83cSJiri Slaby (SUSE) int ret = 0, i, j, bw, chab, iret, retry = 3; 1823*a2f3d83cSJiri Slaby (SUSE) u8 tmp8, ramtype; 1824*a2f3d83cSJiri Slaby (SUSE) u32 tmp32; 1825*a2f3d83cSJiri Slaby (SUSE) static const char mclktable[] = { 1826*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143, 1827*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143, 1828*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143, 1829*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143 1830*a2f3d83cSJiri Slaby (SUSE) }; 1831*a2f3d83cSJiri Slaby (SUSE) static const char eclktable[] = { 1832*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143, 1833*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143, 1834*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143, 1835*a2f3d83cSJiri Slaby (SUSE) 0x3b, 0x22, 0x01, 143 1836*a2f3d83cSJiri Slaby (SUSE) }; 1837*a2f3d83cSJiri Slaby (SUSE) static const char ramtypetable1[] = { 1838*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x04, 0x60, 0x60, 1839*a2f3d83cSJiri Slaby (SUSE) 0x0f, 0x0f, 0x1f, 0x1f, 1840*a2f3d83cSJiri Slaby (SUSE) 0xba, 0xba, 0xba, 0xba, 1841*a2f3d83cSJiri Slaby (SUSE) 0xa9, 0xa9, 0xac, 0xac, 1842*a2f3d83cSJiri Slaby (SUSE) 0xa0, 0xa0, 0xa0, 0xa8, 1843*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x00, 0x02, 0x02, 1844*a2f3d83cSJiri Slaby (SUSE) 0x30, 0x30, 0x40, 0x40 1845*a2f3d83cSJiri Slaby (SUSE) }; 1846*a2f3d83cSJiri Slaby (SUSE) static const char ramtypetable2[] = { 1847*a2f3d83cSJiri Slaby (SUSE) 0x77, 0x77, 0x44, 0x44, 1848*a2f3d83cSJiri Slaby (SUSE) 0x77, 0x77, 0x44, 0x44, 1849*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x00, 0x00, 0x00, 1850*a2f3d83cSJiri Slaby (SUSE) 0x5b, 0x5b, 0xab, 0xab, 1851*a2f3d83cSJiri Slaby (SUSE) 0x00, 0x00, 0xf0, 0xf8 1852*a2f3d83cSJiri Slaby (SUSE) }; 1853*a2f3d83cSJiri Slaby (SUSE) 1854*a2f3d83cSJiri Slaby (SUSE) while (retry--) { 1855*a2f3d83cSJiri Slaby (SUSE) 1856*a2f3d83cSJiri Slaby (SUSE) /* Enable VGA */ 1857*a2f3d83cSJiri Slaby (SUSE) ret = GETREG(SISVGAEN, &tmp8); 1858*a2f3d83cSJiri Slaby (SUSE) ret |= SETREG(SISVGAEN, (tmp8 | 0x01)); 1859*a2f3d83cSJiri Slaby (SUSE) 1860*a2f3d83cSJiri Slaby (SUSE) /* Enable GPU access to VRAM */ 1861*a2f3d83cSJiri Slaby (SUSE) ret |= GETREG(SISMISCR, &tmp8); 1862*a2f3d83cSJiri Slaby (SUSE) ret |= SETREG(SISMISCW, (tmp8 | 0x01)); 1863*a2f3d83cSJiri Slaby (SUSE) 1864*a2f3d83cSJiri Slaby (SUSE) if (ret) 1865*a2f3d83cSJiri Slaby (SUSE) continue; 1866*a2f3d83cSJiri Slaby (SUSE) 1867*a2f3d83cSJiri Slaby (SUSE) /* Reset registers */ 1868*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISCR, 0x5b, 0xdf); 1869*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x05, 0x86); 1870*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x20, 0x01); 1871*a2f3d83cSJiri Slaby (SUSE) 1872*a2f3d83cSJiri Slaby (SUSE) ret |= SETREG(SISMISCW, 0x67); 1873*a2f3d83cSJiri Slaby (SUSE) 1874*a2f3d83cSJiri Slaby (SUSE) for (i = 0x06; i <= 0x1f; i++) 1875*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, i, 0x00); 1876*a2f3d83cSJiri Slaby (SUSE) 1877*a2f3d83cSJiri Slaby (SUSE) for (i = 0x21; i <= 0x27; i++) 1878*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, i, 0x00); 1879*a2f3d83cSJiri Slaby (SUSE) 1880*a2f3d83cSJiri Slaby (SUSE) for (i = 0x31; i <= 0x3d; i++) 1881*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, i, 0x00); 1882*a2f3d83cSJiri Slaby (SUSE) 1883*a2f3d83cSJiri Slaby (SUSE) for (i = 0x12; i <= 0x1b; i++) 1884*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, i, 0x00); 1885*a2f3d83cSJiri Slaby (SUSE) 1886*a2f3d83cSJiri Slaby (SUSE) for (i = 0x79; i <= 0x7c; i++) 1887*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISCR, i, 0x00); 1888*a2f3d83cSJiri Slaby (SUSE) 1889*a2f3d83cSJiri Slaby (SUSE) if (ret) 1890*a2f3d83cSJiri Slaby (SUSE) continue; 1891*a2f3d83cSJiri Slaby (SUSE) 1892*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISCR, 0x63, 0x80); 1893*a2f3d83cSJiri Slaby (SUSE) 1894*a2f3d83cSJiri Slaby (SUSE) ret |= GETIREG(SISSR, 0x3a, &ramtype); 1895*a2f3d83cSJiri Slaby (SUSE) ramtype &= 0x03; 1896*a2f3d83cSJiri Slaby (SUSE) 1897*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]); 1898*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]); 1899*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]); 1900*a2f3d83cSJiri Slaby (SUSE) 1901*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]); 1902*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]); 1903*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]); 1904*a2f3d83cSJiri Slaby (SUSE) 1905*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x07, 0x18); 1906*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x11, 0x0f); 1907*a2f3d83cSJiri Slaby (SUSE) 1908*a2f3d83cSJiri Slaby (SUSE) if (ret) 1909*a2f3d83cSJiri Slaby (SUSE) continue; 1910*a2f3d83cSJiri Slaby (SUSE) 1911*a2f3d83cSJiri Slaby (SUSE) for (i = 0x15, j = 0; i <= 0x1b; i++, j++) { 1912*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, i, 1913*a2f3d83cSJiri Slaby (SUSE) ramtypetable1[(j*4) + ramtype]); 1914*a2f3d83cSJiri Slaby (SUSE) } 1915*a2f3d83cSJiri Slaby (SUSE) for (i = 0x40, j = 0; i <= 0x44; i++, j++) { 1916*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISCR, i, 1917*a2f3d83cSJiri Slaby (SUSE) ramtypetable2[(j*4) + ramtype]); 1918*a2f3d83cSJiri Slaby (SUSE) } 1919*a2f3d83cSJiri Slaby (SUSE) 1920*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISCR, 0x49, 0xaa); 1921*a2f3d83cSJiri Slaby (SUSE) 1922*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x1f, 0x00); 1923*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x20, 0xa0); 1924*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x23, 0xf6); 1925*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x24, 0x0d); 1926*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x25, 0x33); 1927*a2f3d83cSJiri Slaby (SUSE) 1928*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x11, 0x0f); 1929*a2f3d83cSJiri Slaby (SUSE) 1930*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISPART1, 0x2f, 0x01); 1931*a2f3d83cSJiri Slaby (SUSE) 1932*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISCAP, 0x3f, 0xef); 1933*a2f3d83cSJiri Slaby (SUSE) 1934*a2f3d83cSJiri Slaby (SUSE) if (ret) 1935*a2f3d83cSJiri Slaby (SUSE) continue; 1936*a2f3d83cSJiri Slaby (SUSE) 1937*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISPART1, 0x00, 0x00); 1938*a2f3d83cSJiri Slaby (SUSE) 1939*a2f3d83cSJiri Slaby (SUSE) ret |= GETIREG(SISSR, 0x13, &tmp8); 1940*a2f3d83cSJiri Slaby (SUSE) tmp8 >>= 4; 1941*a2f3d83cSJiri Slaby (SUSE) 1942*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISPART1, 0x02, 0x00); 1943*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISPART1, 0x2e, 0x08); 1944*a2f3d83cSJiri Slaby (SUSE) 1945*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32); 1946*a2f3d83cSJiri Slaby (SUSE) tmp32 &= 0x00f00000; 1947*a2f3d83cSJiri Slaby (SUSE) tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03; 1948*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x25, tmp8); 1949*a2f3d83cSJiri Slaby (SUSE) tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88; 1950*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISCR, 0x49, tmp8); 1951*a2f3d83cSJiri Slaby (SUSE) 1952*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x27, 0x1f); 1953*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x31, 0x00); 1954*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x32, 0x11); 1955*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x33, 0x00); 1956*a2f3d83cSJiri Slaby (SUSE) 1957*a2f3d83cSJiri Slaby (SUSE) if (ret) 1958*a2f3d83cSJiri Slaby (SUSE) continue; 1959*a2f3d83cSJiri Slaby (SUSE) 1960*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISCR, 0x83, 0x00); 1961*a2f3d83cSJiri Slaby (SUSE) 1962*a2f3d83cSJiri Slaby (SUSE) sisusb_set_default_mode(sisusb, 0); 1963*a2f3d83cSJiri Slaby (SUSE) 1964*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISSR, 0x21, 0xdf); 1965*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x01, 0x20); 1966*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x16, 0x0f); 1967*a2f3d83cSJiri Slaby (SUSE) 1968*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_triggersr16(sisusb, ramtype); 1969*a2f3d83cSJiri Slaby (SUSE) 1970*a2f3d83cSJiri Slaby (SUSE) /* Disable refresh */ 1971*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGAND(SISSR, 0x17, 0xf8); 1972*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x19, 0x03); 1973*a2f3d83cSJiri Slaby (SUSE) 1974*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_getbuswidth(sisusb, &bw, &chab); 1975*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_verify_mclk(sisusb); 1976*a2f3d83cSJiri Slaby (SUSE) 1977*a2f3d83cSJiri Slaby (SUSE) if (ramtype <= 1) { 1978*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); 1979*a2f3d83cSJiri Slaby (SUSE) if (iret) { 1980*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 1981*a2f3d83cSJiri Slaby (SUSE) "RAM size detection failed, assuming 8MB video RAM\n"); 1982*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x31); 1983*a2f3d83cSJiri Slaby (SUSE) /* TODO */ 1984*a2f3d83cSJiri Slaby (SUSE) } 1985*a2f3d83cSJiri Slaby (SUSE) } else { 1986*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 1987*a2f3d83cSJiri Slaby (SUSE) "DDR RAM device found, assuming 8MB video RAM\n"); 1988*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x14, 0x31); 1989*a2f3d83cSJiri Slaby (SUSE) /* *** TODO *** */ 1990*a2f3d83cSJiri Slaby (SUSE) } 1991*a2f3d83cSJiri Slaby (SUSE) 1992*a2f3d83cSJiri Slaby (SUSE) /* Enable refresh */ 1993*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]); 1994*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]); 1995*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]); 1996*a2f3d83cSJiri Slaby (SUSE) 1997*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREGOR(SISSR, 0x21, 0x20); 1998*a2f3d83cSJiri Slaby (SUSE) 1999*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x22, 0xfb); 2000*a2f3d83cSJiri Slaby (SUSE) ret |= SETIREG(SISSR, 0x21, 0xa5); 2001*a2f3d83cSJiri Slaby (SUSE) 2002*a2f3d83cSJiri Slaby (SUSE) if (ret == 0) 2003*a2f3d83cSJiri Slaby (SUSE) break; 2004*a2f3d83cSJiri Slaby (SUSE) } 2005*a2f3d83cSJiri Slaby (SUSE) 2006*a2f3d83cSJiri Slaby (SUSE) return ret; 2007*a2f3d83cSJiri Slaby (SUSE) } 2008*a2f3d83cSJiri Slaby (SUSE) 2009*a2f3d83cSJiri Slaby (SUSE) #undef SETREG 2010*a2f3d83cSJiri Slaby (SUSE) #undef GETREG 2011*a2f3d83cSJiri Slaby (SUSE) #undef SETIREG 2012*a2f3d83cSJiri Slaby (SUSE) #undef GETIREG 2013*a2f3d83cSJiri Slaby (SUSE) #undef SETIREGOR 2014*a2f3d83cSJiri Slaby (SUSE) #undef SETIREGAND 2015*a2f3d83cSJiri Slaby (SUSE) #undef SETIREGANDOR 2016*a2f3d83cSJiri Slaby (SUSE) #undef READL 2017*a2f3d83cSJiri Slaby (SUSE) #undef WRITEL 2018*a2f3d83cSJiri Slaby (SUSE) 2019*a2f3d83cSJiri Slaby (SUSE) static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) 2020*a2f3d83cSJiri Slaby (SUSE) { 2021*a2f3d83cSJiri Slaby (SUSE) u8 tmp8, tmp82, ramtype; 2022*a2f3d83cSJiri Slaby (SUSE) int bw = 0; 2023*a2f3d83cSJiri Slaby (SUSE) char *ramtypetext1 = NULL; 2024*a2f3d83cSJiri Slaby (SUSE) static const char ram_datarate[4] = {'S', 'S', 'D', 'D'}; 2025*a2f3d83cSJiri Slaby (SUSE) static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'}; 2026*a2f3d83cSJiri Slaby (SUSE) static const int busSDR[4] = {64, 64, 128, 128}; 2027*a2f3d83cSJiri Slaby (SUSE) static const int busDDR[4] = {32, 32, 64, 64}; 2028*a2f3d83cSJiri Slaby (SUSE) static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2}; 2029*a2f3d83cSJiri Slaby (SUSE) 2030*a2f3d83cSJiri Slaby (SUSE) sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8); 2031*a2f3d83cSJiri Slaby (SUSE) sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82); 2032*a2f3d83cSJiri Slaby (SUSE) sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype); 2033*a2f3d83cSJiri Slaby (SUSE) sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024; 2034*a2f3d83cSJiri Slaby (SUSE) ramtype &= 0x03; 2035*a2f3d83cSJiri Slaby (SUSE) switch ((tmp8 >> 2) & 0x03) { 2036*a2f3d83cSJiri Slaby (SUSE) case 0: 2037*a2f3d83cSJiri Slaby (SUSE) ramtypetext1 = "1 ch/1 r"; 2038*a2f3d83cSJiri Slaby (SUSE) if (tmp82 & 0x10) 2039*a2f3d83cSJiri Slaby (SUSE) bw = 32; 2040*a2f3d83cSJiri Slaby (SUSE) else 2041*a2f3d83cSJiri Slaby (SUSE) bw = busSDR[(tmp8 & 0x03)]; 2042*a2f3d83cSJiri Slaby (SUSE) 2043*a2f3d83cSJiri Slaby (SUSE) break; 2044*a2f3d83cSJiri Slaby (SUSE) case 1: 2045*a2f3d83cSJiri Slaby (SUSE) ramtypetext1 = "1 ch/2 r"; 2046*a2f3d83cSJiri Slaby (SUSE) sisusb->vramsize <<= 1; 2047*a2f3d83cSJiri Slaby (SUSE) bw = busSDR[(tmp8 & 0x03)]; 2048*a2f3d83cSJiri Slaby (SUSE) break; 2049*a2f3d83cSJiri Slaby (SUSE) case 2: 2050*a2f3d83cSJiri Slaby (SUSE) ramtypetext1 = "asymmetric"; 2051*a2f3d83cSJiri Slaby (SUSE) sisusb->vramsize += sisusb->vramsize/2; 2052*a2f3d83cSJiri Slaby (SUSE) bw = busDDRA[(tmp8 & 0x03)]; 2053*a2f3d83cSJiri Slaby (SUSE) break; 2054*a2f3d83cSJiri Slaby (SUSE) case 3: 2055*a2f3d83cSJiri Slaby (SUSE) ramtypetext1 = "2 channel"; 2056*a2f3d83cSJiri Slaby (SUSE) sisusb->vramsize <<= 1; 2057*a2f3d83cSJiri Slaby (SUSE) bw = busDDR[(tmp8 & 0x03)]; 2058*a2f3d83cSJiri Slaby (SUSE) break; 2059*a2f3d83cSJiri Slaby (SUSE) } 2060*a2f3d83cSJiri Slaby (SUSE) 2061*a2f3d83cSJiri Slaby (SUSE) dev_info(&sisusb->sisusb_dev->dev, 2062*a2f3d83cSJiri Slaby (SUSE) "%dMB %s %cDR S%cRAM, bus width %d\n", 2063*a2f3d83cSJiri Slaby (SUSE) sisusb->vramsize >> 20, ramtypetext1, 2064*a2f3d83cSJiri Slaby (SUSE) ram_datarate[ramtype], ram_dynamictype[ramtype], bw); 2065*a2f3d83cSJiri Slaby (SUSE) } 2066*a2f3d83cSJiri Slaby (SUSE) 2067*a2f3d83cSJiri Slaby (SUSE) static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) 2068*a2f3d83cSJiri Slaby (SUSE) { 2069*a2f3d83cSJiri Slaby (SUSE) struct sisusb_packet packet; 2070*a2f3d83cSJiri Slaby (SUSE) int ret; 2071*a2f3d83cSJiri Slaby (SUSE) u32 tmp32; 2072*a2f3d83cSJiri Slaby (SUSE) 2073*a2f3d83cSJiri Slaby (SUSE) /* Do some magic */ 2074*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 2075*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000324; 2076*a2f3d83cSJiri Slaby (SUSE) packet.data = 0x00000004; 2077*a2f3d83cSJiri Slaby (SUSE) ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2078*a2f3d83cSJiri Slaby (SUSE) 2079*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 2080*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000364; 2081*a2f3d83cSJiri Slaby (SUSE) packet.data = 0x00000004; 2082*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2083*a2f3d83cSJiri Slaby (SUSE) 2084*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 2085*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000384; 2086*a2f3d83cSJiri Slaby (SUSE) packet.data = 0x00000004; 2087*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2088*a2f3d83cSJiri Slaby (SUSE) 2089*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 2090*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000100; 2091*a2f3d83cSJiri Slaby (SUSE) packet.data = 0x00000700; 2092*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2093*a2f3d83cSJiri Slaby (SUSE) 2094*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x000f; 2095*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000004; 2096*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0); 2097*a2f3d83cSJiri Slaby (SUSE) packet.data |= 0x17; 2098*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2099*a2f3d83cSJiri Slaby (SUSE) 2100*a2f3d83cSJiri Slaby (SUSE) /* Init BAR 0 (VRAM) */ 2101*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); 2102*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0); 2103*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); 2104*a2f3d83cSJiri Slaby (SUSE) tmp32 &= 0x0f; 2105*a2f3d83cSJiri Slaby (SUSE) tmp32 |= SISUSB_PCI_MEMBASE; 2106*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32); 2107*a2f3d83cSJiri Slaby (SUSE) 2108*a2f3d83cSJiri Slaby (SUSE) /* Init BAR 1 (MMIO) */ 2109*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); 2110*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0); 2111*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); 2112*a2f3d83cSJiri Slaby (SUSE) tmp32 &= 0x0f; 2113*a2f3d83cSJiri Slaby (SUSE) tmp32 |= SISUSB_PCI_MMIOBASE; 2114*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32); 2115*a2f3d83cSJiri Slaby (SUSE) 2116*a2f3d83cSJiri Slaby (SUSE) /* Init BAR 2 (i/o ports) */ 2117*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); 2118*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0); 2119*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); 2120*a2f3d83cSJiri Slaby (SUSE) tmp32 &= 0x0f; 2121*a2f3d83cSJiri Slaby (SUSE) tmp32 |= SISUSB_PCI_IOPORTBASE; 2122*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32); 2123*a2f3d83cSJiri Slaby (SUSE) 2124*a2f3d83cSJiri Slaby (SUSE) /* Enable memory and i/o access */ 2125*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32); 2126*a2f3d83cSJiri Slaby (SUSE) tmp32 |= 0x3; 2127*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32); 2128*a2f3d83cSJiri Slaby (SUSE) 2129*a2f3d83cSJiri Slaby (SUSE) if (ret == 0) { 2130*a2f3d83cSJiri Slaby (SUSE) /* Some further magic */ 2131*a2f3d83cSJiri Slaby (SUSE) packet.header = 0x001f; 2132*a2f3d83cSJiri Slaby (SUSE) packet.address = 0x00000050; 2133*a2f3d83cSJiri Slaby (SUSE) packet.data = 0x000000ff; 2134*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); 2135*a2f3d83cSJiri Slaby (SUSE) } 2136*a2f3d83cSJiri Slaby (SUSE) 2137*a2f3d83cSJiri Slaby (SUSE) return ret; 2138*a2f3d83cSJiri Slaby (SUSE) } 2139*a2f3d83cSJiri Slaby (SUSE) 2140*a2f3d83cSJiri Slaby (SUSE) /* Initialize the graphics device (return 0 on success) 2141*a2f3d83cSJiri Slaby (SUSE) * This initializes the net2280 as well as the PCI registers 2142*a2f3d83cSJiri Slaby (SUSE) * of the graphics board. 2143*a2f3d83cSJiri Slaby (SUSE) */ 2144*a2f3d83cSJiri Slaby (SUSE) 2145*a2f3d83cSJiri Slaby (SUSE) static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) 2146*a2f3d83cSJiri Slaby (SUSE) { 2147*a2f3d83cSJiri Slaby (SUSE) int ret = 0, test = 0; 2148*a2f3d83cSJiri Slaby (SUSE) u32 tmp32; 2149*a2f3d83cSJiri Slaby (SUSE) 2150*a2f3d83cSJiri Slaby (SUSE) if (sisusb->devinit == 1) { 2151*a2f3d83cSJiri Slaby (SUSE) /* Read PCI BARs and see if they have been set up */ 2152*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); 2153*a2f3d83cSJiri Slaby (SUSE) if (ret) 2154*a2f3d83cSJiri Slaby (SUSE) return ret; 2155*a2f3d83cSJiri Slaby (SUSE) 2156*a2f3d83cSJiri Slaby (SUSE) if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) 2157*a2f3d83cSJiri Slaby (SUSE) test++; 2158*a2f3d83cSJiri Slaby (SUSE) 2159*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); 2160*a2f3d83cSJiri Slaby (SUSE) if (ret) 2161*a2f3d83cSJiri Slaby (SUSE) return ret; 2162*a2f3d83cSJiri Slaby (SUSE) 2163*a2f3d83cSJiri Slaby (SUSE) if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) 2164*a2f3d83cSJiri Slaby (SUSE) test++; 2165*a2f3d83cSJiri Slaby (SUSE) 2166*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); 2167*a2f3d83cSJiri Slaby (SUSE) if (ret) 2168*a2f3d83cSJiri Slaby (SUSE) return ret; 2169*a2f3d83cSJiri Slaby (SUSE) 2170*a2f3d83cSJiri Slaby (SUSE) if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) 2171*a2f3d83cSJiri Slaby (SUSE) test++; 2172*a2f3d83cSJiri Slaby (SUSE) } 2173*a2f3d83cSJiri Slaby (SUSE) 2174*a2f3d83cSJiri Slaby (SUSE) /* No? So reset the device */ 2175*a2f3d83cSJiri Slaby (SUSE) if ((sisusb->devinit == 0) || (test != 3)) { 2176*a2f3d83cSJiri Slaby (SUSE) 2177*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_do_init_gfxdevice(sisusb); 2178*a2f3d83cSJiri Slaby (SUSE) 2179*a2f3d83cSJiri Slaby (SUSE) if (ret == 0) 2180*a2f3d83cSJiri Slaby (SUSE) sisusb->devinit = 1; 2181*a2f3d83cSJiri Slaby (SUSE) 2182*a2f3d83cSJiri Slaby (SUSE) } 2183*a2f3d83cSJiri Slaby (SUSE) 2184*a2f3d83cSJiri Slaby (SUSE) if (sisusb->devinit) { 2185*a2f3d83cSJiri Slaby (SUSE) /* Initialize the graphics core */ 2186*a2f3d83cSJiri Slaby (SUSE) if (sisusb_init_gfxcore(sisusb) == 0) { 2187*a2f3d83cSJiri Slaby (SUSE) sisusb->gfxinit = 1; 2188*a2f3d83cSJiri Slaby (SUSE) sisusb_get_ramconfig(sisusb); 2189*a2f3d83cSJiri Slaby (SUSE) sisusb_set_default_mode(sisusb, 1); 2190*a2f3d83cSJiri Slaby (SUSE) ret |= sisusb_setup_screen(sisusb, 1, initscreen); 2191*a2f3d83cSJiri Slaby (SUSE) } 2192*a2f3d83cSJiri Slaby (SUSE) } 2193*a2f3d83cSJiri Slaby (SUSE) 2194*a2f3d83cSJiri Slaby (SUSE) return ret; 2195*a2f3d83cSJiri Slaby (SUSE) } 2196*a2f3d83cSJiri Slaby (SUSE) 2197*a2f3d83cSJiri Slaby (SUSE) /* fops */ 2198*a2f3d83cSJiri Slaby (SUSE) 2199*a2f3d83cSJiri Slaby (SUSE) static int sisusb_open(struct inode *inode, struct file *file) 2200*a2f3d83cSJiri Slaby (SUSE) { 2201*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2202*a2f3d83cSJiri Slaby (SUSE) struct usb_interface *interface; 2203*a2f3d83cSJiri Slaby (SUSE) int subminor = iminor(inode); 2204*a2f3d83cSJiri Slaby (SUSE) 2205*a2f3d83cSJiri Slaby (SUSE) interface = usb_find_interface(&sisusb_driver, subminor); 2206*a2f3d83cSJiri Slaby (SUSE) if (!interface) 2207*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2208*a2f3d83cSJiri Slaby (SUSE) 2209*a2f3d83cSJiri Slaby (SUSE) sisusb = usb_get_intfdata(interface); 2210*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2211*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2212*a2f3d83cSJiri Slaby (SUSE) 2213*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2214*a2f3d83cSJiri Slaby (SUSE) 2215*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->present || !sisusb->ready) { 2216*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2217*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2218*a2f3d83cSJiri Slaby (SUSE) } 2219*a2f3d83cSJiri Slaby (SUSE) 2220*a2f3d83cSJiri Slaby (SUSE) if (sisusb->isopen) { 2221*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2222*a2f3d83cSJiri Slaby (SUSE) return -EBUSY; 2223*a2f3d83cSJiri Slaby (SUSE) } 2224*a2f3d83cSJiri Slaby (SUSE) 2225*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->devinit) { 2226*a2f3d83cSJiri Slaby (SUSE) if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || 2227*a2f3d83cSJiri Slaby (SUSE) sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) { 2228*a2f3d83cSJiri Slaby (SUSE) if (sisusb_init_gfxdevice(sisusb, 0)) { 2229*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2230*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 2231*a2f3d83cSJiri Slaby (SUSE) "Failed to initialize device\n"); 2232*a2f3d83cSJiri Slaby (SUSE) return -EIO; 2233*a2f3d83cSJiri Slaby (SUSE) } 2234*a2f3d83cSJiri Slaby (SUSE) } else { 2235*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2236*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 2237*a2f3d83cSJiri Slaby (SUSE) "Device not attached to USB 2.0 hub\n"); 2238*a2f3d83cSJiri Slaby (SUSE) return -EIO; 2239*a2f3d83cSJiri Slaby (SUSE) } 2240*a2f3d83cSJiri Slaby (SUSE) } 2241*a2f3d83cSJiri Slaby (SUSE) 2242*a2f3d83cSJiri Slaby (SUSE) /* Increment usage count for our sisusb */ 2243*a2f3d83cSJiri Slaby (SUSE) kref_get(&sisusb->kref); 2244*a2f3d83cSJiri Slaby (SUSE) 2245*a2f3d83cSJiri Slaby (SUSE) sisusb->isopen = 1; 2246*a2f3d83cSJiri Slaby (SUSE) 2247*a2f3d83cSJiri Slaby (SUSE) file->private_data = sisusb; 2248*a2f3d83cSJiri Slaby (SUSE) 2249*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2250*a2f3d83cSJiri Slaby (SUSE) 2251*a2f3d83cSJiri Slaby (SUSE) return 0; 2252*a2f3d83cSJiri Slaby (SUSE) } 2253*a2f3d83cSJiri Slaby (SUSE) 2254*a2f3d83cSJiri Slaby (SUSE) static void sisusb_delete(struct kref *kref) 2255*a2f3d83cSJiri Slaby (SUSE) { 2256*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); 2257*a2f3d83cSJiri Slaby (SUSE) 2258*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2259*a2f3d83cSJiri Slaby (SUSE) return; 2260*a2f3d83cSJiri Slaby (SUSE) 2261*a2f3d83cSJiri Slaby (SUSE) usb_put_dev(sisusb->sisusb_dev); 2262*a2f3d83cSJiri Slaby (SUSE) 2263*a2f3d83cSJiri Slaby (SUSE) sisusb->sisusb_dev = NULL; 2264*a2f3d83cSJiri Slaby (SUSE) sisusb_free_buffers(sisusb); 2265*a2f3d83cSJiri Slaby (SUSE) sisusb_free_urbs(sisusb); 2266*a2f3d83cSJiri Slaby (SUSE) kfree(sisusb); 2267*a2f3d83cSJiri Slaby (SUSE) } 2268*a2f3d83cSJiri Slaby (SUSE) 2269*a2f3d83cSJiri Slaby (SUSE) static int sisusb_release(struct inode *inode, struct file *file) 2270*a2f3d83cSJiri Slaby (SUSE) { 2271*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2272*a2f3d83cSJiri Slaby (SUSE) 2273*a2f3d83cSJiri Slaby (SUSE) sisusb = file->private_data; 2274*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2275*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2276*a2f3d83cSJiri Slaby (SUSE) 2277*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2278*a2f3d83cSJiri Slaby (SUSE) 2279*a2f3d83cSJiri Slaby (SUSE) if (sisusb->present) { 2280*a2f3d83cSJiri Slaby (SUSE) /* Wait for all URBs to finish if device still present */ 2281*a2f3d83cSJiri Slaby (SUSE) if (!sisusb_wait_all_out_complete(sisusb)) 2282*a2f3d83cSJiri Slaby (SUSE) sisusb_kill_all_busy(sisusb); 2283*a2f3d83cSJiri Slaby (SUSE) } 2284*a2f3d83cSJiri Slaby (SUSE) 2285*a2f3d83cSJiri Slaby (SUSE) sisusb->isopen = 0; 2286*a2f3d83cSJiri Slaby (SUSE) file->private_data = NULL; 2287*a2f3d83cSJiri Slaby (SUSE) 2288*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2289*a2f3d83cSJiri Slaby (SUSE) 2290*a2f3d83cSJiri Slaby (SUSE) /* decrement the usage count on our device */ 2291*a2f3d83cSJiri Slaby (SUSE) kref_put(&sisusb->kref, sisusb_delete); 2292*a2f3d83cSJiri Slaby (SUSE) 2293*a2f3d83cSJiri Slaby (SUSE) return 0; 2294*a2f3d83cSJiri Slaby (SUSE) } 2295*a2f3d83cSJiri Slaby (SUSE) 2296*a2f3d83cSJiri Slaby (SUSE) static ssize_t sisusb_read(struct file *file, char __user *buffer, 2297*a2f3d83cSJiri Slaby (SUSE) size_t count, loff_t *ppos) 2298*a2f3d83cSJiri Slaby (SUSE) { 2299*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2300*a2f3d83cSJiri Slaby (SUSE) ssize_t bytes_read = 0; 2301*a2f3d83cSJiri Slaby (SUSE) int errno = 0; 2302*a2f3d83cSJiri Slaby (SUSE) u8 buf8; 2303*a2f3d83cSJiri Slaby (SUSE) u16 buf16; 2304*a2f3d83cSJiri Slaby (SUSE) u32 buf32, address; 2305*a2f3d83cSJiri Slaby (SUSE) 2306*a2f3d83cSJiri Slaby (SUSE) sisusb = file->private_data; 2307*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2308*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2309*a2f3d83cSJiri Slaby (SUSE) 2310*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2311*a2f3d83cSJiri Slaby (SUSE) 2312*a2f3d83cSJiri Slaby (SUSE) /* Sanity check */ 2313*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2314*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2315*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2316*a2f3d83cSJiri Slaby (SUSE) } 2317*a2f3d83cSJiri Slaby (SUSE) 2318*a2f3d83cSJiri Slaby (SUSE) if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && 2319*a2f3d83cSJiri Slaby (SUSE) (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { 2320*a2f3d83cSJiri Slaby (SUSE) 2321*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + 2322*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_IOPORTBASE; 2323*a2f3d83cSJiri Slaby (SUSE) 2324*a2f3d83cSJiri Slaby (SUSE) /* Read i/o ports 2325*a2f3d83cSJiri Slaby (SUSE) * Byte, word and long(32) can be read. As this 2326*a2f3d83cSJiri Slaby (SUSE) * emulates inX instructions, the data returned is 2327*a2f3d83cSJiri Slaby (SUSE) * in machine-endianness. 2328*a2f3d83cSJiri Slaby (SUSE) */ 2329*a2f3d83cSJiri Slaby (SUSE) switch (count) { 2330*a2f3d83cSJiri Slaby (SUSE) case 1: 2331*a2f3d83cSJiri Slaby (SUSE) if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, 2332*a2f3d83cSJiri Slaby (SUSE) address, &buf8)) 2333*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2334*a2f3d83cSJiri Slaby (SUSE) else if (put_user(buf8, (u8 __user *)buffer)) 2335*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2336*a2f3d83cSJiri Slaby (SUSE) else 2337*a2f3d83cSJiri Slaby (SUSE) bytes_read = 1; 2338*a2f3d83cSJiri Slaby (SUSE) 2339*a2f3d83cSJiri Slaby (SUSE) break; 2340*a2f3d83cSJiri Slaby (SUSE) 2341*a2f3d83cSJiri Slaby (SUSE) case 2: 2342*a2f3d83cSJiri Slaby (SUSE) if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO, 2343*a2f3d83cSJiri Slaby (SUSE) address, &buf16)) 2344*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2345*a2f3d83cSJiri Slaby (SUSE) else if (put_user(buf16, (u16 __user *)buffer)) 2346*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2347*a2f3d83cSJiri Slaby (SUSE) else 2348*a2f3d83cSJiri Slaby (SUSE) bytes_read = 2; 2349*a2f3d83cSJiri Slaby (SUSE) 2350*a2f3d83cSJiri Slaby (SUSE) break; 2351*a2f3d83cSJiri Slaby (SUSE) 2352*a2f3d83cSJiri Slaby (SUSE) case 4: 2353*a2f3d83cSJiri Slaby (SUSE) if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO, 2354*a2f3d83cSJiri Slaby (SUSE) address, &buf32)) 2355*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2356*a2f3d83cSJiri Slaby (SUSE) else if (put_user(buf32, (u32 __user *)buffer)) 2357*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2358*a2f3d83cSJiri Slaby (SUSE) else 2359*a2f3d83cSJiri Slaby (SUSE) bytes_read = 4; 2360*a2f3d83cSJiri Slaby (SUSE) 2361*a2f3d83cSJiri Slaby (SUSE) break; 2362*a2f3d83cSJiri Slaby (SUSE) 2363*a2f3d83cSJiri Slaby (SUSE) default: 2364*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2365*a2f3d83cSJiri Slaby (SUSE) 2366*a2f3d83cSJiri Slaby (SUSE) } 2367*a2f3d83cSJiri Slaby (SUSE) 2368*a2f3d83cSJiri Slaby (SUSE) } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) < 2369*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { 2370*a2f3d83cSJiri Slaby (SUSE) 2371*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + 2372*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MEMBASE; 2373*a2f3d83cSJiri Slaby (SUSE) 2374*a2f3d83cSJiri Slaby (SUSE) /* Read video ram 2375*a2f3d83cSJiri Slaby (SUSE) * Remember: Data delivered is never endian-corrected 2376*a2f3d83cSJiri Slaby (SUSE) */ 2377*a2f3d83cSJiri Slaby (SUSE) errno = sisusb_read_mem_bulk(sisusb, address, 2378*a2f3d83cSJiri Slaby (SUSE) NULL, count, buffer, &bytes_read); 2379*a2f3d83cSJiri Slaby (SUSE) 2380*a2f3d83cSJiri Slaby (SUSE) if (bytes_read) 2381*a2f3d83cSJiri Slaby (SUSE) errno = bytes_read; 2382*a2f3d83cSJiri Slaby (SUSE) 2383*a2f3d83cSJiri Slaby (SUSE) } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && 2384*a2f3d83cSJiri Slaby (SUSE) (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + 2385*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MMIOSIZE) { 2386*a2f3d83cSJiri Slaby (SUSE) 2387*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + 2388*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MMIOBASE; 2389*a2f3d83cSJiri Slaby (SUSE) 2390*a2f3d83cSJiri Slaby (SUSE) /* Read MMIO 2391*a2f3d83cSJiri Slaby (SUSE) * Remember: Data delivered is never endian-corrected 2392*a2f3d83cSJiri Slaby (SUSE) */ 2393*a2f3d83cSJiri Slaby (SUSE) errno = sisusb_read_mem_bulk(sisusb, address, 2394*a2f3d83cSJiri Slaby (SUSE) NULL, count, buffer, &bytes_read); 2395*a2f3d83cSJiri Slaby (SUSE) 2396*a2f3d83cSJiri Slaby (SUSE) if (bytes_read) 2397*a2f3d83cSJiri Slaby (SUSE) errno = bytes_read; 2398*a2f3d83cSJiri Slaby (SUSE) 2399*a2f3d83cSJiri Slaby (SUSE) } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && 2400*a2f3d83cSJiri Slaby (SUSE) (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { 2401*a2f3d83cSJiri Slaby (SUSE) 2402*a2f3d83cSJiri Slaby (SUSE) if (count != 4) { 2403*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2404*a2f3d83cSJiri Slaby (SUSE) return -EINVAL; 2405*a2f3d83cSJiri Slaby (SUSE) } 2406*a2f3d83cSJiri Slaby (SUSE) 2407*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE; 2408*a2f3d83cSJiri Slaby (SUSE) 2409*a2f3d83cSJiri Slaby (SUSE) /* Read PCI config register 2410*a2f3d83cSJiri Slaby (SUSE) * Return value delivered in machine endianness. 2411*a2f3d83cSJiri Slaby (SUSE) */ 2412*a2f3d83cSJiri Slaby (SUSE) if (sisusb_read_pci_config(sisusb, address, &buf32)) 2413*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2414*a2f3d83cSJiri Slaby (SUSE) else if (put_user(buf32, (u32 __user *)buffer)) 2415*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2416*a2f3d83cSJiri Slaby (SUSE) else 2417*a2f3d83cSJiri Slaby (SUSE) bytes_read = 4; 2418*a2f3d83cSJiri Slaby (SUSE) 2419*a2f3d83cSJiri Slaby (SUSE) } else { 2420*a2f3d83cSJiri Slaby (SUSE) 2421*a2f3d83cSJiri Slaby (SUSE) errno = -EBADFD; 2422*a2f3d83cSJiri Slaby (SUSE) 2423*a2f3d83cSJiri Slaby (SUSE) } 2424*a2f3d83cSJiri Slaby (SUSE) 2425*a2f3d83cSJiri Slaby (SUSE) (*ppos) += bytes_read; 2426*a2f3d83cSJiri Slaby (SUSE) 2427*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2428*a2f3d83cSJiri Slaby (SUSE) 2429*a2f3d83cSJiri Slaby (SUSE) return errno ? errno : bytes_read; 2430*a2f3d83cSJiri Slaby (SUSE) } 2431*a2f3d83cSJiri Slaby (SUSE) 2432*a2f3d83cSJiri Slaby (SUSE) static ssize_t sisusb_write(struct file *file, const char __user *buffer, 2433*a2f3d83cSJiri Slaby (SUSE) size_t count, loff_t *ppos) 2434*a2f3d83cSJiri Slaby (SUSE) { 2435*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2436*a2f3d83cSJiri Slaby (SUSE) int errno = 0; 2437*a2f3d83cSJiri Slaby (SUSE) ssize_t bytes_written = 0; 2438*a2f3d83cSJiri Slaby (SUSE) u8 buf8; 2439*a2f3d83cSJiri Slaby (SUSE) u16 buf16; 2440*a2f3d83cSJiri Slaby (SUSE) u32 buf32, address; 2441*a2f3d83cSJiri Slaby (SUSE) 2442*a2f3d83cSJiri Slaby (SUSE) sisusb = file->private_data; 2443*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2444*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2445*a2f3d83cSJiri Slaby (SUSE) 2446*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2447*a2f3d83cSJiri Slaby (SUSE) 2448*a2f3d83cSJiri Slaby (SUSE) /* Sanity check */ 2449*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2450*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2451*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2452*a2f3d83cSJiri Slaby (SUSE) } 2453*a2f3d83cSJiri Slaby (SUSE) 2454*a2f3d83cSJiri Slaby (SUSE) if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && 2455*a2f3d83cSJiri Slaby (SUSE) (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { 2456*a2f3d83cSJiri Slaby (SUSE) 2457*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + 2458*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_IOPORTBASE; 2459*a2f3d83cSJiri Slaby (SUSE) 2460*a2f3d83cSJiri Slaby (SUSE) /* Write i/o ports 2461*a2f3d83cSJiri Slaby (SUSE) * Byte, word and long(32) can be written. As this 2462*a2f3d83cSJiri Slaby (SUSE) * emulates outX instructions, the data is expected 2463*a2f3d83cSJiri Slaby (SUSE) * in machine-endianness. 2464*a2f3d83cSJiri Slaby (SUSE) */ 2465*a2f3d83cSJiri Slaby (SUSE) switch (count) { 2466*a2f3d83cSJiri Slaby (SUSE) case 1: 2467*a2f3d83cSJiri Slaby (SUSE) if (get_user(buf8, (u8 __user *)buffer)) 2468*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2469*a2f3d83cSJiri Slaby (SUSE) else if (sisusb_write_memio_byte(sisusb, 2470*a2f3d83cSJiri Slaby (SUSE) SISUSB_TYPE_IO, address, buf8)) 2471*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2472*a2f3d83cSJiri Slaby (SUSE) else 2473*a2f3d83cSJiri Slaby (SUSE) bytes_written = 1; 2474*a2f3d83cSJiri Slaby (SUSE) 2475*a2f3d83cSJiri Slaby (SUSE) break; 2476*a2f3d83cSJiri Slaby (SUSE) 2477*a2f3d83cSJiri Slaby (SUSE) case 2: 2478*a2f3d83cSJiri Slaby (SUSE) if (get_user(buf16, (u16 __user *)buffer)) 2479*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2480*a2f3d83cSJiri Slaby (SUSE) else if (sisusb_write_memio_word(sisusb, 2481*a2f3d83cSJiri Slaby (SUSE) SISUSB_TYPE_IO, address, buf16)) 2482*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2483*a2f3d83cSJiri Slaby (SUSE) else 2484*a2f3d83cSJiri Slaby (SUSE) bytes_written = 2; 2485*a2f3d83cSJiri Slaby (SUSE) 2486*a2f3d83cSJiri Slaby (SUSE) break; 2487*a2f3d83cSJiri Slaby (SUSE) 2488*a2f3d83cSJiri Slaby (SUSE) case 4: 2489*a2f3d83cSJiri Slaby (SUSE) if (get_user(buf32, (u32 __user *)buffer)) 2490*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2491*a2f3d83cSJiri Slaby (SUSE) else if (sisusb_write_memio_long(sisusb, 2492*a2f3d83cSJiri Slaby (SUSE) SISUSB_TYPE_IO, address, buf32)) 2493*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2494*a2f3d83cSJiri Slaby (SUSE) else 2495*a2f3d83cSJiri Slaby (SUSE) bytes_written = 4; 2496*a2f3d83cSJiri Slaby (SUSE) 2497*a2f3d83cSJiri Slaby (SUSE) break; 2498*a2f3d83cSJiri Slaby (SUSE) 2499*a2f3d83cSJiri Slaby (SUSE) default: 2500*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2501*a2f3d83cSJiri Slaby (SUSE) } 2502*a2f3d83cSJiri Slaby (SUSE) 2503*a2f3d83cSJiri Slaby (SUSE) } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && 2504*a2f3d83cSJiri Slaby (SUSE) (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + 2505*a2f3d83cSJiri Slaby (SUSE) sisusb->vramsize) { 2506*a2f3d83cSJiri Slaby (SUSE) 2507*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + 2508*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MEMBASE; 2509*a2f3d83cSJiri Slaby (SUSE) 2510*a2f3d83cSJiri Slaby (SUSE) /* Write video ram. 2511*a2f3d83cSJiri Slaby (SUSE) * Buffer is copied 1:1, therefore, on big-endian 2512*a2f3d83cSJiri Slaby (SUSE) * machines, the data must be swapped by userland 2513*a2f3d83cSJiri Slaby (SUSE) * in advance (if applicable; no swapping in 8bpp 2514*a2f3d83cSJiri Slaby (SUSE) * mode or if YUV data is being transferred). 2515*a2f3d83cSJiri Slaby (SUSE) */ 2516*a2f3d83cSJiri Slaby (SUSE) errno = sisusb_write_mem_bulk(sisusb, address, NULL, 2517*a2f3d83cSJiri Slaby (SUSE) count, buffer, 0, &bytes_written); 2518*a2f3d83cSJiri Slaby (SUSE) 2519*a2f3d83cSJiri Slaby (SUSE) if (bytes_written) 2520*a2f3d83cSJiri Slaby (SUSE) errno = bytes_written; 2521*a2f3d83cSJiri Slaby (SUSE) 2522*a2f3d83cSJiri Slaby (SUSE) } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && 2523*a2f3d83cSJiri Slaby (SUSE) (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + 2524*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MMIOSIZE) { 2525*a2f3d83cSJiri Slaby (SUSE) 2526*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + 2527*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MMIOBASE; 2528*a2f3d83cSJiri Slaby (SUSE) 2529*a2f3d83cSJiri Slaby (SUSE) /* Write MMIO. 2530*a2f3d83cSJiri Slaby (SUSE) * Buffer is copied 1:1, therefore, on big-endian 2531*a2f3d83cSJiri Slaby (SUSE) * machines, the data must be swapped by userland 2532*a2f3d83cSJiri Slaby (SUSE) * in advance. 2533*a2f3d83cSJiri Slaby (SUSE) */ 2534*a2f3d83cSJiri Slaby (SUSE) errno = sisusb_write_mem_bulk(sisusb, address, NULL, 2535*a2f3d83cSJiri Slaby (SUSE) count, buffer, 0, &bytes_written); 2536*a2f3d83cSJiri Slaby (SUSE) 2537*a2f3d83cSJiri Slaby (SUSE) if (bytes_written) 2538*a2f3d83cSJiri Slaby (SUSE) errno = bytes_written; 2539*a2f3d83cSJiri Slaby (SUSE) 2540*a2f3d83cSJiri Slaby (SUSE) } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && 2541*a2f3d83cSJiri Slaby (SUSE) (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 2542*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_PCONFSIZE) { 2543*a2f3d83cSJiri Slaby (SUSE) 2544*a2f3d83cSJiri Slaby (SUSE) if (count != 4) { 2545*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2546*a2f3d83cSJiri Slaby (SUSE) return -EINVAL; 2547*a2f3d83cSJiri Slaby (SUSE) } 2548*a2f3d83cSJiri Slaby (SUSE) 2549*a2f3d83cSJiri Slaby (SUSE) address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE; 2550*a2f3d83cSJiri Slaby (SUSE) 2551*a2f3d83cSJiri Slaby (SUSE) /* Write PCI config register. 2552*a2f3d83cSJiri Slaby (SUSE) * Given value expected in machine endianness. 2553*a2f3d83cSJiri Slaby (SUSE) */ 2554*a2f3d83cSJiri Slaby (SUSE) if (get_user(buf32, (u32 __user *)buffer)) 2555*a2f3d83cSJiri Slaby (SUSE) errno = -EFAULT; 2556*a2f3d83cSJiri Slaby (SUSE) else if (sisusb_write_pci_config(sisusb, address, buf32)) 2557*a2f3d83cSJiri Slaby (SUSE) errno = -EIO; 2558*a2f3d83cSJiri Slaby (SUSE) else 2559*a2f3d83cSJiri Slaby (SUSE) bytes_written = 4; 2560*a2f3d83cSJiri Slaby (SUSE) 2561*a2f3d83cSJiri Slaby (SUSE) 2562*a2f3d83cSJiri Slaby (SUSE) } else { 2563*a2f3d83cSJiri Slaby (SUSE) 2564*a2f3d83cSJiri Slaby (SUSE) /* Error */ 2565*a2f3d83cSJiri Slaby (SUSE) errno = -EBADFD; 2566*a2f3d83cSJiri Slaby (SUSE) 2567*a2f3d83cSJiri Slaby (SUSE) } 2568*a2f3d83cSJiri Slaby (SUSE) 2569*a2f3d83cSJiri Slaby (SUSE) (*ppos) += bytes_written; 2570*a2f3d83cSJiri Slaby (SUSE) 2571*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2572*a2f3d83cSJiri Slaby (SUSE) 2573*a2f3d83cSJiri Slaby (SUSE) return errno ? errno : bytes_written; 2574*a2f3d83cSJiri Slaby (SUSE) } 2575*a2f3d83cSJiri Slaby (SUSE) 2576*a2f3d83cSJiri Slaby (SUSE) static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig) 2577*a2f3d83cSJiri Slaby (SUSE) { 2578*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2579*a2f3d83cSJiri Slaby (SUSE) loff_t ret; 2580*a2f3d83cSJiri Slaby (SUSE) 2581*a2f3d83cSJiri Slaby (SUSE) sisusb = file->private_data; 2582*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2583*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2584*a2f3d83cSJiri Slaby (SUSE) 2585*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2586*a2f3d83cSJiri Slaby (SUSE) 2587*a2f3d83cSJiri Slaby (SUSE) /* Sanity check */ 2588*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2589*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2590*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2591*a2f3d83cSJiri Slaby (SUSE) } 2592*a2f3d83cSJiri Slaby (SUSE) 2593*a2f3d83cSJiri Slaby (SUSE) ret = no_seek_end_llseek(file, offset, orig); 2594*a2f3d83cSJiri Slaby (SUSE) 2595*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2596*a2f3d83cSJiri Slaby (SUSE) return ret; 2597*a2f3d83cSJiri Slaby (SUSE) } 2598*a2f3d83cSJiri Slaby (SUSE) 2599*a2f3d83cSJiri Slaby (SUSE) static int sisusb_handle_command(struct sisusb_usb_data *sisusb, 2600*a2f3d83cSJiri Slaby (SUSE) struct sisusb_command *y, unsigned long arg) 2601*a2f3d83cSJiri Slaby (SUSE) { 2602*a2f3d83cSJiri Slaby (SUSE) int retval, length; 2603*a2f3d83cSJiri Slaby (SUSE) u32 port, address; 2604*a2f3d83cSJiri Slaby (SUSE) 2605*a2f3d83cSJiri Slaby (SUSE) /* All our commands require the device 2606*a2f3d83cSJiri Slaby (SUSE) * to be initialized. 2607*a2f3d83cSJiri Slaby (SUSE) */ 2608*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->devinit) 2609*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2610*a2f3d83cSJiri Slaby (SUSE) 2611*a2f3d83cSJiri Slaby (SUSE) port = y->data3 - 2612*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_PSEUDO_IOPORTBASE + 2613*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_IOPORTBASE; 2614*a2f3d83cSJiri Slaby (SUSE) 2615*a2f3d83cSJiri Slaby (SUSE) switch (y->operation) { 2616*a2f3d83cSJiri Slaby (SUSE) case SUCMD_GET: 2617*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1); 2618*a2f3d83cSJiri Slaby (SUSE) if (!retval) { 2619*a2f3d83cSJiri Slaby (SUSE) if (copy_to_user((void __user *)arg, y, sizeof(*y))) 2620*a2f3d83cSJiri Slaby (SUSE) retval = -EFAULT; 2621*a2f3d83cSJiri Slaby (SUSE) } 2622*a2f3d83cSJiri Slaby (SUSE) break; 2623*a2f3d83cSJiri Slaby (SUSE) 2624*a2f3d83cSJiri Slaby (SUSE) case SUCMD_SET: 2625*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1); 2626*a2f3d83cSJiri Slaby (SUSE) break; 2627*a2f3d83cSJiri Slaby (SUSE) 2628*a2f3d83cSJiri Slaby (SUSE) case SUCMD_SETOR: 2629*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1); 2630*a2f3d83cSJiri Slaby (SUSE) break; 2631*a2f3d83cSJiri Slaby (SUSE) 2632*a2f3d83cSJiri Slaby (SUSE) case SUCMD_SETAND: 2633*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1); 2634*a2f3d83cSJiri Slaby (SUSE) break; 2635*a2f3d83cSJiri Slaby (SUSE) 2636*a2f3d83cSJiri Slaby (SUSE) case SUCMD_SETANDOR: 2637*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_setidxregandor(sisusb, port, y->data0, 2638*a2f3d83cSJiri Slaby (SUSE) y->data1, y->data2); 2639*a2f3d83cSJiri Slaby (SUSE) break; 2640*a2f3d83cSJiri Slaby (SUSE) 2641*a2f3d83cSJiri Slaby (SUSE) case SUCMD_SETMASK: 2642*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_setidxregmask(sisusb, port, y->data0, 2643*a2f3d83cSJiri Slaby (SUSE) y->data1, y->data2); 2644*a2f3d83cSJiri Slaby (SUSE) break; 2645*a2f3d83cSJiri Slaby (SUSE) 2646*a2f3d83cSJiri Slaby (SUSE) case SUCMD_CLRSCR: 2647*a2f3d83cSJiri Slaby (SUSE) /* Gfx core must be initialized */ 2648*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->gfxinit) 2649*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2650*a2f3d83cSJiri Slaby (SUSE) 2651*a2f3d83cSJiri Slaby (SUSE) length = (y->data0 << 16) | (y->data1 << 8) | y->data2; 2652*a2f3d83cSJiri Slaby (SUSE) address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE + 2653*a2f3d83cSJiri Slaby (SUSE) SISUSB_PCI_MEMBASE; 2654*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_clear_vram(sisusb, address, length); 2655*a2f3d83cSJiri Slaby (SUSE) break; 2656*a2f3d83cSJiri Slaby (SUSE) 2657*a2f3d83cSJiri Slaby (SUSE) case SUCMD_HANDLETEXTMODE: 2658*a2f3d83cSJiri Slaby (SUSE) retval = 0; 2659*a2f3d83cSJiri Slaby (SUSE) break; 2660*a2f3d83cSJiri Slaby (SUSE) 2661*a2f3d83cSJiri Slaby (SUSE) default: 2662*a2f3d83cSJiri Slaby (SUSE) retval = -EINVAL; 2663*a2f3d83cSJiri Slaby (SUSE) } 2664*a2f3d83cSJiri Slaby (SUSE) 2665*a2f3d83cSJiri Slaby (SUSE) if (retval > 0) 2666*a2f3d83cSJiri Slaby (SUSE) retval = -EIO; 2667*a2f3d83cSJiri Slaby (SUSE) 2668*a2f3d83cSJiri Slaby (SUSE) return retval; 2669*a2f3d83cSJiri Slaby (SUSE) } 2670*a2f3d83cSJiri Slaby (SUSE) 2671*a2f3d83cSJiri Slaby (SUSE) static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2672*a2f3d83cSJiri Slaby (SUSE) { 2673*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2674*a2f3d83cSJiri Slaby (SUSE) struct sisusb_info x; 2675*a2f3d83cSJiri Slaby (SUSE) struct sisusb_command y; 2676*a2f3d83cSJiri Slaby (SUSE) long retval = 0; 2677*a2f3d83cSJiri Slaby (SUSE) u32 __user *argp = (u32 __user *)arg; 2678*a2f3d83cSJiri Slaby (SUSE) 2679*a2f3d83cSJiri Slaby (SUSE) sisusb = file->private_data; 2680*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2681*a2f3d83cSJiri Slaby (SUSE) return -ENODEV; 2682*a2f3d83cSJiri Slaby (SUSE) 2683*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2684*a2f3d83cSJiri Slaby (SUSE) 2685*a2f3d83cSJiri Slaby (SUSE) /* Sanity check */ 2686*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { 2687*a2f3d83cSJiri Slaby (SUSE) retval = -ENODEV; 2688*a2f3d83cSJiri Slaby (SUSE) goto err_out; 2689*a2f3d83cSJiri Slaby (SUSE) } 2690*a2f3d83cSJiri Slaby (SUSE) 2691*a2f3d83cSJiri Slaby (SUSE) switch (cmd) { 2692*a2f3d83cSJiri Slaby (SUSE) case SISUSB_GET_CONFIG_SIZE: 2693*a2f3d83cSJiri Slaby (SUSE) 2694*a2f3d83cSJiri Slaby (SUSE) if (put_user(sizeof(x), argp)) 2695*a2f3d83cSJiri Slaby (SUSE) retval = -EFAULT; 2696*a2f3d83cSJiri Slaby (SUSE) 2697*a2f3d83cSJiri Slaby (SUSE) break; 2698*a2f3d83cSJiri Slaby (SUSE) 2699*a2f3d83cSJiri Slaby (SUSE) case SISUSB_GET_CONFIG: 2700*a2f3d83cSJiri Slaby (SUSE) 2701*a2f3d83cSJiri Slaby (SUSE) x.sisusb_id = SISUSB_ID; 2702*a2f3d83cSJiri Slaby (SUSE) x.sisusb_version = SISUSB_VERSION; 2703*a2f3d83cSJiri Slaby (SUSE) x.sisusb_revision = SISUSB_REVISION; 2704*a2f3d83cSJiri Slaby (SUSE) x.sisusb_patchlevel = SISUSB_PATCHLEVEL; 2705*a2f3d83cSJiri Slaby (SUSE) x.sisusb_gfxinit = sisusb->gfxinit; 2706*a2f3d83cSJiri Slaby (SUSE) x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE; 2707*a2f3d83cSJiri Slaby (SUSE) x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE; 2708*a2f3d83cSJiri Slaby (SUSE) x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE; 2709*a2f3d83cSJiri Slaby (SUSE) x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE; 2710*a2f3d83cSJiri Slaby (SUSE) x.sisusb_vramsize = sisusb->vramsize; 2711*a2f3d83cSJiri Slaby (SUSE) x.sisusb_minor = sisusb->minor; 2712*a2f3d83cSJiri Slaby (SUSE) x.sisusb_fbdevactive = 0; 2713*a2f3d83cSJiri Slaby (SUSE) x.sisusb_conactive = 0; 2714*a2f3d83cSJiri Slaby (SUSE) memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); 2715*a2f3d83cSJiri Slaby (SUSE) 2716*a2f3d83cSJiri Slaby (SUSE) if (copy_to_user((void __user *)arg, &x, sizeof(x))) 2717*a2f3d83cSJiri Slaby (SUSE) retval = -EFAULT; 2718*a2f3d83cSJiri Slaby (SUSE) 2719*a2f3d83cSJiri Slaby (SUSE) break; 2720*a2f3d83cSJiri Slaby (SUSE) 2721*a2f3d83cSJiri Slaby (SUSE) case SISUSB_COMMAND: 2722*a2f3d83cSJiri Slaby (SUSE) 2723*a2f3d83cSJiri Slaby (SUSE) if (copy_from_user(&y, (void __user *)arg, sizeof(y))) 2724*a2f3d83cSJiri Slaby (SUSE) retval = -EFAULT; 2725*a2f3d83cSJiri Slaby (SUSE) else 2726*a2f3d83cSJiri Slaby (SUSE) retval = sisusb_handle_command(sisusb, &y, arg); 2727*a2f3d83cSJiri Slaby (SUSE) 2728*a2f3d83cSJiri Slaby (SUSE) break; 2729*a2f3d83cSJiri Slaby (SUSE) 2730*a2f3d83cSJiri Slaby (SUSE) default: 2731*a2f3d83cSJiri Slaby (SUSE) retval = -ENOTTY; 2732*a2f3d83cSJiri Slaby (SUSE) break; 2733*a2f3d83cSJiri Slaby (SUSE) } 2734*a2f3d83cSJiri Slaby (SUSE) 2735*a2f3d83cSJiri Slaby (SUSE) err_out: 2736*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2737*a2f3d83cSJiri Slaby (SUSE) return retval; 2738*a2f3d83cSJiri Slaby (SUSE) } 2739*a2f3d83cSJiri Slaby (SUSE) 2740*a2f3d83cSJiri Slaby (SUSE) #ifdef CONFIG_COMPAT 2741*a2f3d83cSJiri Slaby (SUSE) static long sisusb_compat_ioctl(struct file *f, unsigned int cmd, 2742*a2f3d83cSJiri Slaby (SUSE) unsigned long arg) 2743*a2f3d83cSJiri Slaby (SUSE) { 2744*a2f3d83cSJiri Slaby (SUSE) switch (cmd) { 2745*a2f3d83cSJiri Slaby (SUSE) case SISUSB_GET_CONFIG_SIZE: 2746*a2f3d83cSJiri Slaby (SUSE) case SISUSB_GET_CONFIG: 2747*a2f3d83cSJiri Slaby (SUSE) case SISUSB_COMMAND: 2748*a2f3d83cSJiri Slaby (SUSE) return sisusb_ioctl(f, cmd, arg); 2749*a2f3d83cSJiri Slaby (SUSE) 2750*a2f3d83cSJiri Slaby (SUSE) default: 2751*a2f3d83cSJiri Slaby (SUSE) return -ENOIOCTLCMD; 2752*a2f3d83cSJiri Slaby (SUSE) } 2753*a2f3d83cSJiri Slaby (SUSE) } 2754*a2f3d83cSJiri Slaby (SUSE) #endif 2755*a2f3d83cSJiri Slaby (SUSE) 2756*a2f3d83cSJiri Slaby (SUSE) static const struct file_operations usb_sisusb_fops = { 2757*a2f3d83cSJiri Slaby (SUSE) .owner = THIS_MODULE, 2758*a2f3d83cSJiri Slaby (SUSE) .open = sisusb_open, 2759*a2f3d83cSJiri Slaby (SUSE) .release = sisusb_release, 2760*a2f3d83cSJiri Slaby (SUSE) .read = sisusb_read, 2761*a2f3d83cSJiri Slaby (SUSE) .write = sisusb_write, 2762*a2f3d83cSJiri Slaby (SUSE) .llseek = sisusb_lseek, 2763*a2f3d83cSJiri Slaby (SUSE) #ifdef CONFIG_COMPAT 2764*a2f3d83cSJiri Slaby (SUSE) .compat_ioctl = sisusb_compat_ioctl, 2765*a2f3d83cSJiri Slaby (SUSE) #endif 2766*a2f3d83cSJiri Slaby (SUSE) .unlocked_ioctl = sisusb_ioctl 2767*a2f3d83cSJiri Slaby (SUSE) }; 2768*a2f3d83cSJiri Slaby (SUSE) 2769*a2f3d83cSJiri Slaby (SUSE) static struct usb_class_driver usb_sisusb_class = { 2770*a2f3d83cSJiri Slaby (SUSE) .name = "sisusbvga%d", 2771*a2f3d83cSJiri Slaby (SUSE) .fops = &usb_sisusb_fops, 2772*a2f3d83cSJiri Slaby (SUSE) .minor_base = SISUSB_MINOR 2773*a2f3d83cSJiri Slaby (SUSE) }; 2774*a2f3d83cSJiri Slaby (SUSE) 2775*a2f3d83cSJiri Slaby (SUSE) static int sisusb_probe(struct usb_interface *intf, 2776*a2f3d83cSJiri Slaby (SUSE) const struct usb_device_id *id) 2777*a2f3d83cSJiri Slaby (SUSE) { 2778*a2f3d83cSJiri Slaby (SUSE) struct usb_device *dev = interface_to_usbdev(intf); 2779*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2780*a2f3d83cSJiri Slaby (SUSE) int retval = 0, i; 2781*a2f3d83cSJiri Slaby (SUSE) 2782*a2f3d83cSJiri Slaby (SUSE) dev_info(&dev->dev, "USB2VGA dongle found at address %d\n", 2783*a2f3d83cSJiri Slaby (SUSE) dev->devnum); 2784*a2f3d83cSJiri Slaby (SUSE) 2785*a2f3d83cSJiri Slaby (SUSE) /* Allocate memory for our private */ 2786*a2f3d83cSJiri Slaby (SUSE) sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL); 2787*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2788*a2f3d83cSJiri Slaby (SUSE) return -ENOMEM; 2789*a2f3d83cSJiri Slaby (SUSE) 2790*a2f3d83cSJiri Slaby (SUSE) kref_init(&sisusb->kref); 2791*a2f3d83cSJiri Slaby (SUSE) 2792*a2f3d83cSJiri Slaby (SUSE) mutex_init(&(sisusb->lock)); 2793*a2f3d83cSJiri Slaby (SUSE) 2794*a2f3d83cSJiri Slaby (SUSE) sisusb->sisusb_dev = dev; 2795*a2f3d83cSJiri Slaby (SUSE) sisusb->vrambase = SISUSB_PCI_MEMBASE; 2796*a2f3d83cSJiri Slaby (SUSE) sisusb->mmiobase = SISUSB_PCI_MMIOBASE; 2797*a2f3d83cSJiri Slaby (SUSE) sisusb->mmiosize = SISUSB_PCI_MMIOSIZE; 2798*a2f3d83cSJiri Slaby (SUSE) sisusb->ioportbase = SISUSB_PCI_IOPORTBASE; 2799*a2f3d83cSJiri Slaby (SUSE) /* Everything else is zero */ 2800*a2f3d83cSJiri Slaby (SUSE) 2801*a2f3d83cSJiri Slaby (SUSE) /* Register device */ 2802*a2f3d83cSJiri Slaby (SUSE) retval = usb_register_dev(intf, &usb_sisusb_class); 2803*a2f3d83cSJiri Slaby (SUSE) if (retval) { 2804*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 2805*a2f3d83cSJiri Slaby (SUSE) "Failed to get a minor for device %d\n", 2806*a2f3d83cSJiri Slaby (SUSE) dev->devnum); 2807*a2f3d83cSJiri Slaby (SUSE) retval = -ENODEV; 2808*a2f3d83cSJiri Slaby (SUSE) goto error_1; 2809*a2f3d83cSJiri Slaby (SUSE) } 2810*a2f3d83cSJiri Slaby (SUSE) 2811*a2f3d83cSJiri Slaby (SUSE) sisusb->minor = intf->minor; 2812*a2f3d83cSJiri Slaby (SUSE) 2813*a2f3d83cSJiri Slaby (SUSE) /* Allocate buffers */ 2814*a2f3d83cSJiri Slaby (SUSE) sisusb->ibufsize = SISUSB_IBUF_SIZE; 2815*a2f3d83cSJiri Slaby (SUSE) sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL); 2816*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->ibuf) { 2817*a2f3d83cSJiri Slaby (SUSE) retval = -ENOMEM; 2818*a2f3d83cSJiri Slaby (SUSE) goto error_2; 2819*a2f3d83cSJiri Slaby (SUSE) } 2820*a2f3d83cSJiri Slaby (SUSE) 2821*a2f3d83cSJiri Slaby (SUSE) sisusb->numobufs = 0; 2822*a2f3d83cSJiri Slaby (SUSE) sisusb->obufsize = SISUSB_OBUF_SIZE; 2823*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < NUMOBUFS; i++) { 2824*a2f3d83cSJiri Slaby (SUSE) sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL); 2825*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->obuf[i]) { 2826*a2f3d83cSJiri Slaby (SUSE) if (i == 0) { 2827*a2f3d83cSJiri Slaby (SUSE) retval = -ENOMEM; 2828*a2f3d83cSJiri Slaby (SUSE) goto error_3; 2829*a2f3d83cSJiri Slaby (SUSE) } 2830*a2f3d83cSJiri Slaby (SUSE) break; 2831*a2f3d83cSJiri Slaby (SUSE) } 2832*a2f3d83cSJiri Slaby (SUSE) sisusb->numobufs++; 2833*a2f3d83cSJiri Slaby (SUSE) } 2834*a2f3d83cSJiri Slaby (SUSE) 2835*a2f3d83cSJiri Slaby (SUSE) /* Allocate URBs */ 2836*a2f3d83cSJiri Slaby (SUSE) sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL); 2837*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->sisurbin) { 2838*a2f3d83cSJiri Slaby (SUSE) retval = -ENOMEM; 2839*a2f3d83cSJiri Slaby (SUSE) goto error_3; 2840*a2f3d83cSJiri Slaby (SUSE) } 2841*a2f3d83cSJiri Slaby (SUSE) sisusb->completein = 1; 2842*a2f3d83cSJiri Slaby (SUSE) 2843*a2f3d83cSJiri Slaby (SUSE) for (i = 0; i < sisusb->numobufs; i++) { 2844*a2f3d83cSJiri Slaby (SUSE) sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL); 2845*a2f3d83cSJiri Slaby (SUSE) if (!sisusb->sisurbout[i]) { 2846*a2f3d83cSJiri Slaby (SUSE) retval = -ENOMEM; 2847*a2f3d83cSJiri Slaby (SUSE) goto error_4; 2848*a2f3d83cSJiri Slaby (SUSE) } 2849*a2f3d83cSJiri Slaby (SUSE) sisusb->urbout_context[i].sisusb = (void *)sisusb; 2850*a2f3d83cSJiri Slaby (SUSE) sisusb->urbout_context[i].urbindex = i; 2851*a2f3d83cSJiri Slaby (SUSE) sisusb->urbstatus[i] = 0; 2852*a2f3d83cSJiri Slaby (SUSE) } 2853*a2f3d83cSJiri Slaby (SUSE) 2854*a2f3d83cSJiri Slaby (SUSE) dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", 2855*a2f3d83cSJiri Slaby (SUSE) sisusb->numobufs); 2856*a2f3d83cSJiri Slaby (SUSE) 2857*a2f3d83cSJiri Slaby (SUSE) /* Do remaining init stuff */ 2858*a2f3d83cSJiri Slaby (SUSE) 2859*a2f3d83cSJiri Slaby (SUSE) init_waitqueue_head(&sisusb->wait_q); 2860*a2f3d83cSJiri Slaby (SUSE) 2861*a2f3d83cSJiri Slaby (SUSE) usb_set_intfdata(intf, sisusb); 2862*a2f3d83cSJiri Slaby (SUSE) 2863*a2f3d83cSJiri Slaby (SUSE) usb_get_dev(sisusb->sisusb_dev); 2864*a2f3d83cSJiri Slaby (SUSE) 2865*a2f3d83cSJiri Slaby (SUSE) sisusb->present = 1; 2866*a2f3d83cSJiri Slaby (SUSE) 2867*a2f3d83cSJiri Slaby (SUSE) if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) { 2868*a2f3d83cSJiri Slaby (SUSE) int initscreen = 1; 2869*a2f3d83cSJiri Slaby (SUSE) if (sisusb_init_gfxdevice(sisusb, initscreen)) 2870*a2f3d83cSJiri Slaby (SUSE) dev_err(&sisusb->sisusb_dev->dev, 2871*a2f3d83cSJiri Slaby (SUSE) "Failed to early initialize device\n"); 2872*a2f3d83cSJiri Slaby (SUSE) 2873*a2f3d83cSJiri Slaby (SUSE) } else 2874*a2f3d83cSJiri Slaby (SUSE) dev_info(&sisusb->sisusb_dev->dev, 2875*a2f3d83cSJiri Slaby (SUSE) "Not attached to USB 2.0 hub, deferring init\n"); 2876*a2f3d83cSJiri Slaby (SUSE) 2877*a2f3d83cSJiri Slaby (SUSE) sisusb->ready = 1; 2878*a2f3d83cSJiri Slaby (SUSE) 2879*a2f3d83cSJiri Slaby (SUSE) #ifdef SISUSBENDIANTEST 2880*a2f3d83cSJiri Slaby (SUSE) dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n"); 2881*a2f3d83cSJiri Slaby (SUSE) sisusb_testreadwrite(sisusb); 2882*a2f3d83cSJiri Slaby (SUSE) dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n"); 2883*a2f3d83cSJiri Slaby (SUSE) #endif 2884*a2f3d83cSJiri Slaby (SUSE) 2885*a2f3d83cSJiri Slaby (SUSE) return 0; 2886*a2f3d83cSJiri Slaby (SUSE) 2887*a2f3d83cSJiri Slaby (SUSE) error_4: 2888*a2f3d83cSJiri Slaby (SUSE) sisusb_free_urbs(sisusb); 2889*a2f3d83cSJiri Slaby (SUSE) error_3: 2890*a2f3d83cSJiri Slaby (SUSE) sisusb_free_buffers(sisusb); 2891*a2f3d83cSJiri Slaby (SUSE) error_2: 2892*a2f3d83cSJiri Slaby (SUSE) usb_deregister_dev(intf, &usb_sisusb_class); 2893*a2f3d83cSJiri Slaby (SUSE) error_1: 2894*a2f3d83cSJiri Slaby (SUSE) kfree(sisusb); 2895*a2f3d83cSJiri Slaby (SUSE) return retval; 2896*a2f3d83cSJiri Slaby (SUSE) } 2897*a2f3d83cSJiri Slaby (SUSE) 2898*a2f3d83cSJiri Slaby (SUSE) static void sisusb_disconnect(struct usb_interface *intf) 2899*a2f3d83cSJiri Slaby (SUSE) { 2900*a2f3d83cSJiri Slaby (SUSE) struct sisusb_usb_data *sisusb; 2901*a2f3d83cSJiri Slaby (SUSE) 2902*a2f3d83cSJiri Slaby (SUSE) /* This should *not* happen */ 2903*a2f3d83cSJiri Slaby (SUSE) sisusb = usb_get_intfdata(intf); 2904*a2f3d83cSJiri Slaby (SUSE) if (!sisusb) 2905*a2f3d83cSJiri Slaby (SUSE) return; 2906*a2f3d83cSJiri Slaby (SUSE) 2907*a2f3d83cSJiri Slaby (SUSE) usb_deregister_dev(intf, &usb_sisusb_class); 2908*a2f3d83cSJiri Slaby (SUSE) 2909*a2f3d83cSJiri Slaby (SUSE) mutex_lock(&sisusb->lock); 2910*a2f3d83cSJiri Slaby (SUSE) 2911*a2f3d83cSJiri Slaby (SUSE) /* Wait for all URBs to complete and kill them in case (MUST do) */ 2912*a2f3d83cSJiri Slaby (SUSE) if (!sisusb_wait_all_out_complete(sisusb)) 2913*a2f3d83cSJiri Slaby (SUSE) sisusb_kill_all_busy(sisusb); 2914*a2f3d83cSJiri Slaby (SUSE) 2915*a2f3d83cSJiri Slaby (SUSE) usb_set_intfdata(intf, NULL); 2916*a2f3d83cSJiri Slaby (SUSE) 2917*a2f3d83cSJiri Slaby (SUSE) sisusb->present = 0; 2918*a2f3d83cSJiri Slaby (SUSE) sisusb->ready = 0; 2919*a2f3d83cSJiri Slaby (SUSE) 2920*a2f3d83cSJiri Slaby (SUSE) mutex_unlock(&sisusb->lock); 2921*a2f3d83cSJiri Slaby (SUSE) 2922*a2f3d83cSJiri Slaby (SUSE) /* decrement our usage count */ 2923*a2f3d83cSJiri Slaby (SUSE) kref_put(&sisusb->kref, sisusb_delete); 2924*a2f3d83cSJiri Slaby (SUSE) } 2925*a2f3d83cSJiri Slaby (SUSE) 2926*a2f3d83cSJiri Slaby (SUSE) static const struct usb_device_id sisusb_table[] = { 2927*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0550) }, 2928*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0900) }, 2929*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0901) }, 2930*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0902) }, 2931*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0903) }, 2932*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0918) }, 2933*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0920) }, 2934*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x0950) }, 2935*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x0711, 0x5200) }, 2936*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x182d, 0x021c) }, 2937*a2f3d83cSJiri Slaby (SUSE) { USB_DEVICE(0x182d, 0x0269) }, 2938*a2f3d83cSJiri Slaby (SUSE) { } 2939*a2f3d83cSJiri Slaby (SUSE) }; 2940*a2f3d83cSJiri Slaby (SUSE) 2941*a2f3d83cSJiri Slaby (SUSE) MODULE_DEVICE_TABLE(usb, sisusb_table); 2942*a2f3d83cSJiri Slaby (SUSE) 2943*a2f3d83cSJiri Slaby (SUSE) static struct usb_driver sisusb_driver = { 2944*a2f3d83cSJiri Slaby (SUSE) .name = "sisusb", 2945*a2f3d83cSJiri Slaby (SUSE) .probe = sisusb_probe, 2946*a2f3d83cSJiri Slaby (SUSE) .disconnect = sisusb_disconnect, 2947*a2f3d83cSJiri Slaby (SUSE) .id_table = sisusb_table, 2948*a2f3d83cSJiri Slaby (SUSE) }; 2949*a2f3d83cSJiri Slaby (SUSE) 2950*a2f3d83cSJiri Slaby (SUSE) static int __init usb_sisusb_init(void) 2951*a2f3d83cSJiri Slaby (SUSE) { 2952*a2f3d83cSJiri Slaby (SUSE) return usb_register(&sisusb_driver); 2953*a2f3d83cSJiri Slaby (SUSE) } 2954*a2f3d83cSJiri Slaby (SUSE) 2955*a2f3d83cSJiri Slaby (SUSE) static void __exit usb_sisusb_exit(void) 2956*a2f3d83cSJiri Slaby (SUSE) { 2957*a2f3d83cSJiri Slaby (SUSE) usb_deregister(&sisusb_driver); 2958*a2f3d83cSJiri Slaby (SUSE) } 2959*a2f3d83cSJiri Slaby (SUSE) 2960*a2f3d83cSJiri Slaby (SUSE) module_init(usb_sisusb_init); 2961*a2f3d83cSJiri Slaby (SUSE) module_exit(usb_sisusb_exit); 2962*a2f3d83cSJiri Slaby (SUSE) 2963*a2f3d83cSJiri Slaby (SUSE) MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>"); 2964*a2f3d83cSJiri Slaby (SUSE) MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles"); 2965*a2f3d83cSJiri Slaby (SUSE) MODULE_LICENSE("GPL"); 2966*a2f3d83cSJiri Slaby (SUSE) 2967