1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
   7 /*
   8  * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
   9  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
  10  * All Rights Reserved.
  11  *
  12  * Permission is hereby granted, free of charge, to any person obtaining a
  13  * copy of this software and associated documentation files (the "Software"),
  14  * to deal in the Software without restriction, including without limitation
  15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  16  * and/or sell copies of the Software, and to permit persons to whom the
  17  * Software is furnished to do so, subject to the following conditions:
  18  *
  19  * The above copyright notice and this permission notice (including the next
  20  * paragraph) shall be included in all copies or substantial portions of the
  21  * Software.
  22  *
  23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  26  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  27  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  28  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  29  * DEALINGS IN THE SOFTWARE.
  30  *
  31  * Authors:
  32  *    Kevin E. Martin <martin@valinux.com>
  33  *    Gareth Hughes <gareth@valinux.com>
  34  */
  35 
  36 #pragma ident   "%Z%%M% %I%     %E% SMI"
  37 
  38 #include "drmP.h"
  39 #include "drm.h"
  40 #include "radeon_drm.h"
  41 #include "radeon_drv.h"
  42 #include "r300_reg.h"
  43 #include "radeon_io32.h"
  44 
  45 static int radeon_do_cleanup_cp(drm_device_t *dev);
  46 
  47 /* CP microcode (from ATI) */
  48 static const u32 R200_cp_microcode[][2] = {
  49         {0x21007000, 0000000000},
  50         {0x20007000, 0000000000},
  51         {0x000000ab, 0x00000004},
  52         {0x000000af, 0x00000004},
  53         {0x66544a49, 0000000000},
  54         {0x49494174, 0000000000},
  55         {0x54517d83, 0000000000},
  56         {0x498d8b64, 0000000000},
  57         {0x49494949, 0000000000},
  58         {0x49da493c, 0000000000},
  59         {0x49989898, 0000000000},
  60         {0xd34949d5, 0000000000},
  61         {0x9dc90e11, 0000000000},
  62         {0xce9b9b9b, 0000000000},
  63         {0x000f0000, 0x00000016},
  64         {0x352e232c, 0000000000},
  65         {0x00000013, 0x00000004},
  66         {0x000f0000, 0x00000016},
  67         {0x352e272c, 0000000000},
  68         {0x000f0001, 0x00000016},
  69         {0x3239362f, 0000000000},
  70         {0x000077ef, 0x00000002},
  71         {0x00061000, 0x00000002},
  72         {0x00000020, 0x0000001a},
  73         {0x00004000, 0x0000001e},
  74         {0x00061000, 0x00000002},
  75         {0x00000020, 0x0000001a},
  76         {0x00004000, 0x0000001e},
  77         {0x00061000, 0x00000002},
  78         {0x00000020, 0x0000001a},
  79         {0x00004000, 0x0000001e},
  80         {0x00000016, 0x00000004},
  81         {0x0003802a, 0x00000002},
  82         {0x040067e0, 0x00000002},
  83         {0x00000016, 0x00000004},
  84         {0x000077e0, 0x00000002},
  85         {0x00065000, 0x00000002},
  86         {0x000037e1, 0x00000002},
  87         {0x040067e1, 0x00000006},
  88         {0x000077e0, 0x00000002},
  89         {0x000077e1, 0x00000002},
  90         {0x000077e1, 0x00000006},
  91         {0xffffffff, 0000000000},
  92         {0x10000000, 0000000000},
  93         {0x0003802a, 0x00000002},
  94         {0x040067e0, 0x00000006},
  95         {0x00007675, 0x00000002},
  96         {0x00007676, 0x00000002},
  97         {0x00007677, 0x00000002},
  98         {0x00007678, 0x00000006},
  99         {0x0003802b, 0x00000002},
 100         {0x04002676, 0x00000002},
 101         {0x00007677, 0x00000002},
 102         {0x00007678, 0x00000006},
 103         {0x0000002e, 0x00000018},
 104         {0x0000002e, 0x00000018},
 105         {0000000000, 0x00000006},
 106         {0x0000002f, 0x00000018},
 107         {0x0000002f, 0x00000018},
 108         {0000000000, 0x00000006},
 109         {0x01605000, 0x00000002},
 110         {0x00065000, 0x00000002},
 111         {0x00098000, 0x00000002},
 112         {0x00061000, 0x00000002},
 113         {0x64c0603d, 0x00000004},
 114         {0x00080000, 0x00000016},
 115         {0000000000, 0000000000},
 116         {0x0400251d, 0x00000002},
 117         {0x00007580, 0x00000002},
 118         {0x00067581, 0x00000002},
 119         {0x04002580, 0x00000002},
 120         {0x00067581, 0x00000002},
 121         {0x00000046, 0x00000004},
 122         {0x00005000, 0000000000},
 123         {0x00061000, 0x00000002},
 124         {0x0000750e, 0x00000002},
 125         {0x00019000, 0x00000002},
 126         {0x00011055, 0x00000014},
 127         {0x00000055, 0x00000012},
 128         {0x0400250f, 0x00000002},
 129         {0x0000504a, 0x00000004},
 130         {0x00007565, 0x00000002},
 131         {0x00007566, 0x00000002},
 132         {0x00000051, 0x00000004},
 133         {0x01e655b4, 0x00000002},
 134         {0x4401b0dc, 0x00000002},
 135         {0x01c110dc, 0x00000002},
 136         {0x2666705d, 0x00000018},
 137         {0x040c2565, 0x00000002},
 138         {0x0000005d, 0x00000018},
 139         {0x04002564, 0x00000002},
 140         {0x00007566, 0x00000002},
 141         {0x00000054, 0x00000004},
 142         {0x00401060, 0x00000008},
 143         {0x00101000, 0x00000002},
 144         {0x000d80ff, 0x00000002},
 145         {0x00800063, 0x00000008},
 146         {0x000f9000, 0x00000002},
 147         {0x000e00ff, 0x00000002},
 148         {0000000000, 0x00000006},
 149         {0x00000080, 0x00000018},
 150         {0x00000054, 0x00000004},
 151         {0x00007576, 0x00000002},
 152         {0x00065000, 0x00000002},
 153         {0x00009000, 0x00000002},
 154         {0x00041000, 0x00000002},
 155         {0x0c00350e, 0x00000002},
 156         {0x00049000, 0x00000002},
 157         {0x00051000, 0x00000002},
 158         {0x01e785f8, 0x00000002},
 159         {0x00200000, 0x00000002},
 160         {0x00600073, 0x0000000c},
 161         {0x00007563, 0x00000002},
 162         {0x006075f0, 0x00000021},
 163         {0x20007068, 0x00000004},
 164         {0x00005068, 0x00000004},
 165         {0x00007576, 0x00000002},
 166         {0x00007577, 0x00000002},
 167         {0x0000750e, 0x00000002},
 168         {0x0000750f, 0x00000002},
 169         {0x00a05000, 0x00000002},
 170         {0x00600076, 0x0000000c},
 171         {0x006075f0, 0x00000021},
 172         {0x000075f8, 0x00000002},
 173         {0x00000076, 0x00000004},
 174         {0x000a750e, 0x00000002},
 175         {0x0020750f, 0x00000002},
 176         {0x00600079, 0x00000004},
 177         {0x00007570, 0x00000002},
 178         {0x00007571, 0x00000002},
 179         {0x00007572, 0x00000006},
 180         {0x00005000, 0x00000002},
 181         {0x00a05000, 0x00000002},
 182         {0x00007568, 0x00000002},
 183         {0x00061000, 0x00000002},
 184         {0x00000084, 0x0000000c},
 185         {0x00058000, 0x00000002},
 186         {0x0c607562, 0x00000002},
 187         {0x00000086, 0x00000004},
 188         {0x00600085, 0x00000004},
 189         {0x400070dd, 0000000000},
 190         {0x000380dd, 0x00000002},
 191         {0x00000093, 0x0000001c},
 192         {0x00065095, 0x00000018},
 193         {0x040025bb, 0x00000002},
 194         {0x00061096, 0x00000018},
 195         {0x040075bc, 0000000000},
 196         {0x000075bb, 0x00000002},
 197         {0x000075bc, 0000000000},
 198         {0x00090000, 0x00000006},
 199         {0x00090000, 0x00000002},
 200         {0x000d8002, 0x00000006},
 201         {0x00005000, 0x00000002},
 202         {0x00007821, 0x00000002},
 203         {0x00007800, 0000000000},
 204         {0x00007821, 0x00000002},
 205         {0x00007800, 0000000000},
 206         {0x01665000, 0x00000002},
 207         {0x000a0000, 0x00000002},
 208         {0x000671cc, 0x00000002},
 209         {0x0286f1cd, 0x00000002},
 210         {0x000000a3, 0x00000010},
 211         {0x21007000, 0000000000},
 212         {0x000000aa, 0x0000001c},
 213         {0x00065000, 0x00000002},
 214         {0x000a0000, 0x00000002},
 215         {0x00061000, 0x00000002},
 216         {0x000b0000, 0x00000002},
 217         {0x38067000, 0x00000002},
 218         {0x000a00a6, 0x00000004},
 219         {0x20007000, 0000000000},
 220         {0x01200000, 0x00000002},
 221         {0x20077000, 0x00000002},
 222         {0x01200000, 0x00000002},
 223         {0x20007000, 0000000000},
 224         {0x00061000, 0x00000002},
 225         {0x0120751b, 0x00000002},
 226         {0x8040750a, 0x00000002},
 227         {0x8040750b, 0x00000002},
 228         {0x00110000, 0x00000002},
 229         {0x000380dd, 0x00000002},
 230         {0x000000bd, 0x0000001c},
 231         {0x00061096, 0x00000018},
 232         {0x844075bd, 0x00000002},
 233         {0x00061095, 0x00000018},
 234         {0x840075bb, 0x00000002},
 235         {0x00061096, 0x00000018},
 236         {0x844075bc, 0x00000002},
 237         {0x000000c0, 0x00000004},
 238         {0x804075bd, 0x00000002},
 239         {0x800075bb, 0x00000002},
 240         {0x804075bc, 0x00000002},
 241         {0x00108000, 0x00000002},
 242         {0x01400000, 0x00000002},
 243         {0x006000c4, 0x0000000c},
 244         {0x20c07000, 0x00000020},
 245         {0x000000c6, 0x00000012},
 246         {0x00800000, 0x00000006},
 247         {0x0080751d, 0x00000006},
 248         {0x000025bb, 0x00000002},
 249         {0x000040c0, 0x00000004},
 250         {0x0000775c, 0x00000002},
 251         {0x00a05000, 0x00000002},
 252         {0x00661000, 0x00000002},
 253         {0x0460275d, 0x00000020},
 254         {0x00004000, 0000000000},
 255         {0x00007999, 0x00000002},
 256         {0x00a05000, 0x00000002},
 257         {0x00661000, 0x00000002},
 258         {0x0460299b, 0x00000020},
 259         {0x00004000, 0000000000},
 260         {0x01e00830, 0x00000002},
 261         {0x21007000, 0000000000},
 262         {0x00005000, 0x00000002},
 263         {0x00038042, 0x00000002},
 264         {0x040025e0, 0x00000002},
 265         {0x000075e1, 0000000000},
 266         {0x00000001, 0000000000},
 267         {0x000380d9, 0x00000002},
 268         {0x04007394, 0000000000},
 269         {0000000000, 0000000000},
 270         {0000000000, 0000000000},
 271         {0000000000, 0000000000},
 272         {0000000000, 0000000000},
 273         {0000000000, 0000000000},
 274         {0000000000, 0000000000},
 275         {0000000000, 0000000000},
 276         {0000000000, 0000000000},
 277         {0000000000, 0000000000},
 278         {0000000000, 0000000000},
 279         {0000000000, 0000000000},
 280         {0000000000, 0000000000},
 281         {0000000000, 0000000000},
 282         {0000000000, 0000000000},
 283         {0000000000, 0000000000},
 284         {0000000000, 0000000000},
 285         {0000000000, 0000000000},
 286         {0000000000, 0000000000},
 287         {0000000000, 0000000000},
 288         {0000000000, 0000000000},
 289         {0000000000, 0000000000},
 290         {0000000000, 0000000000},
 291         {0000000000, 0000000000},
 292         {0000000000, 0000000000},
 293         {0000000000, 0000000000},
 294         {0000000000, 0000000000},
 295         {0000000000, 0000000000},
 296         {0000000000, 0000000000},
 297         {0000000000, 0000000000},
 298         {0000000000, 0000000000},
 299         {0000000000, 0000000000},
 300         {0000000000, 0000000000},
 301         {0000000000, 0000000000},
 302         {0000000000, 0000000000},
 303         {0000000000, 0000000000},
 304         {0000000000, 0000000000},
 305 };
 306 
 307 static const u32 radeon_cp_microcode[][2] = {
 308         {0x21007000, 0000000000},
 309         {0x20007000, 0000000000},
 310         {0x000000b4, 0x00000004},
 311         {0x000000b8, 0x00000004},
 312         {0x6f5b4d4c, 0000000000},
 313         {0x4c4c427f, 0000000000},
 314         {0x5b568a92, 0000000000},
 315         {0x4ca09c6d, 0000000000},
 316         {0xad4c4c4c, 0000000000},
 317         {0x4ce1af3d, 0000000000},
 318         {0xd8afafaf, 0000000000},
 319         {0xd64c4cdc, 0000000000},
 320         {0x4cd10d10, 0000000000},
 321         {0x000f0000, 0x00000016},
 322         {0x362f242d, 0000000000},
 323         {0x00000012, 0x00000004},
 324         {0x000f0000, 0x00000016},
 325         {0x362f282d, 0000000000},
 326         {0x000380e7, 0x00000002},
 327         {0x04002c97, 0x00000002},
 328         {0x000f0001, 0x00000016},
 329         {0x333a3730, 0000000000},
 330         {0x000077ef, 0x00000002},
 331         {0x00061000, 0x00000002},
 332         {0x00000021, 0x0000001a},
 333         {0x00004000, 0x0000001e},
 334         {0x00061000, 0x00000002},
 335         {0x00000021, 0x0000001a},
 336         {0x00004000, 0x0000001e},
 337         {0x00061000, 0x00000002},
 338         {0x00000021, 0x0000001a},
 339         {0x00004000, 0x0000001e},
 340         {0x00000017, 0x00000004},
 341         {0x0003802b, 0x00000002},
 342         {0x040067e0, 0x00000002},
 343         {0x00000017, 0x00000004},
 344         {0x000077e0, 0x00000002},
 345         {0x00065000, 0x00000002},
 346         {0x000037e1, 0x00000002},
 347         {0x040067e1, 0x00000006},
 348         {0x000077e0, 0x00000002},
 349         {0x000077e1, 0x00000002},
 350         {0x000077e1, 0x00000006},
 351         {0xffffffff, 0000000000},
 352         {0x10000000, 0000000000},
 353         {0x0003802b, 0x00000002},
 354         {0x040067e0, 0x00000006},
 355         {0x00007675, 0x00000002},
 356         {0x00007676, 0x00000002},
 357         {0x00007677, 0x00000002},
 358         {0x00007678, 0x00000006},
 359         {0x0003802c, 0x00000002},
 360         {0x04002676, 0x00000002},
 361         {0x00007677, 0x00000002},
 362         {0x00007678, 0x00000006},
 363         {0x0000002f, 0x00000018},
 364         {0x0000002f, 0x00000018},
 365         {0000000000, 0x00000006},
 366         {0x00000030, 0x00000018},
 367         {0x00000030, 0x00000018},
 368         {0000000000, 0x00000006},
 369         {0x01605000, 0x00000002},
 370         {0x00065000, 0x00000002},
 371         {0x00098000, 0x00000002},
 372         {0x00061000, 0x00000002},
 373         {0x64c0603e, 0x00000004},
 374         {0x000380e6, 0x00000002},
 375         {0x040025c5, 0x00000002},
 376         {0x00080000, 0x00000016},
 377         {0000000000, 0000000000},
 378         {0x0400251d, 0x00000002},
 379         {0x00007580, 0x00000002},
 380         {0x00067581, 0x00000002},
 381         {0x04002580, 0x00000002},
 382         {0x00067581, 0x00000002},
 383         {0x00000049, 0x00000004},
 384         {0x00005000, 0000000000},
 385         {0x000380e6, 0x00000002},
 386         {0x040025c5, 0x00000002},
 387         {0x00061000, 0x00000002},
 388         {0x0000750e, 0x00000002},
 389         {0x00019000, 0x00000002},
 390         {0x00011055, 0x00000014},
 391         {0x00000055, 0x00000012},
 392         {0x0400250f, 0x00000002},
 393         {0x0000504f, 0x00000004},
 394         {0x000380e6, 0x00000002},
 395         {0x040025c5, 0x00000002},
 396         {0x00007565, 0x00000002},
 397         {0x00007566, 0x00000002},
 398         {0x00000058, 0x00000004},
 399         {0x000380e6, 0x00000002},
 400         {0x040025c5, 0x00000002},
 401         {0x01e655b4, 0x00000002},
 402         {0x4401b0e4, 0x00000002},
 403         {0x01c110e4, 0x00000002},
 404         {0x26667066, 0x00000018},
 405         {0x040c2565, 0x00000002},
 406         {0x00000066, 0x00000018},
 407         {0x04002564, 0x00000002},
 408         {0x00007566, 0x00000002},
 409         {0x0000005d, 0x00000004},
 410         {0x00401069, 0x00000008},
 411         {0x00101000, 0x00000002},
 412         {0x000d80ff, 0x00000002},
 413         {0x0080006c, 0x00000008},
 414         {0x000f9000, 0x00000002},
 415         {0x000e00ff, 0x00000002},
 416         {0000000000, 0x00000006},
 417         {0x0000008f, 0x00000018},
 418         {0x0000005b, 0x00000004},
 419         {0x000380e6, 0x00000002},
 420         {0x040025c5, 0x00000002},
 421         {0x00007576, 0x00000002},
 422         {0x00065000, 0x00000002},
 423         {0x00009000, 0x00000002},
 424         {0x00041000, 0x00000002},
 425         {0x0c00350e, 0x00000002},
 426         {0x00049000, 0x00000002},
 427         {0x00051000, 0x00000002},
 428         {0x01e785f8, 0x00000002},
 429         {0x00200000, 0x00000002},
 430         {0x0060007e, 0x0000000c},
 431         {0x00007563, 0x00000002},
 432         {0x006075f0, 0x00000021},
 433         {0x20007073, 0x00000004},
 434         {0x00005073, 0x00000004},
 435         {0x000380e6, 0x00000002},
 436         {0x040025c5, 0x00000002},
 437         {0x00007576, 0x00000002},
 438         {0x00007577, 0x00000002},
 439         {0x0000750e, 0x00000002},
 440         {0x0000750f, 0x00000002},
 441         {0x00a05000, 0x00000002},
 442         {0x00600083, 0x0000000c},
 443         {0x006075f0, 0x00000021},
 444         {0x000075f8, 0x00000002},
 445         {0x00000083, 0x00000004},
 446         {0x000a750e, 0x00000002},
 447         {0x000380e6, 0x00000002},
 448         {0x040025c5, 0x00000002},
 449         {0x0020750f, 0x00000002},
 450         {0x00600086, 0x00000004},
 451         {0x00007570, 0x00000002},
 452         {0x00007571, 0x00000002},
 453         {0x00007572, 0x00000006},
 454         {0x000380e6, 0x00000002},
 455         {0x040025c5, 0x00000002},
 456         {0x00005000, 0x00000002},
 457         {0x00a05000, 0x00000002},
 458         {0x00007568, 0x00000002},
 459         {0x00061000, 0x00000002},
 460         {0x00000095, 0x0000000c},
 461         {0x00058000, 0x00000002},
 462         {0x0c607562, 0x00000002},
 463         {0x00000097, 0x00000004},
 464         {0x000380e6, 0x00000002},
 465         {0x040025c5, 0x00000002},
 466         {0x00600096, 0x00000004},
 467         {0x400070e5, 0000000000},
 468         {0x000380e6, 0x00000002},
 469         {0x040025c5, 0x00000002},
 470         {0x000380e5, 0x00000002},
 471         {0x000000a8, 0x0000001c},
 472         {0x000650aa, 0x00000018},
 473         {0x040025bb, 0x00000002},
 474         {0x000610ab, 0x00000018},
 475         {0x040075bc, 0000000000},
 476         {0x000075bb, 0x00000002},
 477         {0x000075bc, 0000000000},
 478         {0x00090000, 0x00000006},
 479         {0x00090000, 0x00000002},
 480         {0x000d8002, 0x00000006},
 481         {0x00007832, 0x00000002},
 482         {0x00005000, 0x00000002},
 483         {0x000380e7, 0x00000002},
 484         {0x04002c97, 0x00000002},
 485         {0x00007820, 0x00000002},
 486         {0x00007821, 0x00000002},
 487         {0x00007800, 0000000000},
 488         {0x01200000, 0x00000002},
 489         {0x20077000, 0x00000002},
 490         {0x01200000, 0x00000002},
 491         {0x20007000, 0x00000002},
 492         {0x00061000, 0x00000002},
 493         {0x0120751b, 0x00000002},
 494         {0x8040750a, 0x00000002},
 495         {0x8040750b, 0x00000002},
 496         {0x00110000, 0x00000002},
 497         {0x000380e5, 0x00000002},
 498         {0x000000c6, 0x0000001c},
 499         {0x000610ab, 0x00000018},
 500         {0x844075bd, 0x00000002},
 501         {0x000610aa, 0x00000018},
 502         {0x840075bb, 0x00000002},
 503         {0x000610ab, 0x00000018},
 504         {0x844075bc, 0x00000002},
 505         {0x000000c9, 0x00000004},
 506         {0x804075bd, 0x00000002},
 507         {0x800075bb, 0x00000002},
 508         {0x804075bc, 0x00000002},
 509         {0x00108000, 0x00000002},
 510         {0x01400000, 0x00000002},
 511         {0x006000cd, 0x0000000c},
 512         {0x20c07000, 0x00000020},
 513         {0x000000cf, 0x00000012},
 514         {0x00800000, 0x00000006},
 515         {0x0080751d, 0x00000006},
 516         {0000000000, 0000000000},
 517         {0x0000775c, 0x00000002},
 518         {0x00a05000, 0x00000002},
 519         {0x00661000, 0x00000002},
 520         {0x0460275d, 0x00000020},
 521         {0x00004000, 0000000000},
 522         {0x01e00830, 0x00000002},
 523         {0x21007000, 0000000000},
 524         {0x6464614d, 0000000000},
 525         {0x69687420, 0000000000},
 526         {0x00000073, 0000000000},
 527         {0000000000, 0000000000},
 528         {0x00005000, 0x00000002},
 529         {0x000380d0, 0x00000002},
 530         {0x040025e0, 0x00000002},
 531         {0x000075e1, 0000000000},
 532         {0x00000001, 0000000000},
 533         {0x000380e0, 0x00000002},
 534         {0x04002394, 0x00000002},
 535         {0x00005000, 0000000000},
 536         {0000000000, 0000000000},
 537         {0000000000, 0000000000},
 538         {0x00000008, 0000000000},
 539         {0x00000004, 0000000000},
 540         {0000000000, 0000000000},
 541         {0000000000, 0000000000},
 542         {0000000000, 0000000000},
 543         {0000000000, 0000000000},
 544         {0000000000, 0000000000},
 545         {0000000000, 0000000000},
 546         {0000000000, 0000000000},
 547         {0000000000, 0000000000},
 548         {0000000000, 0000000000},
 549         {0000000000, 0000000000},
 550         {0000000000, 0000000000},
 551         {0000000000, 0000000000},
 552         {0000000000, 0000000000},
 553         {0000000000, 0000000000},
 554         {0000000000, 0000000000},
 555         {0000000000, 0000000000},
 556         {0000000000, 0000000000},
 557         {0000000000, 0000000000},
 558         {0000000000, 0000000000},
 559         {0000000000, 0000000000},
 560         {0000000000, 0000000000},
 561         {0000000000, 0000000000},
 562         {0000000000, 0000000000},
 563         {0000000000, 0000000000},
 564 };
 565 
 566 static const u32 R300_cp_microcode[][2] = {
 567         { 0x4200e000, 0000000000 },
 568         { 0x4000e000, 0000000000 },
 569         { 0x000000af, 0x00000008 },
 570         { 0x000000b3, 0x00000008 },
 571         { 0x6c5a504f, 0000000000 },
 572         { 0x4f4f497a, 0000000000 },
 573         { 0x5a578288, 0000000000 },
 574         { 0x4f91906a, 0000000000 },
 575         { 0x4f4f4f4f, 0000000000 },
 576         { 0x4fe24f44, 0000000000 },
 577         { 0x4f9c9c9c, 0000000000 },
 578         { 0xdc4f4fde, 0000000000 },
 579         { 0xa1cd4f4f, 0000000000 },
 580         { 0xd29d9d9d, 0000000000 },
 581         { 0x4f0f9fd7, 0000000000 },
 582         { 0x000ca000, 0x00000004 },
 583         { 0x000d0012, 0x00000038 },
 584         { 0x0000e8b4, 0x00000004 },
 585         { 0x000d0014, 0x00000038 },
 586         { 0x0000e8b6, 0x00000004 },
 587         { 0x000d0016, 0x00000038 },
 588         { 0x0000e854, 0x00000004 },
 589         { 0x000d0018, 0x00000038 },
 590         { 0x0000e855, 0x00000004 },
 591         { 0x000d001a, 0x00000038 },
 592         { 0x0000e856, 0x00000004 },
 593         { 0x000d001c, 0x00000038 },
 594         { 0x0000e857, 0x00000004 },
 595         { 0x000d001e, 0x00000038 },
 596         { 0x0000e824, 0x00000004 },
 597         { 0x000d0020, 0x00000038 },
 598         { 0x0000e825, 0x00000004 },
 599         { 0x000d0022, 0x00000038 },
 600         { 0x0000e830, 0x00000004 },
 601         { 0x000d0024, 0x00000038 },
 602         { 0x0000f0c0, 0x00000004 },
 603         { 0x000d0026, 0x00000038 },
 604         { 0x0000f0c1, 0x00000004 },
 605         { 0x000d0028, 0x00000038 },
 606         { 0x0000f041, 0x00000004 },
 607         { 0x000d002a, 0x00000038 },
 608         { 0x0000f184, 0x00000004 },
 609         { 0x000d002c, 0x00000038 },
 610         { 0x0000f185, 0x00000004 },
 611         { 0x000d002e, 0x00000038 },
 612         { 0x0000f186, 0x00000004 },
 613         { 0x000d0030, 0x00000038 },
 614         { 0x0000f187, 0x00000004 },
 615         { 0x000d0032, 0x00000038 },
 616         { 0x0000f180, 0x00000004 },
 617         { 0x000d0034, 0x00000038 },
 618         { 0x0000f393, 0x00000004 },
 619         { 0x000d0036, 0x00000038 },
 620         { 0x0000f38a, 0x00000004 },
 621         { 0x000d0038, 0x00000038 },
 622         { 0x0000f38e, 0x00000004 },
 623         { 0x0000e821, 0x00000004 },
 624         { 0x0140a000, 0x00000004 },
 625         { 0x00000043, 0x00000018 },
 626         { 0x00cce800, 0x00000004 },
 627         { 0x001b0001, 0x00000004 },
 628         { 0x08004800, 0x00000004 },
 629         { 0x001b0001, 0x00000004 },
 630         { 0x08004800, 0x00000004 },
 631         { 0x001b0001, 0x00000004 },
 632         { 0x08004800, 0x00000004 },
 633         { 0x0000003a, 0x00000008 },
 634         { 0x0000a000, 0000000000 },
 635         { 0x02c0a000, 0x00000004 },
 636         { 0x000ca000, 0x00000004 },
 637         { 0x00130000, 0x00000004 },
 638         { 0x000c2000, 0x00000004 },
 639         { 0xc980c045, 0x00000008 },
 640         { 0x2000451d, 0x00000004 },
 641         { 0x0000e580, 0x00000004 },
 642         { 0x000ce581, 0x00000004 },
 643         { 0x08004580, 0x00000004 },
 644         { 0x000ce581, 0x00000004 },
 645         { 0x0000004c, 0x00000008 },
 646         { 0x0000a000, 0000000000 },
 647         { 0x000c2000, 0x00000004 },
 648         { 0x0000e50e, 0x00000004 },
 649         { 0x00032000, 0x00000004 },
 650         { 0x00022056, 0x00000028 },
 651         { 0x00000056, 0x00000024 },
 652         { 0x0800450f, 0x00000004 },
 653         { 0x0000a050, 0x00000008 },
 654         { 0x0000e565, 0x00000004 },
 655         { 0x0000e566, 0x00000004 },
 656         { 0x00000057, 0x00000008 },
 657         { 0x03cca5b4, 0x00000004 },
 658         { 0x05432000, 0x00000004 },
 659         { 0x00022000, 0x00000004 },
 660         { 0x4ccce063, 0x00000030 },
 661         { 0x08274565, 0x00000004 },
 662         { 0x00000063, 0x00000030 },
 663         { 0x08004564, 0x00000004 },
 664         { 0x0000e566, 0x00000004 },
 665         { 0x0000005a, 0x00000008 },
 666         { 0x00802066, 0x00000010 },
 667         { 0x00202000, 0x00000004 },
 668         { 0x001b00ff, 0x00000004 },
 669         { 0x01000069, 0x00000010 },
 670         { 0x001f2000, 0x00000004 },
 671         { 0x001c00ff, 0x00000004 },
 672         { 0000000000, 0x0000000c },
 673         { 0x00000085, 0x00000030 },
 674         { 0x0000005a, 0x00000008 },
 675         { 0x0000e576, 0x00000004 },
 676         { 0x000ca000, 0x00000004 },
 677         { 0x00012000, 0x00000004 },
 678         { 0x00082000, 0x00000004 },
 679         { 0x1800650e, 0x00000004 },
 680         { 0x00092000, 0x00000004 },
 681         { 0x000a2000, 0x00000004 },
 682         { 0x000f0000, 0x00000004 },
 683         { 0x00400000, 0x00000004 },
 684         { 0x00000079, 0x00000018 },
 685         { 0x0000e563, 0x00000004 },
 686         { 0x00c0e5f9, 0x000000c2 },
 687         { 0x0000006e, 0x00000008 },
 688         { 0x0000a06e, 0x00000008 },
 689         { 0x0000e576, 0x00000004 },
 690         { 0x0000e577, 0x00000004 },
 691         { 0x0000e50e, 0x00000004 },
 692         { 0x0000e50f, 0x00000004 },
 693         { 0x0140a000, 0x00000004 },
 694         { 0x0000007c, 0x00000018 },
 695         { 0x00c0e5f9, 0x000000c2 },
 696         { 0x0000007c, 0x00000008 },
 697         { 0x0014e50e, 0x00000004 },
 698         { 0x0040e50f, 0x00000004 },
 699         { 0x00c0007f, 0x00000008 },
 700         { 0x0000e570, 0x00000004 },
 701         { 0x0000e571, 0x00000004 },
 702         { 0x0000e572, 0x0000000c },
 703         { 0x0000a000, 0x00000004 },
 704         { 0x0140a000, 0x00000004 },
 705         { 0x0000e568, 0x00000004 },
 706         { 0x000c2000, 0x00000004 },
 707         { 0x00000089, 0x00000018 },
 708         { 0x000b0000, 0x00000004 },
 709         { 0x18c0e562, 0x00000004 },
 710         { 0x0000008b, 0x00000008 },
 711         { 0x00c0008a, 0x00000008 },
 712         { 0x000700e4, 0x00000004 },
 713         { 0x00000097, 0x00000038 },
 714         { 0x000ca099, 0x00000030 },
 715         { 0x080045bb, 0x00000004 },
 716         { 0x000c209a, 0x00000030 },
 717         { 0x0800e5bc, 0000000000 },
 718         { 0x0000e5bb, 0x00000004 },
 719         { 0x0000e5bc, 0000000000 },
 720         { 0x00120000, 0x0000000c },
 721         { 0x00120000, 0x00000004 },
 722         { 0x001b0002, 0x0000000c },
 723         { 0x0000a000, 0x00000004 },
 724         { 0x0000e821, 0x00000004 },
 725         { 0x0000e800, 0000000000 },
 726         { 0x0000e821, 0x00000004 },
 727         { 0x0000e82e, 0000000000 },
 728         { 0x02cca000, 0x00000004 },
 729         { 0x00140000, 0x00000004 },
 730         { 0x000ce1cc, 0x00000004 },
 731         { 0x050de1cd, 0x00000004 },
 732         { 0x000000a7, 0x00000020 },
 733         { 0x4200e000, 0000000000 },
 734         { 0x000000ae, 0x00000038 },
 735         { 0x000ca000, 0x00000004 },
 736         { 0x00140000, 0x00000004 },
 737         { 0x000c2000, 0x00000004 },
 738         { 0x00160000, 0x00000004 },
 739         { 0x700ce000, 0x00000004 },
 740         { 0x001400aa, 0x00000008 },
 741         { 0x4000e000, 0000000000 },
 742         { 0x02400000, 0x00000004 },
 743         { 0x400ee000, 0x00000004 },
 744         { 0x02400000, 0x00000004 },
 745         { 0x4000e000, 0000000000 },
 746         { 0x000c2000, 0x00000004 },
 747         { 0x0240e51b, 0x00000004 },
 748         { 0x0080e50a, 0x00000005 },
 749         { 0x0080e50b, 0x00000005 },
 750         { 0x00220000, 0x00000004 },
 751         { 0x000700e4, 0x00000004 },
 752         { 0x000000c1, 0x00000038 },
 753         { 0x000c209a, 0x00000030 },
 754         { 0x0880e5bd, 0x00000005 },
 755         { 0x000c2099, 0x00000030 },
 756         { 0x0800e5bb, 0x00000005 },
 757         { 0x000c209a, 0x00000030 },
 758         { 0x0880e5bc, 0x00000005 },
 759         { 0x000000c4, 0x00000008 },
 760         { 0x0080e5bd, 0x00000005 },
 761         { 0x0000e5bb, 0x00000005 },
 762         { 0x0080e5bc, 0x00000005 },
 763         { 0x00210000, 0x00000004 },
 764         { 0x02800000, 0x00000004 },
 765         { 0x00c000c8, 0x00000018 },
 766         { 0x4180e000, 0x00000040 },
 767         { 0x000000ca, 0x00000024 },
 768         { 0x01000000, 0x0000000c },
 769         { 0x0100e51d, 0x0000000c },
 770         { 0x000045bb, 0x00000004 },
 771         { 0x000080c4, 0x00000008 },
 772         { 0x0000f3ce, 0x00000004 },
 773         { 0x0140a000, 0x00000004 },
 774         { 0x00cc2000, 0x00000004 },
 775         { 0x08c053cf, 0x00000040 },
 776         { 0x00008000, 0000000000 },
 777         { 0x0000f3d2, 0x00000004 },
 778         { 0x0140a000, 0x00000004 },
 779         { 0x00cc2000, 0x00000004 },
 780         { 0x08c053d3, 0x00000040 },
 781         { 0x00008000, 0000000000 },
 782         { 0x0000f39d, 0x00000004 },
 783         { 0x0140a000, 0x00000004 },
 784         { 0x00cc2000, 0x00000004 },
 785         { 0x08c0539e, 0x00000040 },
 786         { 0x00008000, 0000000000 },
 787         { 0x03c00830, 0x00000004 },
 788         { 0x4200e000, 0000000000 },
 789         { 0x0000a000, 0x00000004 },
 790         { 0x200045e0, 0x00000004 },
 791         { 0x0000e5e1, 0000000000 },
 792         { 0x00000001, 0000000000 },
 793         { 0x000700e1, 0x00000004 },
 794         { 0x0800e394, 0000000000 },
 795         { 0000000000, 0000000000 },
 796         { 0000000000, 0000000000 },
 797         { 0000000000, 0000000000 },
 798         { 0000000000, 0000000000 },
 799         { 0000000000, 0000000000 },
 800         { 0000000000, 0000000000 },
 801         { 0000000000, 0000000000 },
 802         { 0000000000, 0000000000 },
 803         { 0000000000, 0000000000 },
 804         { 0000000000, 0000000000 },
 805         { 0000000000, 0000000000 },
 806         { 0000000000, 0000000000 },
 807         { 0000000000, 0000000000 },
 808         { 0000000000, 0000000000 },
 809         { 0000000000, 0000000000 },
 810         { 0000000000, 0000000000 },
 811         { 0000000000, 0000000000 },
 812         { 0000000000, 0000000000 },
 813         { 0000000000, 0000000000 },
 814         { 0000000000, 0000000000 },
 815         { 0000000000, 0000000000 },
 816         { 0000000000, 0000000000 },
 817         { 0000000000, 0000000000 },
 818         { 0000000000, 0000000000 },
 819         { 0000000000, 0000000000 },
 820         { 0000000000, 0000000000 },
 821         { 0000000000, 0000000000 },
 822         { 0000000000, 0000000000 },
 823 };
 824 
 825 static int RADEON_READ_PLL(drm_device_t *dev, int addr)
 826 {
 827         drm_radeon_private_t *dev_priv = dev->dev_private;
 828 
 829         RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
 830         return (RADEON_READ(RADEON_CLOCK_CNTL_DATA));
 831 }
 832 
 833 static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
 834 {
 835         RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
 836         return (RADEON_READ(RADEON_PCIE_DATA));
 837 }
 838 
 839 #if RADEON_FIFO_DEBUG
 840 static void radeon_status(drm_radeon_private_t *dev_priv)
 841 {
 842         cmn_err(CE_NOTE, "RBBM_STATUS = 0x%08x\n",
 843             (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
 844         cmn_err(CE_NOTE, "CP_RB_RTPR = 0x%08x\n",
 845             (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
 846         cmn_err(CE_NOTE, "CP_RB_WTPR = 0x%08x\n",
 847             (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
 848         cmn_err(CE_NOTE, "AIC_CNTL = 0x%08x\n",
 849             (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
 850         cmn_err(CE_NOTE, "AIC_STAT = 0x%08x\n",
 851             (unsigned int)RADEON_READ(RADEON_AIC_STAT));
 852         cmn_err(CE_NOTE, "AIC_PT_BASE = 0x%08x\n",
 853             (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
 854         cmn_err(CE_NOTE, "TLB_ADDR = 0x%08x\n",
 855             (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
 856         cmn_err(CE_NOTE, "TLB_DATA = 0x%08x\n",
 857             (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
 858 }
 859 #endif
 860 
 861 /*
 862  * Engine, FIFO control
 863  */
 864 
 865 static int radeon_do_pixcache_flush(drm_radeon_private_t *dev_priv)
 866 {
 867         u32 tmp;
 868         int i;
 869 
 870         dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 871 
 872         tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
 873         tmp |= RADEON_RB3D_DC_FLUSH_ALL;
 874         RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
 875 
 876         for (i = 0; i < dev_priv->usec_timeout; i++) {
 877                 if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) &
 878                     RADEON_RB3D_DC_BUSY)) {
 879                         return (0);
 880                 }
 881                 DRM_UDELAY(1);
 882         }
 883 
 884 #if RADEON_FIFO_DEBUG
 885         DRM_ERROR("failed!\n");
 886         radeon_status(dev_priv);
 887 #endif
 888         return (EBUSY);
 889 }
 890 
 891 static int radeon_do_wait_for_fifo(drm_radeon_private_t *dev_priv, int entries)
 892 {
 893         int i;
 894 
 895         dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 896 
 897         for (i = 0; i < dev_priv->usec_timeout; i++) {
 898                 int slots = (RADEON_READ(RADEON_RBBM_STATUS) &
 899                     RADEON_RBBM_FIFOCNT_MASK);
 900                 if (slots >= entries)
 901                         return (0);
 902                 DRM_UDELAY(1);
 903         }
 904 
 905 
 906         DRM_ERROR("radeon_do_wait_for_fifo: failed timeout=%d",
 907             dev_priv->usec_timeout);
 908 #if RADEON_FIFO_DEBUG
 909         radeon_status(dev_priv);
 910 #endif
 911         return (EBUSY);
 912 }
 913 
 914 static int radeon_do_wait_for_idle(drm_radeon_private_t *dev_priv)
 915 {
 916         int i, ret;
 917 
 918         dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 919 
 920         ret = radeon_do_wait_for_fifo(dev_priv, 64);
 921         if (ret)
 922                 return (ret);
 923 
 924         for (i = 0; i < dev_priv->usec_timeout; i++) {
 925                 if (!(RADEON_READ(RADEON_RBBM_STATUS) &
 926                     RADEON_RBBM_ACTIVE)) {
 927                         (void) radeon_do_pixcache_flush(dev_priv);
 928                         return (0);
 929                 }
 930                 DRM_UDELAY(1);
 931         }
 932 
 933         DRM_ERROR("radeon_do_wait_for_idle: failed timeout=%d",
 934             dev_priv->usec_timeout);
 935 
 936 #if RADEON_FIFO_DEBUG
 937         radeon_status(dev_priv);
 938 #endif
 939         return (EBUSY);
 940 }
 941 
 942 /*
 943  * CP control, initialization
 944  */
 945 
 946 /* Load the microcode for the CP */
 947 static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
 948 {
 949         int i;
 950 
 951         (void) radeon_do_wait_for_idle(dev_priv);
 952 
 953         RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
 954 
 955         if (dev_priv->microcode_version == UCODE_R200) {
 956                 DRM_INFO("Loading R200 Microcode\n");
 957                 for (i = 0; i < 256; i++) {
 958                         RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
 959                             R200_cp_microcode[i][1]);
 960                         RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
 961                             R200_cp_microcode[i][0]);
 962                 }
 963         } else if (dev_priv->microcode_version == UCODE_R300) {
 964                 DRM_INFO("Loading R300 Microcode\n");
 965                 for (i = 0; i < 256; i++) {
 966                         RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
 967                             R300_cp_microcode[i][1]);
 968                         RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
 969                             R300_cp_microcode[i][0]);
 970                 }
 971         } else {
 972                 for (i = 0; i < 256; i++) {
 973                         RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
 974                             radeon_cp_microcode[i][1]);
 975                         RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
 976                             radeon_cp_microcode[i][0]);
 977                 }
 978         }
 979 }
 980 
 981 /*
 982  * Flush any pending commands to the CP.  This should only be used just
 983  * prior to a wait for idle, as it informs the engine that the command
 984  * stream is ending.
 985  */
 986 /*ARGSUSED*/
 987 static void radeon_do_cp_flush(drm_radeon_private_t *dev_priv)
 988 {
 989         DRM_DEBUG("\n");
 990 
 991 #if 0
 992         u32 tmp;
 993 
 994         tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
 995         RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
 996 #endif
 997 }
 998 
 999 /* Wait for the CP to go idle. */
1000 int
1001 radeon_do_cp_idle(drm_radeon_private_t *dev_priv)
1002 {
1003         RING_LOCALS;
1004 
1005         BEGIN_RING(6);
1006 
1007         RADEON_PURGE_CACHE();
1008         RADEON_PURGE_ZCACHE();
1009         RADEON_WAIT_UNTIL_IDLE();
1010 
1011         ADVANCE_RING();
1012         COMMIT_RING();
1013 
1014         return (radeon_do_wait_for_idle(dev_priv));
1015 }
1016 
1017 /* Start the Command Processor. */
1018 static void radeon_do_cp_start(drm_radeon_private_t *dev_priv)
1019 {
1020         RING_LOCALS;
1021 
1022         (void) radeon_do_wait_for_idle(dev_priv);
1023 
1024         RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
1025 
1026         dev_priv->cp_running = 1;
1027 
1028         BEGIN_RING(6);
1029 
1030         RADEON_PURGE_CACHE();
1031         RADEON_PURGE_ZCACHE();
1032         RADEON_WAIT_UNTIL_IDLE();
1033 
1034         ADVANCE_RING();
1035         COMMIT_RING();
1036 }
1037 
1038 /*
1039  * Reset the Command Processor.  This will not flush any pending
1040  * commands, so you must wait for the CP command stream to complete
1041  * before calling this routine.
1042  */
1043 static void radeon_do_cp_reset(drm_radeon_private_t *dev_priv)
1044 {
1045         u32 cur_read_ptr;
1046         DRM_DEBUG("\n");
1047 
1048         cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
1049         RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
1050         SET_RING_HEAD(dev_priv, cur_read_ptr);
1051         dev_priv->ring.tail = cur_read_ptr;
1052 }
1053 
1054 /*
1055  * Stop the Command Processor.  This will not flush any pending
1056  * commands, so you must flush the command stream and wait for the CP
1057  * to go idle before calling this routine.
1058  */
1059 static void radeon_do_cp_stop(drm_radeon_private_t *dev_priv)
1060 {
1061         DRM_DEBUG("\n");
1062 
1063         RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
1064 
1065         dev_priv->cp_running = 0;
1066 }
1067 
1068 /* Reset the engine.  This will stop the CP if it is running. */
1069 static int radeon_do_engine_reset(drm_device_t *dev)
1070 {
1071         drm_radeon_private_t *dev_priv = dev->dev_private;
1072         u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
1073         DRM_DEBUG("\n");
1074 
1075         (void) radeon_do_pixcache_flush(dev_priv);
1076 
1077         clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
1078         mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
1079 
1080         RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
1081             RADEON_FORCEON_MCLKA |
1082             RADEON_FORCEON_MCLKB |
1083             RADEON_FORCEON_YCLKA |
1084             RADEON_FORCEON_YCLKB |
1085             RADEON_FORCEON_MC |
1086             RADEON_FORCEON_AIC));
1087 
1088         rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
1089 
1090         RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
1091             RADEON_SOFT_RESET_CP |
1092             RADEON_SOFT_RESET_HI |
1093             RADEON_SOFT_RESET_SE |
1094             RADEON_SOFT_RESET_RE |
1095             RADEON_SOFT_RESET_PP |
1096             RADEON_SOFT_RESET_E2 |
1097             RADEON_SOFT_RESET_RB));
1098         (void) RADEON_READ(RADEON_RBBM_SOFT_RESET);
1099         RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
1100             ~(RADEON_SOFT_RESET_CP |
1101             RADEON_SOFT_RESET_HI |
1102             RADEON_SOFT_RESET_SE |
1103             RADEON_SOFT_RESET_RE |
1104             RADEON_SOFT_RESET_PP |
1105             RADEON_SOFT_RESET_E2 |
1106             RADEON_SOFT_RESET_RB)));
1107         (void) RADEON_READ(RADEON_RBBM_SOFT_RESET);
1108 
1109         RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
1110         RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
1111         RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
1112 
1113         /* Reset the CP ring */
1114         radeon_do_cp_reset(dev_priv);
1115 
1116         /* The CP is no longer running after an engine reset */
1117         dev_priv->cp_running = 0;
1118 
1119         /* Reset any pending vertex, indirect buffers */
1120         radeon_freelist_reset(dev);
1121 
1122         return (0);
1123 }
1124 
1125 static void
1126 radeon_cp_init_ring_buffer(drm_device_t *dev, drm_radeon_private_t *dev_priv)
1127 {
1128         u32 ring_start, cur_read_ptr;
1129         u32 tmp;
1130 
1131         /*
1132          * Initialize the memory controller. With new memory map, the fb
1133          * location is not changed, it should have been properly initialized
1134          * already. Part of the problem is that the code below is bogus,
1135          * assuming the GART is always appended to the fb which is not
1136          * necessarily the case
1137          */
1138         if (!dev_priv->new_memmap)
1139                 RADEON_WRITE(RADEON_MC_FB_LOCATION,
1140                     ((dev_priv->gart_vm_start - 1) & 0xffff0000) |
1141                     (dev_priv->fb_location >> 16));
1142 
1143 #if __OS_HAS_AGP
1144         if (dev_priv->flags & RADEON_IS_AGP) {
1145                 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
1146                 RADEON_WRITE(RADEON_MC_AGP_LOCATION,
1147                     (((dev_priv->gart_vm_start - 1 +
1148                     dev_priv->gart_size) & 0xffff0000) |
1149                     (dev_priv->gart_vm_start >> 16)));
1150 
1151                 ring_start = dev_priv->cp_ring->offset -
1152                     dev->agp->base + dev_priv->gart_vm_start;
1153         } else
1154 #endif
1155                 ring_start = (dev_priv->cp_ring->offset -
1156                     (unsigned long)dev->sg->virtual +
1157                     dev_priv->gart_vm_start);
1158 
1159         RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
1160 
1161         /* Set the write pointer delay */
1162         RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
1163 
1164         /* Initialize the ring buffer's read and write pointers */
1165         cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
1166         RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
1167         SET_RING_HEAD(dev_priv, cur_read_ptr);
1168         dev_priv->ring.tail = cur_read_ptr;
1169 
1170 #if __OS_HAS_AGP
1171         if (dev_priv->flags & RADEON_IS_AGP) {
1172                 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
1173                     dev_priv->ring_rptr->offset -
1174                     dev->agp->base + dev_priv->gart_vm_start);
1175         } else
1176 #endif
1177         {
1178                 drm_sg_mem_t *entry = dev->sg;
1179                 unsigned long tmp_ofs, page_ofs;
1180 
1181                 tmp_ofs = dev_priv->ring_rptr->offset -
1182                     (unsigned long)dev->sg->virtual;
1183                 page_ofs = tmp_ofs >> PAGE_SHIFT;
1184 
1185                 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
1186                 DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
1187                     (unsigned long)entry->busaddr[page_ofs],
1188                     entry->handle + tmp_ofs);
1189         }
1190 
1191         /* Set ring buffer size */
1192 #ifdef __BIG_ENDIAN
1193         RADEON_WRITE(RADEON_CP_RB_CNTL,
1194             dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
1195 #else
1196         RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
1197 #endif
1198 
1199         /* Start with assuming that writeback doesn't work */
1200         dev_priv->writeback_works = 0;
1201 
1202         /*
1203          * Initialize the scratch register pointer.  This will cause
1204          * the scratch register values to be written out to memory
1205          * whenever they are updated.
1206          *
1207          * We simply put this behind the ring read pointer, this works
1208          * with PCI GART as well as (whatever kind of) AGP GART
1209          */
1210         RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
1211             + RADEON_SCRATCH_REG_OFFSET);
1212 
1213         dev_priv->scratch = ((__volatile__ u32 *)
1214             dev_priv->ring_rptr->handle +
1215             (RADEON_SCRATCH_REG_OFFSET / sizeof (u32)));
1216 
1217         RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
1218 
1219         /* Turn on bus mastering */
1220         tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
1221         RADEON_WRITE(RADEON_BUS_CNTL, tmp);
1222 
1223         dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
1224         RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
1225 
1226         dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
1227         RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
1228             dev_priv->sarea_priv->last_dispatch);
1229 
1230         dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
1231         RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
1232 
1233         (void) radeon_do_wait_for_idle(dev_priv);
1234 
1235         /* Sync everything up */
1236         RADEON_WRITE(RADEON_ISYNC_CNTL,
1237             (RADEON_ISYNC_ANY2D_IDLE3D |
1238             RADEON_ISYNC_ANY3D_IDLE2D |
1239             RADEON_ISYNC_WAIT_IDLEGUI |
1240             RADEON_ISYNC_CPSCRATCH_IDLEGUI));
1241 
1242 }
1243 
1244 static void radeon_test_writeback(drm_radeon_private_t *dev_priv)
1245 {
1246 #if 0
1247         u32 tmp;
1248 
1249         /*
1250          * Writeback doesn't seem to work everywhere, test it here and possibly
1251          * enable it if it appears to work
1252          */
1253         DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
1254         RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
1255 
1256         for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
1257                 if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
1258                     0xdeadbeef)
1259                         break;
1260                 DRM_UDELAY(1);
1261         }
1262 
1263         tmp = dev_priv->usec_timeout;
1264 
1265         if (tmp < dev_priv->usec_timeout) {
1266                 dev_priv->writeback_works = 1;
1267                 DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
1268         } else {
1269                 dev_priv->writeback_works = 0;
1270                 DRM_INFO("writeback test failed\n");
1271         }
1272         if (radeon_no_wb == 1) {
1273                 dev_priv->writeback_works = 0;
1274                 DRM_INFO("writeback forced off\n");
1275         }
1276 #else
1277         /*
1278          * Writeback doesn't work everywhere. And the timeout is so long
1279          * so Xserver needs more time to start itself. But dtlogin doesn't
1280          * want to wait for the timeout, and it just stops Xserver and
1281          * restart it again. As a result, Xserver cannot start. So, we
1282          * just ignore writeback here.
1283          */
1284         dev_priv->writeback_works = 0;
1285 #endif
1286 
1287         if (!dev_priv->writeback_works) {
1288                 /*
1289                  * Disable writeback to avoid unnecessary bus master
1290                  * transfers
1291                  */
1292                 RADEON_WRITE(RADEON_CP_RB_CNTL,
1293                     RADEON_READ(RADEON_CP_RB_CNTL) | RADEON_RB_NO_UPDATE);
1294                 RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
1295         }
1296 
1297 }
1298 
1299 /* Enable or disable PCI-E GART on the chip */
1300 static void radeon_set_pciegart(drm_radeon_private_t *dev_priv, int on)
1301 {
1302         u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
1303         if (on) {
1304 
1305                 DRM_DEBUG("programming pcie %08X %08lX %08X\n",
1306                     dev_priv->gart_vm_start,
1307                     (long)dev_priv->gart_info.bus_addr,
1308                     dev_priv->gart_size);
1309                 RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
1310                     dev_priv->gart_vm_start);
1311                 RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
1312                     dev_priv->gart_info.bus_addr);
1313                 RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
1314                     dev_priv->gart_vm_start);
1315                 RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
1316                     dev_priv->gart_vm_start + dev_priv->gart_size - 1);
1317 
1318                 RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);       /* ?? */
1319 
1320                 RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
1321                     RADEON_PCIE_TX_GART_EN);
1322         } else {
1323                 RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
1324                     tmp & ~RADEON_PCIE_TX_GART_EN);
1325         }
1326 }
1327 
1328 /* Enable or disable PCI GART on the chip */
1329 static void radeon_set_pcigart(drm_radeon_private_t *dev_priv, int on)
1330 {
1331         u32 tmp;
1332 
1333         if (dev_priv->flags & RADEON_IS_PCIE) {
1334                 radeon_set_pciegart(dev_priv, on);
1335                 return;
1336         }
1337 
1338         tmp = RADEON_READ(RADEON_AIC_CNTL);
1339 
1340         if (on) {
1341                 RADEON_WRITE(RADEON_AIC_CNTL,
1342                     tmp | RADEON_PCIGART_TRANSLATE_EN);
1343 
1344                 /* set PCI GART page-table base address */
1345                 RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
1346 
1347                 /* set address range for PCI address translate */
1348                 RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
1349                 RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start +
1350                     dev_priv->gart_size - 1);
1351 
1352                 /* Turn off AGP aperture -- is this required for PCI GART?  */
1353                 RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);       /* ?? */
1354                 RADEON_WRITE(RADEON_AGP_COMMAND, 0);    /* clear AGP_COMMAND */
1355         } else {
1356                 RADEON_WRITE(RADEON_AIC_CNTL,
1357                     tmp & ~RADEON_PCIGART_TRANSLATE_EN);
1358         }
1359 }
1360 
1361 static int radeon_do_init_cp(drm_device_t *dev, drm_radeon_init_t *init)
1362 {
1363         drm_radeon_private_t *dev_priv = dev->dev_private;
1364 
1365         /* if we require new memory map but we don't have it fail */
1366         if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
1367                 DRM_ERROR("Cannot initialise DRM on this card\n"
1368                     "This card requires a new X.org DDX for 3D\n");
1369                 (void) radeon_do_cleanup_cp(dev);
1370                 return (EINVAL);
1371         }
1372 
1373         if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
1374                 DRM_DEBUG("Forcing AGP card to PCI mode\n");
1375                 dev_priv->flags &= ~RADEON_IS_AGP;
1376         } else if (!(dev_priv->flags &
1377             (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) &&
1378             !init->is_pci) {
1379                 DRM_DEBUG("Restoring AGP flag\n");
1380                 dev_priv->flags |= RADEON_IS_AGP;
1381         }
1382 
1383         if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
1384                 DRM_ERROR("PCI GART memory not allocated!\n");
1385                 (void) radeon_do_cleanup_cp(dev);
1386                 return (EINVAL);
1387         }
1388 
1389         dev_priv->usec_timeout = init->usec_timeout;
1390         if (dev_priv->usec_timeout < 1 ||
1391             dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
1392                 (void) radeon_do_cleanup_cp(dev);
1393                 return (EINVAL);
1394         }
1395 
1396         switch (init->func) {
1397         case RADEON_INIT_R200_CP:
1398                 dev_priv->microcode_version = UCODE_R200;
1399                 break;
1400         case RADEON_INIT_R300_CP:
1401                 dev_priv->microcode_version = UCODE_R300;
1402                 break;
1403         default:
1404                 dev_priv->microcode_version = UCODE_R100;
1405         }
1406 
1407         dev_priv->do_boxes = 0;
1408         dev_priv->cp_mode = init->cp_mode;
1409 
1410         /*
1411          * We don't support anything other than bus-mastering ring mode,
1412          * but the ring can be in either AGP or PCI space for the ring
1413          * read pointer.
1414          */
1415         if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
1416             (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
1417                 DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
1418                 (void) radeon_do_cleanup_cp(dev);
1419                 return (EINVAL);
1420         }
1421 
1422         switch (init->fb_bpp) {
1423         case 16:
1424                 dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
1425                 break;
1426         case 32:
1427         default:
1428                 dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
1429                 break;
1430         }
1431         dev_priv->front_offset = init->front_offset;
1432         dev_priv->front_pitch = init->front_pitch;
1433         dev_priv->back_offset = init->back_offset;
1434         dev_priv->back_pitch = init->back_pitch;
1435 
1436         switch (init->depth_bpp) {
1437         case 16:
1438                 dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
1439                 break;
1440         case 32:
1441         default:
1442                 dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
1443                 break;
1444         }
1445         dev_priv->depth_offset = init->depth_offset;
1446         dev_priv->depth_pitch = init->depth_pitch;
1447 
1448         /*
1449          * Hardware state for depth clears.  Remove this if/when we no
1450          * longer clear the depth buffer with a 3D rectangle.  Hard-code
1451          * all values to prevent unwanted 3D state from slipping through
1452          * and screwing with the clear operation.
1453          */
1454         dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
1455             (dev_priv->color_fmt << 10) |
1456             (dev_priv->microcode_version ==
1457             UCODE_R100 ? RADEON_ZBLOCK16 : 0));
1458 
1459         dev_priv->depth_clear.rb3d_zstencilcntl =
1460             (dev_priv->depth_fmt |
1461             RADEON_Z_TEST_ALWAYS |
1462             RADEON_STENCIL_TEST_ALWAYS |
1463             RADEON_STENCIL_S_FAIL_REPLACE |
1464             RADEON_STENCIL_ZPASS_REPLACE |
1465             RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
1466 
1467         dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
1468             RADEON_BFACE_SOLID |
1469             RADEON_FFACE_SOLID |
1470             RADEON_FLAT_SHADE_VTX_LAST |
1471             RADEON_DIFFUSE_SHADE_FLAT |
1472             RADEON_ALPHA_SHADE_FLAT |
1473             RADEON_SPECULAR_SHADE_FLAT |
1474             RADEON_FOG_SHADE_FLAT |
1475             RADEON_VTX_PIX_CENTER_OGL |
1476             RADEON_ROUND_MODE_TRUNC |
1477             RADEON_ROUND_PREC_8TH_PIX);
1478 
1479         DRM_GETSAREA();
1480 
1481         dev_priv->ring_offset = init->ring_offset;
1482         dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1483         dev_priv->buffers_offset = init->buffers_offset;
1484         dev_priv->gart_textures_offset = init->gart_textures_offset;
1485 
1486         if (!dev_priv->sarea) {
1487                 DRM_ERROR("could not find sarea!\n");
1488                 (void) radeon_do_cleanup_cp(dev);
1489                 return (EINVAL);
1490         }
1491 
1492         dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
1493         if (!dev_priv->cp_ring) {
1494                 DRM_ERROR("could not find cp ring region, offset=0x%lx\n",
1495                     init->ring_offset);
1496                 (void) radeon_do_cleanup_cp(dev);
1497                 return (EINVAL);
1498         }
1499         dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
1500         if (!dev_priv->ring_rptr) {
1501                 DRM_ERROR("could not find ring read pointer, offset=0x%lx\n",
1502                     init->ring_rptr_offset);
1503                 (void) radeon_do_cleanup_cp(dev);
1504                 return (EINVAL);
1505         }
1506         dev->agp_buffer_token = init->buffers_offset;
1507         dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
1508         if (!dev->agp_buffer_map) {
1509                 DRM_ERROR("could not find dma buffer region, offset=0x%lx\n",
1510                     init->buffers_offset);
1511                 (void) radeon_do_cleanup_cp(dev);
1512                 return (EINVAL);
1513         }
1514 
1515         if (init->gart_textures_offset) {
1516                 dev_priv->gart_textures =
1517                     drm_core_findmap(dev, init->gart_textures_offset);
1518                 if (!dev_priv->gart_textures) {
1519                         DRM_ERROR("could not find GART texture region, "
1520                             "offset=0x%lx\n", init->gart_textures_offset);
1521                         (void) radeon_do_cleanup_cp(dev);
1522                         return (EINVAL);
1523                 }
1524         }
1525 
1526         dev_priv->sarea_priv = (drm_radeon_sarea_t *)(uintptr_t)
1527             ((u8 *)(uintptr_t)dev_priv->sarea->handle +
1528             init->sarea_priv_offset);
1529 
1530 #if __OS_HAS_AGP
1531         if (dev_priv->flags & RADEON_IS_AGP) {
1532                 drm_core_ioremap(dev_priv->cp_ring, dev);
1533                 drm_core_ioremap(dev_priv->ring_rptr, dev);
1534                 drm_core_ioremap(dev->agp_buffer_map, dev);
1535                 if (!dev_priv->cp_ring->handle ||
1536                     !dev_priv->ring_rptr->handle ||
1537                     !dev->agp_buffer_map->handle) {
1538                         DRM_ERROR("radeon_do_init_cp: failed to find agp "
1539                             "regions,"
1540                             "cp_ring=0x%x, ring_rptr=0x%x, agp_buf=0x%x",
1541                             dev_priv->cp_ring->handle,
1542                             dev_priv->ring_rptr->handle,
1543                             dev->agp_buffer_map->handle);
1544                         (void) radeon_do_cleanup_cp(dev);
1545                         return (EINVAL);
1546                 }
1547         } else
1548 #endif
1549         {
1550                 dev_priv->cp_ring->handle =
1551                     (void *)(intptr_t)dev_priv->cp_ring->offset;
1552                 dev_priv->ring_rptr->handle =
1553                     (void *)(intptr_t)dev_priv->ring_rptr->offset;
1554                 dev->agp_buffer_map->handle =
1555                     (void *)(intptr_t)dev->agp_buffer_map->offset;
1556 
1557                 DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
1558                     dev_priv->cp_ring->handle);
1559                 DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
1560                     dev_priv->ring_rptr->handle);
1561                 DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
1562                     dev->agp_buffer_map->handle);
1563         }
1564 
1565         dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) &
1566             0xffff) << 16;
1567         dev_priv->fb_size =
1568             ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
1569             - dev_priv->fb_location;
1570 
1571         dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
1572             ((dev_priv->front_offset + dev_priv->fb_location) >> 10));
1573 
1574         dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
1575             ((dev_priv->back_offset + dev_priv->fb_location) >> 10));
1576 
1577         dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
1578             ((dev_priv->depth_offset + dev_priv->fb_location) >> 10));
1579 
1580         dev_priv->gart_size = init->gart_size;
1581 
1582         /* New let's set the memory map ... */
1583         if (dev_priv->new_memmap) {
1584                 u32 base = 0;
1585 
1586                 DRM_INFO("Setting GART location based on new memory map\n");
1587 
1588                 /*
1589                  * If using AGP, try to locate the AGP aperture at the same
1590                  * location in the card and on the bus, though we have to
1591                  * align it down.
1592                  */
1593 #if __OS_HAS_AGP
1594                 if (dev_priv->flags & RADEON_IS_AGP) {
1595                         base = dev->agp->base;
1596                         /* Check if valid */
1597                         if ((base + dev_priv->gart_size - 1) >=
1598                             dev_priv->fb_location &&
1599                             base < (dev_priv->fb_location +
1600                             dev_priv->fb_size - 1)) {
1601                                 DRM_INFO("Can't use AGP base @0x%08lx,"
1602                                     "won't fit\n", dev->agp->base);
1603                                 base = 0;
1604                         }
1605                 }
1606 #endif
1607                 /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
1608                 if (base == 0) {
1609                         base = dev_priv->fb_location + dev_priv->fb_size;
1610                         if (base < dev_priv->fb_location ||
1611                             ((base + dev_priv->gart_size) &
1612                             0xfffffffful) < base)
1613                                 base = dev_priv->fb_location -
1614                                     dev_priv->gart_size;
1615                 }
1616                 dev_priv->gart_vm_start = base & 0xffc00000u;
1617                 if (dev_priv->gart_vm_start != base)
1618                         DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
1619                             base, dev_priv->gart_vm_start);
1620         } else {
1621                 DRM_INFO("Setting GART location based on old memory map\n");
1622                 dev_priv->gart_vm_start = dev_priv->fb_location +
1623                     RADEON_READ(RADEON_CONFIG_APER_SIZE);
1624         }
1625 
1626 #if __OS_HAS_AGP
1627         if (dev_priv->flags & RADEON_IS_AGP)
1628                 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset -
1629                     dev->agp->base + dev_priv->gart_vm_start);
1630         else
1631 #endif
1632                 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset -
1633                     (unsigned long)dev->sg->virtual + dev_priv->gart_vm_start);
1634 
1635         DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
1636         DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
1637         DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
1638             dev_priv->gart_buffers_offset);
1639 
1640         dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
1641         dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle +
1642             init->ring_size / sizeof (u32));
1643         dev_priv->ring.size = init->ring_size;
1644         dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
1645 
1646         dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof (u32)) - 1;
1647 
1648         dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
1649 
1650 #if __OS_HAS_AGP
1651         if (dev_priv->flags & RADEON_IS_AGP) {
1652                 /* Turn off PCI GART */
1653                 radeon_set_pcigart(dev_priv, 0);
1654         } else
1655 #endif
1656         {
1657                 /* if we have an offset set from userspace */
1658                 if (dev_priv->pcigart_offset) {
1659                         dev_priv->gart_info.bus_addr =
1660                             dev_priv->pcigart_offset + dev_priv->fb_location;
1661                         dev_priv->gart_info.mapping.offset =
1662                             dev_priv->gart_info.bus_addr;
1663                         dev_priv->gart_info.mapping.size =
1664                             RADEON_PCIGART_TABLE_SIZE;
1665 
1666                         drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
1667                         dev_priv->gart_info.addr =
1668                             dev_priv->gart_info.mapping.handle;
1669 
1670                         dev_priv->gart_info.is_pcie =
1671                             !!(dev_priv->flags & RADEON_IS_PCIE);
1672                         dev_priv->gart_info.gart_table_location =
1673                             DRM_ATI_GART_FB;
1674 
1675                         DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
1676                             dev_priv->gart_info.addr, dev_priv->pcigart_offset);
1677                 } else {
1678                         dev_priv->gart_info.gart_table_location =
1679                             DRM_ATI_GART_MAIN;
1680                         dev_priv->gart_info.addr = NULL;
1681                         dev_priv->gart_info.bus_addr = 0;
1682                         if (dev_priv->flags & RADEON_IS_PCIE) {
1683                                 DRM_ERROR("Cannot use PCI Express without "
1684                                     "GART in FB memory\n");
1685                                 (void) radeon_do_cleanup_cp(dev);
1686                                 return (EINVAL);
1687                         }
1688                 }
1689 
1690                 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
1691                         DRM_ERROR("failed to init PCI GART!\n");
1692                         (void) radeon_do_cleanup_cp(dev);
1693                         return (ENOMEM);
1694                 }
1695 
1696                 /* Turn on PCI GART */
1697                 radeon_set_pcigart(dev_priv, 1);
1698         }
1699 
1700         radeon_cp_load_microcode(dev_priv);
1701         radeon_cp_init_ring_buffer(dev, dev_priv);
1702 
1703         dev_priv->last_buf = 0;
1704 
1705         (void) radeon_do_engine_reset(dev);
1706         radeon_test_writeback(dev_priv);
1707 
1708         return (0);
1709 }
1710 
1711 static int radeon_do_cleanup_cp(drm_device_t *dev)
1712 {
1713         drm_radeon_private_t *dev_priv = dev->dev_private;
1714 
1715         /*
1716          * Make sure interrupts are disabled here because the uninstall ioctl
1717          * may not have been called from userspace and after dev_private
1718          * is freed, it's too late.
1719          */
1720         if (dev->irq_enabled)
1721                 (void) drm_irq_uninstall(dev);
1722 
1723 #if __OS_HAS_AGP
1724         if (dev_priv->flags & RADEON_IS_AGP) {
1725                 if (dev_priv->cp_ring != NULL) {
1726                         drm_core_ioremapfree(dev_priv->cp_ring, dev);
1727                         dev_priv->cp_ring = NULL;
1728                 }
1729                 if (dev_priv->ring_rptr != NULL) {
1730                         drm_core_ioremapfree(dev_priv->ring_rptr, dev);
1731                         dev_priv->ring_rptr = NULL;
1732                 }
1733                 if (dev->agp_buffer_map != NULL) {
1734                         drm_core_ioremapfree(dev->agp_buffer_map, dev);
1735                         dev->agp_buffer_map = NULL;
1736                 }
1737         } else
1738 #endif
1739         {
1740 
1741                 if (dev_priv->gart_info.bus_addr) {
1742                         /* Turn off PCI GART */
1743                         radeon_set_pcigart(dev_priv, 0);
1744                         if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
1745                                 DRM_ERROR("failed to cleanup PCI GART!\n");
1746                 }
1747 
1748                 if (dev_priv->gart_info.gart_table_location ==
1749                     DRM_ATI_GART_FB) {
1750                         drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
1751                         dev_priv->gart_info.addr = 0;
1752                 }
1753         }
1754         /* only clear to the start of flags */
1755         (void) memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
1756 
1757         return (0);
1758 }
1759 
1760 /*
1761  * This code will reinit the Radeon CP hardware after a resume from disc.
1762  * AFAIK, it would be very difficult to pickle the state at suspend time, so
1763  * here we make sure that all Radeon hardware initialisation is re-done without
1764  * affecting running applications.
1765  *
1766  * Charl P. Botha <http://cpbotha.net>
1767  */
1768 static int radeon_do_resume_cp(drm_device_t *dev)
1769 {
1770         drm_radeon_private_t *dev_priv = dev->dev_private;
1771 
1772         if (!dev_priv) {
1773                 DRM_ERROR("Called with no initialization\n");
1774                 return (EINVAL);
1775         }
1776 
1777         DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1778 
1779 #if __OS_HAS_AGP
1780         if (dev_priv->flags & RADEON_IS_AGP) {
1781                 /* Turn off PCI GART */
1782                 radeon_set_pcigart(dev_priv, 0);
1783         } else
1784 #endif
1785         {
1786                 /* Turn on PCI GART */
1787                 radeon_set_pcigart(dev_priv, 1);
1788         }
1789 
1790         radeon_cp_load_microcode(dev_priv);
1791         radeon_cp_init_ring_buffer(dev, dev_priv);
1792 
1793         (void) radeon_do_engine_reset(dev);
1794 
1795         DRM_DEBUG("radeon_do_resume_cp() complete\n");
1796 
1797         return (0);
1798 }
1799 
1800 /*ARGSUSED*/
1801 int
1802 radeon_cp_init(DRM_IOCTL_ARGS)
1803 {
1804         DRM_DEVICE;
1805         drm_radeon_init_t init;
1806 
1807 
1808         LOCK_TEST_WITH_RETURN(dev, fpriv);
1809 
1810 #ifdef _MULTI_DATAMODEL
1811         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
1812                 drm_radeon_init_32_t init32;
1813 
1814                 DRM_COPYFROM_WITH_RETURN(&init32, (void *) data,
1815                     sizeof (init32));
1816                 init.func = init32.func;
1817                 init.sarea_priv_offset = init32.sarea_priv_offset;
1818                 init.is_pci = init32.is_pci;
1819                 init.cp_mode = init32.cp_mode;
1820                 init.gart_size = init32.gart_size;
1821                 init.ring_size = init32.ring_size;
1822                 init.usec_timeout = init32.usec_timeout;
1823                 init.fb_bpp = init32.fb_bpp;
1824                 init.front_offset = init32.front_offset;
1825                 init.front_pitch = init32.front_pitch;
1826                 init.back_offset = init32.back_offset;
1827                 init.back_pitch = init32.back_pitch;
1828                 init.depth_bpp = init32.depth_bpp;
1829                 init.depth_offset = init32.depth_offset;
1830                 init.depth_pitch = init32.depth_pitch;
1831                 init.ring_offset = init32.ring_offset;
1832                 init.ring_rptr_offset = init32.ring_rptr_offset;
1833                 init.buffers_offset = init32.buffers_offset;
1834                 init.gart_textures_offset = init32.gart_textures_offset;
1835         } else {
1836 #endif
1837                 DRM_COPYFROM_WITH_RETURN(&init, (void *) data, sizeof (init));
1838 #ifdef _MULTI_DATAMODEL
1839         }
1840 #endif
1841 
1842         if (init.func == RADEON_INIT_R300_CP)
1843                 r300_init_reg_flags();
1844 
1845         switch (init.func) {
1846         case RADEON_INIT_CP:
1847         case RADEON_INIT_R200_CP:
1848         case RADEON_INIT_R300_CP:
1849                 return (radeon_do_init_cp(dev, &init));
1850         case RADEON_CLEANUP_CP:
1851                 return (radeon_do_cleanup_cp(dev));
1852         }
1853 
1854         return (EINVAL);
1855 }
1856 
1857 /*ARGSUSED*/
1858 int
1859 radeon_cp_start(DRM_IOCTL_ARGS)
1860 {
1861         DRM_DEVICE;
1862         drm_radeon_private_t *dev_priv = dev->dev_private;
1863 
1864         LOCK_TEST_WITH_RETURN(dev, fpriv);
1865 
1866         if (dev_priv->cp_running) {
1867                 return (0);
1868         }
1869         if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
1870                 DRM_DEBUG("called with bogus CP mode (%d)\n",
1871                     dev_priv->cp_mode);
1872                 return (0);
1873         }
1874 
1875         radeon_do_cp_start(dev_priv);
1876 
1877         return (0);
1878 }
1879 
1880 /*
1881  * Stop the CP.  The engine must have been idled before calling this
1882  * routine.
1883  */
1884 /*ARGSUSED*/
1885 int
1886 radeon_cp_stop(DRM_IOCTL_ARGS)
1887 {
1888         DRM_DEVICE;
1889         drm_radeon_private_t *dev_priv = dev->dev_private;
1890         drm_radeon_cp_stop_t stop;
1891         int ret;
1892 
1893         LOCK_TEST_WITH_RETURN(dev, fpriv);
1894 
1895         DRM_COPYFROM_WITH_RETURN(&stop, (void *) data, sizeof (stop));
1896 
1897         if (!dev_priv->cp_running)
1898                 return (0);
1899 
1900         /*
1901          * Flush any pending CP commands.  This ensures any outstanding
1902          * commands are exectuted by the engine before we turn it off.
1903          */
1904         if (stop.flush) {
1905                 radeon_do_cp_flush(dev_priv);
1906         }
1907 
1908         /*
1909          * If we fail to make the engine go idle, we return an error
1910          * code so that the DRM ioctl wrapper can try again.
1911          */
1912         if (stop.idle) {
1913                 ret = radeon_do_cp_idle(dev_priv);
1914                 if (ret)
1915                         return (ret);
1916         }
1917 
1918         /*
1919          * Finally, we can turn off the CP.  If the engine isn't idle,
1920          * we will get some dropped triangles as they won't be fully
1921          * rendered before the CP is shut down.
1922          */
1923         radeon_do_cp_stop(dev_priv);
1924 
1925         /* Reset the engine */
1926         (void) radeon_do_engine_reset(dev);
1927 
1928         return (0);
1929 }
1930 
1931 void
1932 radeon_do_release(drm_device_t *dev)
1933 {
1934         drm_radeon_private_t *dev_priv = dev->dev_private;
1935         int i, ret;
1936 
1937         if (dev_priv) {
1938                 if (dev_priv->cp_running) {
1939                         /* Stop the cp */
1940                         while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
1941                                 DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
1942 #ifdef __linux__
1943                                 schedule();
1944 #else
1945 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
1946                                 msleep(&ret, &dev->dev_lock, PZERO,
1947                                     "rdnrel", 1);
1948 #else
1949 #if defined(__SOLARIS__) || defined(sun)
1950                                 (void) drv_usectohz(5);
1951 #else
1952                                 tsleep(&ret, PZERO, "rdnrel", 1);
1953 #endif
1954 #endif
1955 #endif
1956                         }
1957                         radeon_do_cp_stop(dev_priv);
1958                         (void) radeon_do_engine_reset(dev);
1959                 }
1960 
1961                 /* Disable *all* interrupts */
1962                 /* remove this after permanent addmaps */
1963                 if (dev_priv->mmio)
1964                         RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
1965 
1966                 if (dev_priv->mmio) {        /* remove all surfaces */
1967                         for (i = 0; i < RADEON_MAX_SURFACES; i++) {
1968                                 RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
1969                                 RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
1970                                     16 * i, 0);
1971                                 RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
1972                                     16 * i, 0);
1973                         }
1974                 }
1975 
1976                 /* Free memory heap structures */
1977                 radeon_mem_takedown(&(dev_priv->gart_heap));
1978                 radeon_mem_takedown(&(dev_priv->fb_heap));
1979 
1980                 /* deallocate kernel resources */
1981                 (void) radeon_do_cleanup_cp(dev);
1982         }
1983 }
1984 
1985 /* Just reset the CP ring.  Called as part of an X Server engine reset. */
1986 /*ARGSUSED*/
1987 int
1988 radeon_cp_reset(DRM_IOCTL_ARGS)
1989 {
1990         DRM_DEVICE;
1991         drm_radeon_private_t *dev_priv = dev->dev_private;
1992 
1993         LOCK_TEST_WITH_RETURN(dev, fpriv);
1994 
1995         if (!dev_priv) {
1996                 DRM_DEBUG("radeon_cp_reset called before init done\n");
1997                 return (EINVAL);
1998         }
1999 
2000         radeon_do_cp_reset(dev_priv);
2001 
2002         /* The CP is no longer running after an engine reset */
2003         dev_priv->cp_running = 0;
2004 
2005         return (0);
2006 }
2007 
2008 /*ARGSUSED*/
2009 int
2010 radeon_cp_idle(DRM_IOCTL_ARGS)
2011 {
2012         DRM_DEVICE;
2013         drm_radeon_private_t *dev_priv = dev->dev_private;
2014 
2015         LOCK_TEST_WITH_RETURN(dev, fpriv);
2016 
2017         return (radeon_do_cp_idle(dev_priv));
2018 }
2019 
2020 /* Added by Charl P. Botha to call radeon_do_resume_cp(). */
2021 /*ARGSUSED*/
2022 int
2023 radeon_cp_resume(DRM_IOCTL_ARGS)
2024 {
2025         DRM_DEVICE;
2026 
2027         return (radeon_do_resume_cp(dev));
2028 }
2029 
2030 /*ARGSUSED*/
2031 int
2032 radeon_engine_reset(DRM_IOCTL_ARGS)
2033 {
2034         DRM_DEVICE;
2035 
2036         LOCK_TEST_WITH_RETURN(dev, fpriv);
2037 
2038         return (radeon_do_engine_reset(dev));
2039 }
2040 
2041 /*
2042  * Fullscreen mode
2043  */
2044 
2045 /* KW: Deprecated to say the least: */
2046 /*ARGSUSED*/
2047 int
2048 radeon_fullscreen(DRM_IOCTL_ARGS)
2049 {
2050         return (0);
2051 }
2052 
2053 /*
2054  * Freelist management
2055  */
2056 
2057 /*
2058  * Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
2059  *   bufs until freelist code is used.  Note this hides a problem with
2060  *   the scratch register * (used to keep track of last buffer
2061  *   completed) being written to before * the last buffer has actually
2062  *   completed rendering.
2063  *
2064  * KW:  It's also a good way to find free buffers quickly.
2065  *
2066  * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
2067  * sleep.  However, bugs in older versions of radeon_accel.c mean that
2068  * we essentially have to do this, else old clients will break.
2069  *
2070  * However, it does leave open a potential deadlock where all the
2071  * buffers are held by other clients, which can't release them because
2072  * they can't get the lock.
2073  */
2074 
2075 drm_buf_t *
2076 radeon_freelist_get(drm_device_t *dev)
2077 {
2078         drm_device_dma_t *dma = dev->dma;
2079         drm_radeon_private_t *dev_priv = dev->dev_private;
2080         drm_radeon_buf_priv_t *buf_priv;
2081         drm_buf_t *buf;
2082         int i, t;
2083         int start;
2084 
2085         if (++dev_priv->last_buf >= dma->buf_count)
2086                 dev_priv->last_buf = 0;
2087 
2088         start = dev_priv->last_buf;
2089 
2090         for (t = 0; t < dev_priv->usec_timeout; t++) {
2091                 u32 done_age = GET_SCRATCH(1);
2092                 DRM_DEBUG("done_age = %d\n", done_age);
2093                 for (i = start; i < dma->buf_count; i++) {
2094                         buf = dma->buflist[i];
2095                         buf_priv = buf->dev_private;
2096                         if (buf->filp == 0 || (buf->pending &&
2097                             buf_priv->age <= done_age)) {
2098                                 dev_priv->stats.requested_bufs++;
2099                                 buf->pending = 0;
2100                                 return (buf);
2101                         }
2102                         start = 0;
2103                 }
2104 
2105                 if (t) {
2106                         DRM_UDELAY(1);
2107                         dev_priv->stats.freelist_loops++;
2108                 }
2109         }
2110 
2111         DRM_DEBUG("returning NULL!\n");
2112         return (NULL);
2113 }
2114 
2115 #if 0
2116 drm_buf_t *
2117 radeon_freelist_get(drm_device_t *dev)
2118 {
2119         drm_device_dma_t *dma = dev->dma;
2120         drm_radeon_private_t *dev_priv = dev->dev_private;
2121         drm_radeon_buf_priv_t *buf_priv;
2122         drm_buf_t *buf;
2123         int i, t;
2124         int start;
2125         u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
2126 
2127         if (++dev_priv->last_buf >= dma->buf_count)
2128                 dev_priv->last_buf = 0;
2129 
2130         start = dev_priv->last_buf;
2131         dev_priv->stats.freelist_loops++;
2132 
2133         for (t = 0; t < 2; t++) {
2134                 for (i = start; i < dma->buf_count; i++) {
2135                         buf = dma->buflist[i];
2136                         buf_priv = buf->dev_private;
2137                         if (buf->filp == 0 || (buf->pending &&
2138                             buf_priv->age <= done_age)) {
2139                                 dev_priv->stats.requested_bufs++;
2140                                 buf->pending = 0;
2141                                 return (buf);
2142                         }
2143                 }
2144                 start = 0;
2145         }
2146 
2147         return (NULL);
2148 }
2149 #endif
2150 
2151 void
2152 radeon_freelist_reset(drm_device_t *dev)
2153 {
2154         drm_device_dma_t *dma = dev->dma;
2155         drm_radeon_private_t *dev_priv = dev->dev_private;
2156         int i;
2157 
2158         dev_priv->last_buf = 0;
2159         for (i = 0; i < dma->buf_count; i++) {
2160                 drm_buf_t *buf = dma->buflist[i];
2161                 drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
2162                 buf_priv->age = 0;
2163         }
2164 }
2165 
2166 /*
2167  * CP command submission
2168  */
2169 int
2170 radeon_wait_ring(drm_radeon_private_t *dev_priv, int n)
2171 {
2172         drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
2173         int i;
2174         u32 last_head = GET_RING_HEAD(dev_priv);
2175 
2176         for (i = 0; i < dev_priv->usec_timeout; i++) {
2177                 u32 head = GET_RING_HEAD(dev_priv);
2178 
2179                 ring->space = (head - ring->tail) * sizeof (u32);
2180                 if (ring->space <= 0)
2181                         ring->space += ring->size;
2182                 if (ring->space > n)
2183                         return (0);
2184 
2185                 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
2186 
2187                 if (head != last_head)
2188                         i = 0;
2189                 last_head = head;
2190 
2191                 DRM_UDELAY(1);
2192         }
2193 
2194         /* FIXME: This return value is ignored in the BEGIN_RING macro! */
2195 #if RADEON_FIFO_DEBUG
2196         cmn_err(CE_WARN, "radeon_wait_ring failed\n");
2197         radeon_status(dev_priv);
2198         DRM_ERROR("failed!\n");
2199 #endif
2200         return (EBUSY);
2201 }
2202 
2203 static int
2204 radeon_cp_get_buffers(drm_file_t *filp, drm_device_t *dev, drm_dma_t *d)
2205 {
2206         int i;
2207         drm_buf_t *buf;
2208 
2209         for (i = d->granted_count; i < d->request_count; i++) {
2210                 buf = radeon_freelist_get(dev);
2211                 if (!buf)
2212                         return (EBUSY); /* NOTE: broken client */
2213 
2214                 buf->filp = filp;
2215 
2216                 if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
2217                     sizeof (buf->idx)))
2218                         return (EFAULT);
2219                 if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
2220                     sizeof (buf->total)))
2221                         return (EFAULT);
2222 
2223                 d->granted_count++;
2224         }
2225         return (0);
2226 }
2227 
2228 /*ARGSUSED*/
2229 int
2230 radeon_cp_buffers(DRM_IOCTL_ARGS)
2231 {
2232         DRM_DEVICE;
2233         drm_device_dma_t *dma = dev->dma;
2234         int ret = 0;
2235         drm_dma_t d;
2236 
2237         LOCK_TEST_WITH_RETURN(dev, fpriv);
2238 
2239 #ifdef _MULTI_DATAMODEL
2240         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2241                 drm_dma_32_t    dma32;
2242 
2243                 DRM_COPYFROM_WITH_RETURN(&dma32, (void *)data, sizeof (dma32));
2244                 d.context = dma32.context;
2245                 d.send_count = dma32.send_count;
2246                 d.send_indices = (void *)(uintptr_t)dma32.send_indices;
2247                 d.send_sizes = (void *)(uintptr_t)dma32.send_sizes;
2248                 d.flags = dma32.flags;
2249                 d.request_count = dma32.request_count;
2250                 d.request_size = dma32.request_size;
2251                 d.request_indices = (void *)(uintptr_t)dma32.request_indices;
2252                 d.request_sizes = (void *)(uintptr_t)dma32.request_sizes;
2253                 d.granted_count = dma32.granted_count;
2254         } else {
2255 #endif
2256                 DRM_COPYFROM_WITH_RETURN(&d, (void *)data, sizeof (d));
2257 #ifdef _MULTI_DATAMODEL
2258         }
2259 #endif
2260         /* Please don't send us buffers. */
2261         if (d.send_count != 0) {
2262                 DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
2263                     DRM_CURRENTPID, d.send_count);
2264                 return (EINVAL);
2265         }
2266 
2267         /* We'll send you buffers. */
2268         if (d.request_count < 0 || d.request_count > dma->buf_count) {
2269                 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
2270                     DRM_CURRENTPID, d.request_count, dma->buf_count);
2271                 return (EINVAL);
2272         }
2273 
2274         d.granted_count = 0;
2275 
2276         if (d.request_count) {
2277                 ret = radeon_cp_get_buffers(fpriv, dev, &d);
2278         }
2279 
2280 #ifdef _MULTI_DATAMODEL
2281         if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
2282                 drm_dma_32_t    dma32;
2283 
2284                 dma32.context = d.context;
2285                 dma32.send_count = d.send_count;
2286                 dma32.send_indices = (uintptr_t)d.send_indices;
2287                 dma32.send_sizes = (uintptr_t)d.send_sizes;
2288                 dma32.flags = d.flags;
2289                 dma32.request_count = d.request_count;
2290                 dma32.request_size = d.request_size;
2291                 dma32.request_indices = (uintptr_t)d.request_indices;
2292                 dma32.request_sizes = (uintptr_t)d.request_sizes;
2293                 dma32.granted_count = d.granted_count;
2294                 DRM_COPYTO_WITH_RETURN((void *)data, &dma32, sizeof (dma32));
2295         } else {
2296 #endif
2297                 DRM_COPYTO_WITH_RETURN((void *)data, &d, sizeof (d));
2298 #ifdef _MULTI_DATAMODEL
2299         }
2300 #endif
2301         return (ret);
2302 }
2303 
2304 int
2305 radeon_driver_load(struct drm_device *dev, unsigned long flags)
2306 {
2307         drm_radeon_private_t *dev_priv;
2308         int ret = 0;
2309 
2310         dev_priv = drm_alloc(sizeof (drm_radeon_private_t), DRM_MEM_DRIVER);
2311         if (dev_priv == NULL)
2312                 return (ENOMEM);
2313 
2314         (void) memset(dev_priv, 0, sizeof (drm_radeon_private_t));
2315         dev->dev_private = (void *)dev_priv;
2316         dev_priv->flags = (int)flags;
2317 
2318         switch (flags & RADEON_FAMILY_MASK) {
2319         case CHIP_R100:
2320         case CHIP_RV200:
2321         case CHIP_R200:
2322         case CHIP_R300:
2323         case CHIP_R350:
2324         case CHIP_R420:
2325         case CHIP_RV410:
2326                 dev_priv->flags |= RADEON_HAS_HIERZ;
2327                 break;
2328         default:
2329                 /* all other chips have no hierarchical z buffer */
2330                 break;
2331         }
2332 
2333         if (drm_device_is_agp(dev))
2334                 dev_priv->flags |= RADEON_IS_AGP;
2335         else if (drm_device_is_pcie(dev))
2336                 dev_priv->flags |= RADEON_IS_PCIE;
2337         else
2338                 dev_priv->flags |= RADEON_IS_PCI;
2339 
2340         return (ret);
2341 }
2342 
2343 /*
2344  * Create mappings for registers and framebuffer so userland doesn't necessarily
2345  * have to find them.
2346  */
2347 int
2348 radeon_driver_firstopen(struct drm_device *dev)
2349 {
2350         int ret;
2351         drm_local_map_t *map;
2352         drm_radeon_private_t *dev_priv = dev->dev_private;
2353 
2354         /* dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; */
2355 
2356         ret = drm_addmap(dev, (uint_t)drm_get_resource_start(dev, 2),
2357             (uint_t)drm_get_resource_len(dev, 2), _DRM_REGISTERS,
2358             _DRM_READ_ONLY, &dev_priv->mmio);
2359 
2360         if (ret != 0) {
2361                 cmn_err(CE_WARN, "radeon_driver_firstopen: "
2362                     "failed to mmap BAR2 addr=0x%x, len=0x%x",
2363                     (uint_t)drm_get_resource_start(dev, 2),
2364                     (uint_t)drm_get_resource_len(dev, 2));
2365                 return (ret);
2366         }
2367 
2368         ret = drm_addmap(dev, (uint_t)drm_get_resource_start(dev, 0),
2369             (uint_t)drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
2370             _DRM_WRITE_COMBINING, &map);
2371         if (ret != 0)
2372                 return (ret);
2373 
2374         return (0);
2375 }
2376 
2377 int
2378 radeon_driver_unload(struct drm_device *dev)
2379 {
2380         drm_radeon_private_t *dev_priv = dev->dev_private;
2381 
2382         DRM_DEBUG("\n");
2383         drm_free(dev_priv, sizeof (*dev_priv), DRM_MEM_DRIVER);
2384 
2385         dev->dev_private = NULL;
2386         return (0);
2387 }