1*5d9d9091SRichard Lowe/* 2*5d9d9091SRichard Lowe * CDDL HEADER START 3*5d9d9091SRichard Lowe * 4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the 5*5d9d9091SRichard Lowe * Common Development and Distribution License, Version 1.0 only 6*5d9d9091SRichard Lowe * (the "License"). You may not use this file except in compliance 7*5d9d9091SRichard Lowe * with the License. 8*5d9d9091SRichard Lowe * 9*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing. 11*5d9d9091SRichard Lowe * See the License for the specific language governing permissions 12*5d9d9091SRichard Lowe * and limitations under the License. 13*5d9d9091SRichard Lowe * 14*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each 15*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the 17*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying 18*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner] 19*5d9d9091SRichard Lowe * 20*5d9d9091SRichard Lowe * CDDL HEADER END 21*5d9d9091SRichard Lowe */ 22*5d9d9091SRichard Lowe/* 23*5d9d9091SRichard Lowe * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*5d9d9091SRichard Lowe * Use is subject to license terms. 25*5d9d9091SRichard Lowe */ 26*5d9d9091SRichard Lowe 27*5d9d9091SRichard Lowe#ident "%Z%%M% %I% %E% SMI" 28*5d9d9091SRichard Lowe 29*5d9d9091SRichard Lowe/* 30*5d9d9091SRichard Lowe * This file contains no entry points which can be called directly from 31*5d9d9091SRichard Lowe * C and hence is of no interest to lint. However, we want to avoid the 32*5d9d9091SRichard Lowe * dreaded "Empty translation unit" warning. 33*5d9d9091SRichard Lowe */ 34*5d9d9091SRichard Lowe 35*5d9d9091SRichard Lowe#include <sys/asm_linkage.h> 36*5d9d9091SRichard Lowe#include <sys/fdreg.h> 37*5d9d9091SRichard Lowe#include <sys/fdvar.h> 38*5d9d9091SRichard Lowe#include "fd_assym.h" 39*5d9d9091SRichard Lowe 40*5d9d9091SRichard Lowe/* 41*5d9d9091SRichard Lowe * Since this is part of a Sparc "generic" module, it may be loaded during 42*5d9d9091SRichard Lowe * reconfigure time on systems that do not support the fast interrupt 43*5d9d9091SRichard Lowe * handler. On these machines the symbol "impl_setintreg_on" will be 44*5d9d9091SRichard Lowe * undefined but we don't want to cause error messages when we load. 45*5d9d9091SRichard Lowe */ 46*5d9d9091SRichard Lowe .weak impl_setintreg_on 47*5d9d9091SRichard Lowe .type impl_setintreg_on, #function 48*5d9d9091SRichard Lowe .weak fd_softintr_cookie 49*5d9d9091SRichard Lowe .type fd_softintr_cookie, #object 50*5d9d9091SRichard Lowe 51*5d9d9091SRichard Lowe#define Tmp2 %l4 /* temp register prior to dispatch to right opmode */ 52*5d9d9091SRichard Lowe#define Reg %l4 /* pointer to the chip's registers */ 53*5d9d9091SRichard Lowe#define Fdc %l3 /* pointer to fdctlr structure */ 54*5d9d9091SRichard Lowe#define Adr %l5 /* data address pointer */ 55*5d9d9091SRichard Lowe#define Len %l6 /* data length counter */ 56*5d9d9091SRichard Lowe#define Tmp %l7 /* general scratch */ 57*5d9d9091SRichard Lowe#define TRIGGER 0x33 58*5d9d9091SRichard Lowe ENTRY(fd_intr) ! fd standard interrupt handler 59*5d9d9091SRichard Lowe save %sp, -SA(MINFRAME), %sp 60*5d9d9091SRichard Lowe ! 61*5d9d9091SRichard Lowe ! Traverse the list of controllers until we find the first 62*5d9d9091SRichard Lowe ! controller expecting an interrupt. Unfortunately, the 63*5d9d9091SRichard Lowe ! 82072 floppy controller really doesn't have a way to tell 64*5d9d9091SRichard Lowe ! you that it is interrupting. 65*5d9d9091SRichard Lowe ! 66*5d9d9091SRichard Lowe set fdctlrs, Fdc ! load list of controllers 67*5d9d9091SRichard Lowe ldn [Fdc], Fdc ! get the first in the list... 68*5d9d9091SRichard Lowe1: tst Fdc ! do we have any more to check 69*5d9d9091SRichard Lowe bz .panic ! Nothing to service. Panic 70*5d9d9091SRichard Lowe nop 71*5d9d9091SRichard Lowe 72*5d9d9091SRichard Lowe3: ldub [Fdc + FD_OPMODE], Tmp2 ! load opmode into Tmp2 73*5d9d9091SRichard Lowe and Tmp2, 0x3, Tmp2 ! opmode must be 1, 2, or 3 74*5d9d9091SRichard Lowe tst Tmp2 ! non-zero? 75*5d9d9091SRichard Lowe bnz .mutex_enter ! yes! 76*5d9d9091SRichard Lowe nop 77*5d9d9091SRichard Lowe ldn [Fdc + FD_NEXT], Tmp ! Try next ctlr... 78*5d9d9091SRichard Lowe tst Tmp 79*5d9d9091SRichard Lowe bnz,a 1b 80*5d9d9091SRichard Lowe mov Tmp, Fdc 81*5d9d9091SRichard Lowe ! no more controllers 82*5d9d9091SRichard Lowe mov 0x2, Tmp2 ! must be spurious or "ready" int 83*5d9d9091SRichard Lowe.mutex_enter: 84*5d9d9091SRichard Lowe ! 85*5d9d9091SRichard Lowe ! grab high level mutex for this controller 86*5d9d9091SRichard Lowe ! 87*5d9d9091SRichard Lowe sethi %hi(asm_mutex_spin_enter), %l7 88*5d9d9091SRichard Lowe jmpl %l7 + %lo(asm_mutex_spin_enter), %l7 89*5d9d9091SRichard Lowe add Fdc, FD_HILOCK, %l6 90*5d9d9091SRichard Lowe ! 91*5d9d9091SRichard Lowe ! dispatch to correct handler 92*5d9d9091SRichard Lowe ! 93*5d9d9091SRichard Lowe cmp Tmp2, 3 !case 3: results ? 94*5d9d9091SRichard Lowe be,a .opmode3 ! yes... 95*5d9d9091SRichard Lowe ldn [Fdc + FD_REG], Reg ! load pointer to h/w registers 96*5d9d9091SRichard Lowe cmp Tmp2, 2 !case 2: seek/recalibrate ? 97*5d9d9091SRichard Lowe be .opmode2 ! yes.. 98*5d9d9091SRichard Lowe ldn [Fdc + FD_REG], Reg ! load pointer to h/w registers 99*5d9d9091SRichard Lowe ! 100*5d9d9091SRichard Lowe ! opmode 1: 101*5d9d9091SRichard Lowe ! read/write/format data-xfer case - they have a result phase 102*5d9d9091SRichard Lowe ! 103*5d9d9091SRichard Lowe.opmode1: 104*5d9d9091SRichard Lowe ld [Fdc + FD_RLEN], Len 105*5d9d9091SRichard Lowe ! 106*5d9d9091SRichard Lowe ! XXX- test for null raddr 107*5d9d9091SRichard Lowe ! 108*5d9d9091SRichard Lowe ldn [Fdc + FD_RADDR], Adr 109*5d9d9091SRichard Lowe 110*5d9d9091SRichard Lowe ! 111*5d9d9091SRichard Lowe ! while the fifo ready bit set, then data/status available 112*5d9d9091SRichard Lowe ! 113*5d9d9091SRichard Lowe1: ldub [Reg], Tmp ! get csr 114*5d9d9091SRichard Lowe andcc Tmp, RQM, %g0 ! 115*5d9d9091SRichard Lowe be 4f ! branch if bit clear 116*5d9d9091SRichard Lowe andcc Tmp, NDM, %g0 ! NDM set means data 117*5d9d9091SRichard Lowe be 7f ! if not set, it is status time 118*5d9d9091SRichard Lowe andcc Tmp, DIO, %g0 ! check for input vs. output data 119*5d9d9091SRichard Lowe be 2f ! 120*5d9d9091SRichard Lowe sub Len, 0x1, Len ! predecrement length... 121*5d9d9091SRichard Lowe ldub [Reg + 0x1], Tmp ! DIO set, *addr = *fifo 122*5d9d9091SRichard Lowe b 3f ! 123*5d9d9091SRichard Lowe stb Tmp, [Adr] ! 124*5d9d9091SRichard Lowe2: ldsb [Adr], Tmp ! *fifo = *addr 125*5d9d9091SRichard Lowe stb Tmp, [Reg + 0x1] ! 126*5d9d9091SRichard Lowe3: tst Len ! if (len == 0) send TC 127*5d9d9091SRichard Lowe bne 1b ! branch if not.... 128*5d9d9091SRichard Lowe add Adr, 0x1, Adr ! 129*5d9d9091SRichard Lowe b 6f ! 130*5d9d9091SRichard Lowe .empty ! 131*5d9d9091SRichard Lowe ! 132*5d9d9091SRichard Lowe ! save updated len, addr 133*5d9d9091SRichard Lowe ! 134*5d9d9091SRichard Lowe4: st Len, [Fdc + FD_RLEN] 135*5d9d9091SRichard Lowe b .out ! not done yet, return 136*5d9d9091SRichard Lowe stn Adr, [Fdc + FD_RADDR] 137*5d9d9091SRichard Lowe ! 138*5d9d9091SRichard Lowe ! END OF TRANSFER - if read/write, toggle the TC 139*5d9d9091SRichard Lowe ! bit in AUXIO_REG then save status and set state = 3. 140*5d9d9091SRichard Lowe ! 141*5d9d9091SRichard Lowe5: 142*5d9d9091SRichard Lowe ! 143*5d9d9091SRichard Lowe ! Stash len and addr before they get lost 144*5d9d9091SRichard Lowe ! 145*5d9d9091SRichard Lowe st Len, [Fdc + FD_RLEN] 146*5d9d9091SRichard Lowe6: stn Adr, [Fdc + FD_RADDR] 147*5d9d9091SRichard Lowe ! 148*5d9d9091SRichard Lowe ! Begin TC delay... 149*5d9d9091SRichard Lowe ! Old comment: 150*5d9d9091SRichard Lowe ! five nops provide 100ns of delay at 10MIPS to ensure 151*5d9d9091SRichard Lowe ! TC is wide enough at slowest possible floppy clock 152*5d9d9091SRichard Lowe ! (500ns @ 250Kbps). 153*5d9d9091SRichard Lowe ! 154*5d9d9091SRichard Lowe ! I gather this mean that we have to give 100ns delay for TC. 155*5d9d9091SRichard Lowe ! 156*5d9d9091SRichard Lowe ! At 100 Mips, that would be 1 * 10 (10) nops. 157*5d9d9091SRichard Lowe ! 158*5d9d9091SRichard Lowe 159*5d9d9091SRichard Lowe ldn [Fdc + FD_AUXIOVA], Adr 160*5d9d9091SRichard Lowe ldub [Fdc + FD_AUXIODATA], Tmp2 161*5d9d9091SRichard Lowe ldub [Adr], Tmp 162*5d9d9091SRichard Lowe or Tmp, Tmp2, Tmp 163*5d9d9091SRichard Lowe stb Tmp, [Adr] 164*5d9d9091SRichard Lowe nop; nop; nop; nop; nop; nop; nop; nop; nop; nop ! 10 nops 165*5d9d9091SRichard Lowe ! 166*5d9d9091SRichard Lowe ! End TC delay...now clear the TC bit 167*5d9d9091SRichard Lowe ! 168*5d9d9091SRichard Lowe ldub [Fdc + FD_AUXIODATA2], Tmp2 169*5d9d9091SRichard Lowe andn Tmp, Tmp2, Tmp 170*5d9d9091SRichard Lowe stb Tmp, [Adr] 171*5d9d9091SRichard Lowe 172*5d9d9091SRichard Lowe ! 173*5d9d9091SRichard Lowe ! set opmode to 3 to indicate going into status mode 174*5d9d9091SRichard Lowe ! 175*5d9d9091SRichard Lowe mov 3, Tmp 176*5d9d9091SRichard Lowe b .out 177*5d9d9091SRichard Lowe stb Tmp, [Fdc + FD_OPMODE] 178*5d9d9091SRichard Lowe ! 179*5d9d9091SRichard Lowe ! error status state: save old pointers, go direct to result snarfing 180*5d9d9091SRichard Lowe ! 181*5d9d9091SRichard Lowe7: st Len, [Fdc + FD_RLEN] 182*5d9d9091SRichard Lowe stn Adr, [Fdc + FD_RADDR] 183*5d9d9091SRichard Lowe mov 0x3, Tmp 184*5d9d9091SRichard Lowe b .opmode3 185*5d9d9091SRichard Lowe stb Tmp, [Fdc + FD_OPMODE] 186*5d9d9091SRichard Lowe ! 187*5d9d9091SRichard Lowe ! opmode 2: 188*5d9d9091SRichard Lowe ! recalibrate/seek - no result phase, must do sense interrupt status. 189*5d9d9091SRichard Lowe ! 190*5d9d9091SRichard Lowe.opmode2: 191*5d9d9091SRichard Lowe ldub [Reg], Tmp ! Tmp = *csr 192*5d9d9091SRichard Lowe1: andcc Tmp, CB, %g0 ! is CB set? 193*5d9d9091SRichard Lowe bne 1b ! yes, keep waiting 194*5d9d9091SRichard Lowe ldub [Reg], Tmp !! Tmp = *csr 195*5d9d9091SRichard Lowe ! 196*5d9d9091SRichard Lowe ! wait!!! should we check rqm first??? ABSOLUTELY YES!!!! 197*5d9d9091SRichard Lowe ! 198*5d9d9091SRichard Lowe1: andcc Tmp, RQM, %g0 ! 199*5d9d9091SRichard Lowe be,a 1b ! branch if bit clear 200*5d9d9091SRichard Lowe ldub [Reg], Tmp ! busy wait until RQM set 201*5d9d9091SRichard Lowe mov SNSISTAT, Tmp ! cmd for SENSE_INTERRUPT_STATUS 202*5d9d9091SRichard Lowe stb Tmp, [Reg + 0x1] 203*5d9d9091SRichard Lowe ! 204*5d9d9091SRichard Lowe ! NOTE: we ignore DIO here, assume it is set before RQM! 205*5d9d9091SRichard Lowe ! 206*5d9d9091SRichard Lowe ldub [Reg], Tmp ! busy wait until RQM set 207*5d9d9091SRichard Lowe1: andcc Tmp, RQM, Tmp 208*5d9d9091SRichard Lowe be,a 1b ! branch if bit clear 209*5d9d9091SRichard Lowe ldub [Reg], Tmp ! busy wait until RQM set 210*5d9d9091SRichard Lowe ! 211*5d9d9091SRichard Lowe ! fdc->c_csb.csb_rslt[0] = *fifo; 212*5d9d9091SRichard Lowe ! 213*5d9d9091SRichard Lowe ldub [Reg + 0x1], Tmp 214*5d9d9091SRichard Lowe stb Tmp, [Fdc + FD_RSLT] 215*5d9d9091SRichard Lowe ldub [Reg], Tmp ! busy wait until RQM set 216*5d9d9091SRichard Lowe1: andcc Tmp, RQM, Tmp 217*5d9d9091SRichard Lowe be,a 1b ! branch if bit clear 218*5d9d9091SRichard Lowe ldub [Reg], Tmp ! busy wait until RQM set 219*5d9d9091SRichard Lowe ! 220*5d9d9091SRichard Lowe ! fdc->c_csb.csb_rslt[1] = *fifo; 221*5d9d9091SRichard Lowe ! 222*5d9d9091SRichard Lowe ldub [Reg + 0x1], Tmp 223*5d9d9091SRichard Lowe b .notify 224*5d9d9091SRichard Lowe stb Tmp, [Fdc + FD_RSLT + 1] 225*5d9d9091SRichard Lowe ! 226*5d9d9091SRichard Lowe ! case 3: result mode 227*5d9d9091SRichard Lowe ! We are in result mode make sure all status bytes are read out 228*5d9d9091SRichard Lowe ! 229*5d9d9091SRichard Lowe ! We have to have *both* RQM and DIO set. 230*5d9d9091SRichard Lowe ! 231*5d9d9091SRichard Lowe.opmode3: 232*5d9d9091SRichard Lowe add Fdc, FD_RSLT, Adr ! load address of csb->csb_rslt 233*5d9d9091SRichard Lowe add Adr, 10, Len ! put an upper bound on it.. 234*5d9d9091SRichard Lowe ldub [Reg], Tmp ! 235*5d9d9091SRichard Lowe1: andcc Tmp, CB, %g0 ! is CB set? 236*5d9d9091SRichard Lowe be .notify ! no, jump around, must be done 237*5d9d9091SRichard Lowe andcc Tmp, RQM, %g0 ! check for RQM in delay slot 238*5d9d9091SRichard Lowe be,a 1b ! No RQM, go back 239*5d9d9091SRichard Lowe ldub [Reg], Tmp ! and load control reg in delay 240*5d9d9091SRichard Lowe andcc Tmp, DIO, %g0 ! DIO set? 241*5d9d9091SRichard Lowe be,a 1b ! No DIO, go back 242*5d9d9091SRichard Lowe ldub [Reg], Tmp ! and load control reg in delay 243*5d9d9091SRichard Lowe ! 244*5d9d9091SRichard Lowe ! CB && DIO && RQM all true. 245*5d9d9091SRichard Lowe ! Time to get a byte. 246*5d9d9091SRichard Lowe ! 247*5d9d9091SRichard Lowe ldub [Reg + 0x1], Tmp ! *fifo into Tmp 248*5d9d9091SRichard Lowe cmp Adr, Len ! already at our limit? 249*5d9d9091SRichard Lowe bge,a 1b ! Yes, go back.. 250*5d9d9091SRichard Lowe ldub [Reg], Tmp ! and load control reg in delay 251*5d9d9091SRichard Lowe stb Tmp, [Adr] ! store new byte 252*5d9d9091SRichard Lowe add Adr, 1, Adr ! increment address 253*5d9d9091SRichard Lowe b 1b ! and pop back to the top 254*5d9d9091SRichard Lowe ldub [Reg], Tmp ! and load control reg in delay 255*5d9d9091SRichard Lowe 256*5d9d9091SRichard Lowe ! 257*5d9d9091SRichard Lowe ! schedule 2nd stage interrupt 258*5d9d9091SRichard Lowe ! 259*5d9d9091SRichard Lowe.notify: 260*5d9d9091SRichard Lowe ! 261*5d9d9091SRichard Lowe ! if fast traps are enabled, use the platform dependent 262*5d9d9091SRichard Lowe ! impl_setintreg_on function. 263*5d9d9091SRichard Lowe ! 264*5d9d9091SRichard Lowe ldub [Fdc + FD_FASTTRAP], Tmp 265*5d9d9091SRichard Lowe tst Tmp 266*5d9d9091SRichard Lowe bnz .fast 267*5d9d9091SRichard Lowe nop 268*5d9d9091SRichard Lowe 269*5d9d9091SRichard Lowe ! 270*5d9d9091SRichard Lowe ! fast traps are not in use. Do not schedule the soft interrupt 271*5d9d9091SRichard Lowe ! at this time. Wait to trigger it at the end of the handler 272*5d9d9091SRichard Lowe ! when the mutexes have been released 273*5d9d9091SRichard Lowe ! 274*5d9d9091SRichard Lowe mov TRIGGER, Tmp2 275*5d9d9091SRichard Lowe b .out 276*5d9d9091SRichard Lowe nop 277*5d9d9091SRichard Lowe 278*5d9d9091SRichard Lowe ! 279*5d9d9091SRichard Lowe ! fast traps are enabled. Schedule the soft interrupt. 280*5d9d9091SRichard Lowe ! impl_setintreg uses %l4-%l7 281*5d9d9091SRichard Lowe ! 282*5d9d9091SRichard Lowe.fast: sethi %hi(fd_softintr_cookie), %l6 283*5d9d9091SRichard Lowe sethi %hi(impl_setintreg_on), %l7 284*5d9d9091SRichard Lowe jmpl %l7 + %lo(impl_setintreg_on), %l7 285*5d9d9091SRichard Lowe ld [%l6 + %lo(fd_softintr_cookie)], %l6 286*5d9d9091SRichard Lowe ! 287*5d9d9091SRichard Lowe ! set new opmode to 4 288*5d9d9091SRichard Lowe ! 289*5d9d9091SRichard Lowe mov 0x4, Tmp 290*5d9d9091SRichard Lowe stb Tmp, [Fdc + FD_OPMODE] 291*5d9d9091SRichard Lowe 292*5d9d9091SRichard Lowe ! 293*5d9d9091SRichard Lowe ! and fall through to exit 294*5d9d9091SRichard Lowe ! 295*5d9d9091SRichard Lowe.out: 296*5d9d9091SRichard Lowe ! 297*5d9d9091SRichard Lowe ! update high level interrupt counter... 298*5d9d9091SRichard Lowe ! 299*5d9d9091SRichard Lowe ldn [Fdc + FD_HIINTCT], Adr 300*5d9d9091SRichard Lowe tst Adr 301*5d9d9091SRichard Lowe be,a 1f 302*5d9d9091SRichard Lowe nop 303*5d9d9091SRichard Lowe ld [Adr], Tmp 304*5d9d9091SRichard Lowe inc Tmp 305*5d9d9091SRichard Lowe st Tmp, [Adr] 306*5d9d9091SRichard Lowe1: 307*5d9d9091SRichard Lowe ! 308*5d9d9091SRichard Lowe ! Release mutex 309*5d9d9091SRichard Lowe ! 310*5d9d9091SRichard Lowe sethi %hi(asm_mutex_spin_exit), %l7 311*5d9d9091SRichard Lowe jmpl %l7 + %lo(asm_mutex_spin_exit), %l7 312*5d9d9091SRichard Lowe add Fdc, FD_HILOCK, %l6 313*5d9d9091SRichard Lowe 314*5d9d9091SRichard Lowe ! 315*5d9d9091SRichard Lowe ! schedule the soft interrupt if needed 316*5d9d9091SRichard Lowe ! 317*5d9d9091SRichard Lowe cmp Tmp2, TRIGGER 318*5d9d9091SRichard Lowe bne .end 319*5d9d9091SRichard Lowe nop 320*5d9d9091SRichard Lowe 321*5d9d9091SRichard Lowe ! 322*5d9d9091SRichard Lowe ! set new opmode to 4 323*5d9d9091SRichard Lowe ! 324*5d9d9091SRichard Lowe mov 0x4, Tmp 325*5d9d9091SRichard Lowe stb Tmp, [Fdc + FD_OPMODE] 326*5d9d9091SRichard Lowe 327*5d9d9091SRichard Lowe ! invoke ddi_trigger_softintr. load 328*5d9d9091SRichard Lowe ! softid parameter in the delay slot 329*5d9d9091SRichard Lowe ! 330*5d9d9091SRichard Lowe call ddi_trigger_softintr 331*5d9d9091SRichard Lowe ldn [Fdc + FD_SOFTID], %o0 332*5d9d9091SRichard Lowe 333*5d9d9091SRichard Lowe.end: mov 1, %i0 334*5d9d9091SRichard Lowe ret 335*5d9d9091SRichard Lowe restore 336*5d9d9091SRichard Lowe SET_SIZE(fd_intr) 337*5d9d9091SRichard Lowe 338*5d9d9091SRichard Lowe.panic: 339*5d9d9091SRichard Lowe ! invoke a kernel panic 340*5d9d9091SRichard Lowe sethi %hi(panic_msg), %o1 341*5d9d9091SRichard Lowe ldn [%o1 + %lo(panic_msg)], %o1 342*5d9d9091SRichard Lowe mov 3, %o0 343*5d9d9091SRichard Lowe call cmn_err 344*5d9d9091SRichard Lowe nop 345*5d9d9091SRichard Lowe 346*5d9d9091SRichard Lowe 347